summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt16
-rw-r--r--CMakeModules/CopyYuzuQt5Deps.cmake3
-rw-r--r--appveyor.yml4
-rw-r--r--externals/CMakeLists.txt6
m---------externals/catch0
m---------externals/dynarmic0
-rw-r--r--externals/glad/include/glad/glad.h23
-rw-r--r--externals/glad/src/glad.c6385
m---------externals/mbedtls0
-rw-r--r--src/audio_core/CMakeLists.txt16
-rw-r--r--src/audio_core/algorithm/filter.cpp79
-rw-r--r--src/audio_core/algorithm/filter.h62
-rw-r--r--src/audio_core/algorithm/interpolate.cpp71
-rw-r--r--src/audio_core/algorithm/interpolate.h43
-rw-r--r--src/audio_core/audio_out.cpp10
-rw-r--r--src/audio_core/audio_out.h5
-rw-r--r--src/audio_core/audio_renderer.cpp249
-rw-r--r--src/audio_core/audio_renderer.h211
-rw-r--r--src/audio_core/buffer.h13
-rw-r--r--src/audio_core/codec.cpp77
-rw-r--r--src/audio_core/codec.h44
-rw-r--r--src/audio_core/cubeb_sink.cpp60
-rw-r--r--src/audio_core/cubeb_sink.h3
-rw-r--r--src/audio_core/null_sink.h6
-rw-r--r--src/audio_core/sink.h4
-rw-r--r--src/audio_core/sink_stream.h4
-rw-r--r--src/audio_core/stream.cpp26
-rw-r--r--src/audio_core/stream.h7
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/alignment.h4
-rw-r--r--src/common/bit_set.h2
-rw-r--r--src/common/break_points.cpp90
-rw-r--r--src/common/break_points.h49
-rw-r--r--src/common/color.h50
-rw-r--r--src/common/file_util.cpp16
-rw-r--r--src/common/file_util.h30
-rw-r--r--src/common/hash.h4
-rw-r--r--src/common/logging/backend.cpp14
-rw-r--r--src/common/logging/log.h9
-rw-r--r--src/common/thread_queue_list.h10
-rw-r--r--src/common/vector_math.h362
-rw-r--r--src/common/x64/xbyak_util.h2
-rw-r--r--src/core/CMakeLists.txt8
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp15
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp2
-rw-r--r--src/core/core.cpp43
-rw-r--r--src/core/core.h56
-rw-r--r--src/core/core_cpu.cpp4
-rw-r--r--src/core/core_cpu.h2
-rw-r--r--src/core/core_timing.cpp16
-rw-r--r--src/core/core_timing.h11
-rw-r--r--src/core/file_sys/card_image.cpp28
-rw-r--r--src/core/file_sys/card_image.h6
-rw-r--r--src/core/file_sys/content_archive.cpp116
-rw-r--r--src/core/file_sys/content_archive.h6
-rw-r--r--src/core/file_sys/control_metadata.h7
-rw-r--r--src/core/file_sys/directory.h12
-rw-r--r--src/core/file_sys/partition_filesystem.cpp8
-rw-r--r--src/core/file_sys/partition_filesystem.h2
-rw-r--r--src/core/file_sys/program_metadata.cpp12
-rw-r--r--src/core/file_sys/program_metadata.h2
-rw-r--r--src/core/file_sys/savedata_factory.h1
-rw-r--r--src/core/file_sys/vfs.cpp148
-rw-r--r--src/core/file_sys/vfs.h80
-rw-r--r--src/core/file_sys/vfs_offset.h3
-rw-r--r--src/core/file_sys/vfs_real.cpp341
-rw-r--r--src/core/file_sys/vfs_real.h56
-rw-r--r--src/core/file_sys/vfs_vector.h3
-rw-r--r--src/core/frontend/emu_window.cpp4
-rw-r--r--src/core/frontend/emu_window.h4
-rw-r--r--src/core/gdbstub/gdbstub.cpp174
-rw-r--r--src/core/gdbstub/gdbstub.h8
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp30
-rw-r--r--src/core/hle/kernel/client_port.cpp12
-rw-r--r--src/core/hle/kernel/client_port.h14
-rw-r--r--src/core/hle/kernel/event.h12
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp2
-rw-r--r--src/core/hle/kernel/hle_ipc.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/object.h15
-rw-r--r--src/core/hle/kernel/scheduler.cpp2
-rw-r--r--src/core/hle/kernel/scheduler.h2
-rw-r--r--src/core/hle/kernel/server_session.cpp10
-rw-r--r--src/core/hle/kernel/svc.cpp4
-rw-r--r--src/core/hle/kernel/thread.cpp32
-rw-r--r--src/core/hle/romfs.cpp102
-rw-r--r--src/core/hle/romfs.h22
-rw-r--r--src/core/hle/service/acc/acc.cpp30
-rw-r--r--src/core/hle/service/acc/acc.h1
-rw-r--r--src/core/hle/service/acc/acc_su.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp9
-rw-r--r--src/core/hle/service/am/am.h1
-rw-r--r--src/core/hle/service/apm/apm.cpp1
-rw-r--r--src/core/hle/service/apm/interface.cpp25
-rw-r--r--src/core/hle/service/apm/interface.h8
-rw-r--r--src/core/hle/service/audio/audout_a.cpp2
-rw-r--r--src/core/hle/service/audio/audout_u.cpp14
-rw-r--r--src/core/hle/service/audio/audout_u.h10
-rw-r--r--src/core/hle/service/audio/audren_u.cpp250
-rw-r--r--src/core/hle/service/audio/audren_u.h20
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp16
-rw-r--r--src/core/hle/service/filesystem/filesystem.h2
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp9
-rw-r--r--src/core/hle/service/friend/friend.cpp104
-rw-r--r--src/core/hle/service/hid/hid.cpp20
-rw-r--r--src/core/hle/service/mm/mm_u.cpp83
-rw-r--r--src/core/hle/service/mm/mm_u.h15
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp34
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h36
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp34
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h36
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp2
-rw-r--r--src/core/hle/service/nvdrv/interface.h1
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp13
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h8
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h3
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp14
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h17
-rw-r--r--src/core/hle/service/service.cpp8
-rw-r--r--src/core/hle/service/service.h7
-rw-r--r--src/core/hle/service/time/time.cpp4
-rw-r--r--src/core/hle/service/usb/usb.cpp238
-rw-r--r--src/core/hle/service/usb/usb.h15
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp85
-rw-r--r--src/core/loader/deconstructed_rom_directory.h11
-rw-r--r--src/core/loader/elf.cpp2
-rw-r--r--src/core/loader/loader.cpp55
-rw-r--r--src/core/loader/loader.h58
-rw-r--r--src/core/loader/nca.cpp56
-rw-r--r--src/core/loader/nca.h4
-rw-r--r--src/core/loader/nro.cpp10
-rw-r--r--src/core/loader/xci.cpp40
-rw-r--r--src/core/loader/xci.h5
-rw-r--r--src/core/memory.h23
-rw-r--r--src/core/perf_stats.cpp17
-rw-r--r--src/core/perf_stats.h8
-rw-r--r--src/core/settings.cpp6
-rw-r--r--src/tests/common/param_package.cpp2
-rw-r--r--src/tests/core/core_timing.cpp2
-rw-r--r--src/tests/glad.cpp2
-rw-r--r--src/tests/tests.cpp2
-rw-r--r--src/video_core/command_processor.cpp8
-rw-r--r--src/video_core/command_processor.h3
-rw-r--r--src/video_core/engines/maxwell_3d.cpp17
-rw-r--r--src/video_core/engines/maxwell_3d.h28
-rw-r--r--src/video_core/engines/shader_bytecode.h53
-rw-r--r--src/video_core/gpu.cpp51
-rw-r--r--src/video_core/gpu.h26
-rw-r--r--src/video_core/renderer_base.cpp19
-rw-r--r--src/video_core/renderer_base.h30
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp220
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h32
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp188
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h308
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp174
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_state.h10
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp201
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.h42
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h29
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp10
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h8
-rw-r--r--src/video_core/textures/decoders.cpp86
-rw-r--r--src/video_core/textures/decoders.h4
-rw-r--r--src/video_core/video_core.cpp4
-rw-r--r--src/video_core/video_core.h11
-rw-r--r--src/yuzu/CMakeLists.txt3
-rw-r--r--src/yuzu/about_dialog.cpp2
-rw-r--r--src/yuzu/about_dialog.h2
-rw-r--r--src/yuzu/bootmanager.h4
-rw-r--r--src/yuzu/configuration/config.cpp14
-rw-r--r--src/yuzu/configuration/configure.ui11
-rw-r--r--src/yuzu/configuration/configure_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.ui7
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp8
-rw-r--r--src/yuzu/configuration/configure_dialog.h4
-rw-r--r--src/yuzu/configuration/configure_gamelist.cpp63
-rw-r--r--src/yuzu/configuration/configure_gamelist.h28
-rw-r--r--src/yuzu/configuration/configure_gamelist.ui126
-rw-r--r--src/yuzu/configuration/configure_general.cpp6
-rw-r--r--src/yuzu/configuration/configure_general.h4
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp2
-rw-r--r--src/yuzu/configuration/configure_system.cpp2
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp9
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.h6
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
-rw-r--r--src/yuzu/debugger/wait_tree.h4
-rw-r--r--src/yuzu/game_list.cpp127
-rw-r--r--src/yuzu/game_list.h3
-rw-r--r--src/yuzu/game_list_p.h63
-rw-r--r--src/yuzu/hotkeys.cpp67
-rw-r--r--src/yuzu/hotkeys.h107
-rw-r--r--src/yuzu/main.cpp211
-rw-r--r--src/yuzu/main.h8
-rw-r--r--src/yuzu/ui_settings.h6
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h2
-rw-r--r--src/yuzu_cmd/yuzu.cpp25
210 files changed, 8026 insertions, 5510 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3639b623c..59c610732 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
-# CMake 3.6 required for FindBoost to define IMPORTED libs properly on unknown Boost versions
-cmake_minimum_required(VERSION 3.6)
+cmake_minimum_required(VERSION 3.7)
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
include(DownloadExternals)
@@ -66,10 +66,12 @@ if (NOT ENABLE_GENERIC)
detect_architecture("_M_AMD64" x86_64)
detect_architecture("_M_IX86" x86)
detect_architecture("_M_ARM" ARM)
+ detect_architecture("_M_ARM64" ARM64)
else()
detect_architecture("__x86_64__" x86_64)
detect_architecture("__i386__" x86)
detect_architecture("__arm__" ARM)
+ detect_architecture("__aarch64__" ARM64)
endif()
endif()
@@ -187,8 +189,8 @@ find_package(Threads REQUIRED)
if (ENABLE_SDL2)
if (YUZU_USE_BUNDLED_SDL2)
# Detect toolchain and platform
- if (MSVC14 AND ARCHITECTURE_x86_64)
- set(SDL2_VER "SDL2-2.0.5")
+ if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) AND ARCHITECTURE_x86_64)
+ set(SDL2_VER "SDL2-2.0.8")
else()
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
endif()
@@ -220,7 +222,7 @@ if (YUZU_USE_BUNDLED_UNICORN)
if (MSVC)
message(STATUS "unicorn not found, falling back to bundled")
# Detect toolchain and platform
- if (MSVC14 AND ARCHITECTURE_x86_64)
+ if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) AND ARCHITECTURE_x86_64)
set(UNICORN_VER "unicorn-yuzu")
else()
message(FATAL_ERROR "No bundled Unicorn binaries for your toolchain. Disable YUZU_USE_BUNDLED_UNICORN and provide your own.")
@@ -279,7 +281,7 @@ endif()
if (ENABLE_QT)
if (YUZU_USE_BUNDLED_QT)
- if (MSVC14 AND ARCHITECTURE_x86_64)
+ if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) AND ARCHITECTURE_x86_64)
set(QT_VER qt-5.10.0-msvc2015_64)
else()
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
@@ -303,7 +305,7 @@ endif()
# ======================================
IF (APPLE)
- FIND_LIBRARY(COCOA_LIBRARY Cocoa) # Umbrella framework for everything GUI-related
+ find_library(COCOA_LIBRARY Cocoa) # Umbrella framework for everything GUI-related
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake
index e4a9796c8..aaf80b77b 100644
--- a/CMakeModules/CopyYuzuQt5Deps.cmake
+++ b/CMakeModules/CopyYuzuQt5Deps.cmake
@@ -4,8 +4,10 @@ function(copy_yuzu_Qt5_deps target_dir)
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
+ set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(PLATFORMS ${DLL_DEST}platforms/)
set(STYLES ${DLL_DEST}styles/)
+ set(IMAGEFORMATS ${DLL_DEST}imageformats/)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
icudt*.dll
icuin*.dll
@@ -17,4 +19,5 @@ function(copy_yuzu_Qt5_deps target_dir)
)
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
+ windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} qjpeg$<$<CONFIG:Debug>:d>.*)
endfunction(copy_yuzu_Qt5_deps)
diff --git a/appveyor.yml b/appveyor.yml
index 17d1b5fee..a6f12b267 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -117,6 +117,7 @@ after_build:
mkdir $RELEASE_DIST
mkdir $RELEASE_DIST/platforms
mkdir $RELEASE_DIST/styles
+ mkdir $RELEASE_DIST/imageformats
# copy the compiled binaries and other release files to the release folder
Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
@@ -140,6 +141,9 @@ after_build:
# copy the qt windows vista style dll to platforms
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/styles/qwindowsvistastyle.dll" -force -destination "$RELEASE_DIST/styles"
+ # copy the qt jpeg imageformat dll to platforms
+ Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/imageformats/qjpeg.dll" -force -destination "$RELEASE_DIST/imageformats"
+
7z a -tzip $MINGW_BUILD_ZIP $RELEASE_DIST\*
7z a $MINGW_SEVENZIP $RELEASE_DIST
}
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 987d0142a..b6eb36f20 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -32,11 +32,11 @@ add_subdirectory(inih)
# lz4
set(LZ4_BUNDLED_MODE ON)
-add_subdirectory(lz4/contrib/cmake_unofficial)
+add_subdirectory(lz4/contrib/cmake_unofficial EXCLUDE_FROM_ALL)
target_include_directories(lz4_static INTERFACE ./lz4/lib)
# mbedtls
-add_subdirectory(mbedtls)
+add_subdirectory(mbedtls EXCLUDE_FROM_ALL)
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
# MicroProfile
@@ -62,5 +62,5 @@ target_include_directories(opus INTERFACE ./opus/include)
# Cubeb
if(ENABLE_CUBEB)
set(BUILD_TESTS OFF CACHE BOOL "")
- add_subdirectory(cubeb)
+ add_subdirectory(cubeb EXCLUDE_FROM_ALL)
endif()
diff --git a/externals/catch b/externals/catch
-Subproject d2a130f2433aeaca070e3e4d6298a80049d21cf
+Subproject 15cf3caaceb21172ea42a24e595a2eb58c3ec96
diff --git a/externals/dynarmic b/externals/dynarmic
-Subproject 4f96c63025af34c1490c59f6729497b9866ffa3
+Subproject 0118ee04f90faaff951989f3c2494bc6ffb70cf
diff --git a/externals/glad/include/glad/glad.h b/externals/glad/include/glad/glad.h
index 5f4b962d9..fd41dc702 100644
--- a/externals/glad/include/glad/glad.h
+++ b/externals/glad/include/glad/glad.h
@@ -1,6 +1,6 @@
/*
- OpenGL loader generated by glad 0.1.25 on Fri Jul 20 07:59:28 2018.
+ OpenGL loader generated by glad 0.1.26 on Tue Aug 7 08:21:50 2018.
Language/Generator: C/C++
Specification: gl
@@ -15,6 +15,7 @@
GL_AMD_debug_output,
GL_AMD_depth_clamp_separate,
GL_AMD_draw_buffers_blend,
+ GL_AMD_framebuffer_multisample_advanced,
GL_AMD_framebuffer_sample_positions,
GL_AMD_gcn_shader,
GL_AMD_gpu_shader_half_float,
@@ -600,7 +601,7 @@
Omit khrplatform: False
Commandline:
- --profile="core" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_3DFX_multisample,GL_3DFX_tbuffer,GL_3DFX_texture_compression_FXT1,GL_AMD_blend_minmax_factor,GL_AMD_conservative_depth,GL_AMD_debug_output,GL_AMD_depth_clamp_separate,GL_AMD_draw_buffers_blend,GL_AMD_framebuffer_sample_positions,GL_AMD_gcn_shader,GL_AMD_gpu_shader_half_float,GL_AMD_gpu_shader_int16,GL_AMD_gpu_shader_int64,GL_AMD_interleaved_elements,GL_AMD_multi_draw_indirect,GL_AMD_name_gen_delete,GL_AMD_occlusion_query_event,GL_AMD_performance_monitor,GL_AMD_pinned_memory,GL_AMD_query_buffer_object,GL_AMD_sample_positions,GL_AMD_seamless_cubemap_per_texture,GL_AMD_shader_atomic_counter_ops,GL_AMD_shader_ballot,GL_AMD_shader_explicit_vertex_parameter,GL_AMD_shader_gpu_shader_half_float_fetch,GL_AMD_shader_image_load_store_lod,GL_AMD_shader_stencil_export,GL_AMD_shader_trinary_minmax,GL_AMD_sparse_texture,GL_AMD_stencil_operation_extended,GL_AMD_texture_gather_bias_lod,GL_AMD_texture_texture4,GL_AMD_transform_feedback3_lines_triangles,GL_AMD_transform_feedback4,GL_AMD_vertex_shader_layer,GL_AMD_vertex_shader_tessellator,GL_AMD_vertex_shader_viewport_index,GL_APPLE_aux_depth_stencil,GL_APPLE_client_storage,GL_APPLE_element_array,GL_APPLE_fence,GL_APPLE_float_pixels,GL_APPLE_flush_buffer_range,GL_APPLE_object_purgeable,GL_APPLE_rgb_422,GL_APPLE_row_bytes,GL_APPLE_specular_vector,GL_APPLE_texture_range,GL_APPLE_transform_hint,GL_APPLE_vertex_array_object,GL_APPLE_vertex_array_range,GL_APPLE_vertex_program_evaluators,GL_APPLE_ycbcr_422,GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_arrays_of_arrays,GL_ARB_base_instance,GL_ARB_bindless_texture,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_cl_event,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_clip_control,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_conditional_render_inverted,GL_ARB_conservative_depth,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_cull_distance,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_derivative_control,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_imaging,GL_ARB_indirect_parameters,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_invalidate_subdata,GL_ARB_map_buffer_alignment,GL_ARB_map_buffer_range,GL_ARB_matrix_palette,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_parallel_shader_compile,GL_ARB_pipeline_statistics_query,GL_ARB_pixel_buffer_object,GL_ARB_point_parameters,GL_ARB_point_sprite,GL_ARB_polygon_offset_clamp,GL_ARB_post_depth_coverage,GL_ARB_program_interface_query,GL_ARB_provoking_vertex,GL_ARB_query_buffer_object,GL_ARB_robust_buffer_access_behavior,GL_ARB_robustness,GL_ARB_robustness_isolation,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_sampler_objects,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_separate_shader_objects,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_ballot,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_draw_parameters,GL_ARB_shader_group_vote,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_precision,GL_ARB_shader_stencil_export,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_subroutine,GL_ARB_shader_texture_image_samples,GL_ARB_shader_texture_lod,GL_ARB_shader_viewport_layer_array,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_shadow,GL_ARB_shadow_ambient,GL_ARB_sparse_buffer,GL_ARB_sparse_texture,GL_ARB_sparse_texture2,GL_ARB_sparse_texture_clamp,GL_ARB_spirv_extensions,GL_ARB_stencil_texturing,GL_ARB_sync,GL_ARB_tessellation_shader,GL_ARB_texture_barrier,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_buffer_range,GL_ARB_texture_compression,GL_ARB_texture_compression_bptc,GL_ARB_texture_compression_rgtc,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_env_combine,GL_ARB_texture_env_crossbar,GL_ARB_texture_env_dot3,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_gather,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_query_levels,GL_ARB_texture_query_lod,GL_ARB_texture_rectangle,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_texture_stencil8,GL_ARB_texture_storage,GL_ARB_texture_storage_multisample,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transform_feedback2,GL_ARB_transform_feedback3,GL_ARB_transform_feedback_instanced,GL_ARB_transform_feedback_overflow_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_64bit,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_blend,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_10f_11f_11f_rev,GL_ARB_vertex_type_2_10_10_10_rev,GL_ARB_viewport_array,GL_ARB_window_pos,GL_ATI_draw_buffers,GL_ATI_element_array,GL_ATI_envmap_bumpmap,GL_ATI_fragment_shader,GL_ATI_map_object_buffer,GL_ATI_meminfo,GL_ATI_pixel_format_float,GL_ATI_pn_triangles,GL_ATI_separate_stencil,GL_ATI_text_fragment_shader,GL_ATI_texture_env_combine3,GL_ATI_texture_float,GL_ATI_texture_mirror_once,GL_ATI_vertex_array_object,GL_ATI_vertex_attrib_array_object,GL_ATI_vertex_streams,GL_EXT_422_pixels,GL_EXT_EGL_image_storage,GL_EXT_abgr,GL_EXT_bgra,GL_EXT_bindable_uniform,GL_EXT_blend_color,GL_EXT_blend_equation_separate,GL_EXT_blend_func_separate,GL_EXT_blend_logic_op,GL_EXT_blend_minmax,GL_EXT_blend_subtract,GL_EXT_clip_volume_hint,GL_EXT_cmyka,GL_EXT_color_subtable,GL_EXT_compiled_vertex_array,GL_EXT_convolution,GL_EXT_coordinate_frame,GL_EXT_copy_texture,GL_EXT_cull_vertex,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_depth_bounds_test,GL_EXT_direct_state_access,GL_EXT_draw_buffers2,GL_EXT_draw_instanced,GL_EXT_draw_range_elements,GL_EXT_external_buffer,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_program_parameters,GL_EXT_gpu_shader4,GL_EXT_histogram,GL_EXT_index_array_formats,GL_EXT_index_func,GL_EXT_index_material,GL_EXT_index_texture,GL_EXT_light_texture,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_memory_object_win32,GL_EXT_misc_attribute,GL_EXT_multi_draw_arrays,GL_EXT_multisample,GL_EXT_packed_depth_stencil,GL_EXT_packed_float,GL_EXT_packed_pixels,GL_EXT_paletted_texture,GL_EXT_pixel_buffer_object,GL_EXT_pixel_transform,GL_EXT_pixel_transform_color_table,GL_EXT_point_parameters,GL_EXT_polygon_offset,GL_EXT_polygon_offset_clamp,GL_EXT_post_depth_coverage,GL_EXT_provoking_vertex,GL_EXT_raster_multisample,GL_EXT_rescale_normal,GL_EXT_secondary_color,GL_EXT_semaphore,GL_EXT_semaphore_fd,GL_EXT_semaphore_win32,GL_EXT_separate_shader_objects,GL_EXT_separate_specular_color,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_framebuffer_fetch_non_coherent,GL_EXT_shader_image_load_formatted,GL_EXT_shader_image_load_store,GL_EXT_shader_integer_mix,GL_EXT_shadow_funcs,GL_EXT_shared_texture_palette,GL_EXT_sparse_texture2,GL_EXT_stencil_clear_tag,GL_EXT_stencil_two_side,GL_EXT_stencil_wrap,GL_EXT_subtexture,GL_EXT_texture,GL_EXT_texture3D,GL_EXT_texture_array,GL_EXT_texture_buffer_object,GL_EXT_texture_compression_latc,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_cube_map,GL_EXT_texture_env_add,GL_EXT_texture_env_combine,GL_EXT_texture_env_dot3,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_filter_minmax,GL_EXT_texture_integer,GL_EXT_texture_lod_bias,GL_EXT_texture_mirror_clamp,GL_EXT_texture_object,GL_EXT_texture_perturb_normal,GL_EXT_texture_sRGB,GL_EXT_texture_sRGB_decode,GL_EXT_texture_shared_exponent,GL_EXT_texture_snorm,GL_EXT_texture_swizzle,GL_EXT_timer_query,GL_EXT_transform_feedback,GL_EXT_vertex_array,GL_EXT_vertex_array_bgra,GL_EXT_vertex_attrib_64bit,GL_EXT_vertex_shader,GL_EXT_vertex_weighting,GL_EXT_win32_keyed_mutex,GL_EXT_window_rectangles,GL_EXT_x11_sync_object,GL_GREMEDY_frame_terminator,GL_GREMEDY_string_marker,GL_HP_convolution_border_modes,GL_HP_image_transform,GL_HP_occlusion_test,GL_HP_texture_lighting,GL_IBM_cull_vertex,GL_IBM_multimode_draw_arrays,GL_IBM_rasterpos_clip,GL_IBM_static_data,GL_IBM_texture_mirrored_repeat,GL_IBM_vertex_array_lists,GL_INGR_blend_func_separate,GL_INGR_color_clamp,GL_INGR_interlace_read,GL_INTEL_blackhole_render,GL_INTEL_conservative_rasterization,GL_INTEL_fragment_shader_ordering,GL_INTEL_framebuffer_CMAA,GL_INTEL_map_texture,GL_INTEL_parallel_arrays,GL_INTEL_performance_query,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_context_flush_control,GL_KHR_debug,GL_KHR_no_error,GL_KHR_parallel_shader_compile,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_MESAX_texture_stack,GL_MESA_pack_invert,GL_MESA_program_binary_formats,GL_MESA_resize_buffers,GL_MESA_shader_integer_functions,GL_MESA_tile_raster_order,GL_MESA_window_pos,GL_MESA_ycbcr_texture,GL_NVX_blend_equation_advanced_multi_draw_buffers,GL_NVX_conditional_render,GL_NVX_gpu_memory_info,GL_NVX_linked_gpu_multicast,GL_NV_alpha_to_coverage_dither_control,GL_NV_bindless_multi_draw_indirect,GL_NV_bindless_multi_draw_indirect_count,GL_NV_bindless_texture,GL_NV_blend_equation_advanced,GL_NV_blend_equation_advanced_coherent,GL_NV_blend_minmax_factor,GL_NV_blend_square,GL_NV_clip_space_w_scaling,GL_NV_command_list,GL_NV_compute_program5,GL_NV_conditional_render,GL_NV_conservative_raster,GL_NV_conservative_raster_dilate,GL_NV_conservative_raster_pre_snap,GL_NV_conservative_raster_pre_snap_triangles,GL_NV_conservative_raster_underestimation,GL_NV_copy_depth_to_color,GL_NV_copy_image,GL_NV_deep_texture3D,GL_NV_depth_buffer_float,GL_NV_depth_clamp,GL_NV_draw_texture,GL_NV_draw_vulkan_image,GL_NV_evaluators,GL_NV_explicit_multisample,GL_NV_fence,GL_NV_fill_rectangle,GL_NV_float_buffer,GL_NV_fog_distance,GL_NV_fragment_coverage_to_color,GL_NV_fragment_program,GL_NV_fragment_program2,GL_NV_fragment_program4,GL_NV_fragment_program_option,GL_NV_fragment_shader_interlock,GL_NV_framebuffer_mixed_samples,GL_NV_framebuffer_multisample_coverage,GL_NV_geometry_program4,GL_NV_geometry_shader4,GL_NV_geometry_shader_passthrough,GL_NV_gpu_multicast,GL_NV_gpu_program4,GL_NV_gpu_program5,GL_NV_gpu_program5_mem_extended,GL_NV_gpu_shader5,GL_NV_half_float,GL_NV_internalformat_sample_query,GL_NV_light_max_exponent,GL_NV_multisample_coverage,GL_NV_multisample_filter_hint,GL_NV_occlusion_query,GL_NV_packed_depth_stencil,GL_NV_parameter_buffer_object,GL_NV_parameter_buffer_object2,GL_NV_path_rendering,GL_NV_path_rendering_shared_edge,GL_NV_pixel_data_range,GL_NV_point_sprite,GL_NV_present_video,GL_NV_primitive_restart,GL_NV_query_resource,GL_NV_query_resource_tag,GL_NV_register_combiners,GL_NV_register_combiners2,GL_NV_robustness_video_memory_purge,GL_NV_sample_locations,GL_NV_sample_mask_override_coverage,GL_NV_shader_atomic_counters,GL_NV_shader_atomic_float,GL_NV_shader_atomic_float64,GL_NV_shader_atomic_fp16_vector,GL_NV_shader_atomic_int64,GL_NV_shader_buffer_load,GL_NV_shader_buffer_store,GL_NV_shader_storage_buffer_object,GL_NV_shader_thread_group,GL_NV_shader_thread_shuffle,GL_NV_stereo_view_rendering,GL_NV_tessellation_program5,GL_NV_texgen_emboss,GL_NV_texgen_reflection,GL_NV_texture_barrier,GL_NV_texture_compression_vtc,GL_NV_texture_env_combine4,GL_NV_texture_expand_normal,GL_NV_texture_multisample,GL_NV_texture_rectangle,GL_NV_texture_rectangle_compressed,GL_NV_texture_shader,GL_NV_texture_shader2,GL_NV_texture_shader3,GL_NV_transform_feedback,GL_NV_transform_feedback2,GL_NV_uniform_buffer_unified_memory,GL_NV_vdpau_interop,GL_NV_vertex_array_range,GL_NV_vertex_array_range2,GL_NV_vertex_attrib_integer_64bit,GL_NV_vertex_buffer_unified_memory,GL_NV_vertex_program,GL_NV_vertex_program1_1,GL_NV_vertex_program2,GL_NV_vertex_program2_option,GL_NV_vertex_program3,GL_NV_vertex_program4,GL_NV_video_capture,GL_NV_viewport_array2,GL_NV_viewport_swizzle,GL_OES_byte_coordinates,GL_OES_compressed_paletted_texture,GL_OES_fixed_point,GL_OES_query_matrix,GL_OES_read_format,GL_OES_single_precision,GL_OML_interlace,GL_OML_resample,GL_OML_subsample,GL_OVR_multiview,GL_OVR_multiview2,GL_PGI_misc_hints,GL_PGI_vertex_hints,GL_REND_screen_coordinates,GL_S3_s3tc,GL_SGIS_detail_texture,GL_SGIS_fog_function,GL_SGIS_generate_mipmap,GL_SGIS_multisample,GL_SGIS_pixel_texture,GL_SGIS_point_line_texgen,GL_SGIS_point_parameters,GL_SGIS_sharpen_texture,GL_SGIS_texture4D,GL_SGIS_texture_border_clamp,GL_SGIS_texture_color_mask,GL_SGIS_texture_edge_clamp,GL_SGIS_texture_filter4,GL_SGIS_texture_lod,GL_SGIS_texture_select,GL_SGIX_async,GL_SGIX_async_histogram,GL_SGIX_async_pixel,GL_SGIX_blend_alpha_minmax,GL_SGIX_calligraphic_fragment,GL_SGIX_clipmap,GL_SGIX_convolution_accuracy,GL_SGIX_depth_pass_instrument,GL_SGIX_depth_texture,GL_SGIX_flush_raster,GL_SGIX_fog_offset,GL_SGIX_fragment_lighting,GL_SGIX_framezoom,GL_SGIX_igloo_interface,GL_SGIX_instruments,GL_SGIX_interlace,GL_SGIX_ir_instrument1,GL_SGIX_list_priority,GL_SGIX_pixel_texture,GL_SGIX_pixel_tiles,GL_SGIX_polynomial_ffd,GL_SGIX_reference_plane,GL_SGIX_resample,GL_SGIX_scalebias_hint,GL_SGIX_shadow,GL_SGIX_shadow_ambient,GL_SGIX_sprite,GL_SGIX_subsample,GL_SGIX_tag_sample_buffer,GL_SGIX_texture_add_env,GL_SGIX_texture_coordinate_clamp,GL_SGIX_texture_lod_bias,GL_SGIX_texture_multi_buffer,GL_SGIX_texture_scale_bias,GL_SGIX_vertex_preclip,GL_SGIX_ycrcb,GL_SGIX_ycrcb_subsample,GL_SGIX_ycrcba,GL_SGI_color_matrix,GL_SGI_color_table,GL_SGI_texture_color_table,GL_SUNX_constant_data,GL_SUN_convolution_border_modes,GL_SUN_global_alpha,GL_SUN_mesh_array,GL_SUN_slice_accum,GL_SUN_triangle_list,GL_SUN_vertex,GL_WIN_phong_shading,GL_WIN_specular_fog"
+ --profile="core" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_3DFX_multisample,GL_3DFX_tbuffer,GL_3DFX_texture_compression_FXT1,GL_AMD_blend_minmax_factor,GL_AMD_conservative_depth,GL_AMD_debug_output,GL_AMD_depth_clamp_separate,GL_AMD_draw_buffers_blend,GL_AMD_framebuffer_multisample_advanced,GL_AMD_framebuffer_sample_positions,GL_AMD_gcn_shader,GL_AMD_gpu_shader_half_float,GL_AMD_gpu_shader_int16,GL_AMD_gpu_shader_int64,GL_AMD_interleaved_elements,GL_AMD_multi_draw_indirect,GL_AMD_name_gen_delete,GL_AMD_occlusion_query_event,GL_AMD_performance_monitor,GL_AMD_pinned_memory,GL_AMD_query_buffer_object,GL_AMD_sample_positions,GL_AMD_seamless_cubemap_per_texture,GL_AMD_shader_atomic_counter_ops,GL_AMD_shader_ballot,GL_AMD_shader_explicit_vertex_parameter,GL_AMD_shader_gpu_shader_half_float_fetch,GL_AMD_shader_image_load_store_lod,GL_AMD_shader_stencil_export,GL_AMD_shader_trinary_minmax,GL_AMD_sparse_texture,GL_AMD_stencil_operation_extended,GL_AMD_texture_gather_bias_lod,GL_AMD_texture_texture4,GL_AMD_transform_feedback3_lines_triangles,GL_AMD_transform_feedback4,GL_AMD_vertex_shader_layer,GL_AMD_vertex_shader_tessellator,GL_AMD_vertex_shader_viewport_index,GL_APPLE_aux_depth_stencil,GL_APPLE_client_storage,GL_APPLE_element_array,GL_APPLE_fence,GL_APPLE_float_pixels,GL_APPLE_flush_buffer_range,GL_APPLE_object_purgeable,GL_APPLE_rgb_422,GL_APPLE_row_bytes,GL_APPLE_specular_vector,GL_APPLE_texture_range,GL_APPLE_transform_hint,GL_APPLE_vertex_array_object,GL_APPLE_vertex_array_range,GL_APPLE_vertex_program_evaluators,GL_APPLE_ycbcr_422,GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_arrays_of_arrays,GL_ARB_base_instance,GL_ARB_bindless_texture,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_cl_event,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_clip_control,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_conditional_render_inverted,GL_ARB_conservative_depth,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_cull_distance,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_derivative_control,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_imaging,GL_ARB_indirect_parameters,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_invalidate_subdata,GL_ARB_map_buffer_alignment,GL_ARB_map_buffer_range,GL_ARB_matrix_palette,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_parallel_shader_compile,GL_ARB_pipeline_statistics_query,GL_ARB_pixel_buffer_object,GL_ARB_point_parameters,GL_ARB_point_sprite,GL_ARB_polygon_offset_clamp,GL_ARB_post_depth_coverage,GL_ARB_program_interface_query,GL_ARB_provoking_vertex,GL_ARB_query_buffer_object,GL_ARB_robust_buffer_access_behavior,GL_ARB_robustness,GL_ARB_robustness_isolation,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_sampler_objects,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_separate_shader_objects,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_ballot,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_draw_parameters,GL_ARB_shader_group_vote,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_precision,GL_ARB_shader_stencil_export,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_subroutine,GL_ARB_shader_texture_image_samples,GL_ARB_shader_texture_lod,GL_ARB_shader_viewport_layer_array,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_shadow,GL_ARB_shadow_ambient,GL_ARB_sparse_buffer,GL_ARB_sparse_texture,GL_ARB_sparse_texture2,GL_ARB_sparse_texture_clamp,GL_ARB_spirv_extensions,GL_ARB_stencil_texturing,GL_ARB_sync,GL_ARB_tessellation_shader,GL_ARB_texture_barrier,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_buffer_range,GL_ARB_texture_compression,GL_ARB_texture_compression_bptc,GL_ARB_texture_compression_rgtc,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_env_combine,GL_ARB_texture_env_crossbar,GL_ARB_texture_env_dot3,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_gather,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_query_levels,GL_ARB_texture_query_lod,GL_ARB_texture_rectangle,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_texture_stencil8,GL_ARB_texture_storage,GL_ARB_texture_storage_multisample,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transform_feedback2,GL_ARB_transform_feedback3,GL_ARB_transform_feedback_instanced,GL_ARB_transform_feedback_overflow_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_64bit,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_blend,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_10f_11f_11f_rev,GL_ARB_vertex_type_2_10_10_10_rev,GL_ARB_viewport_array,GL_ARB_window_pos,GL_ATI_draw_buffers,GL_ATI_element_array,GL_ATI_envmap_bumpmap,GL_ATI_fragment_shader,GL_ATI_map_object_buffer,GL_ATI_meminfo,GL_ATI_pixel_format_float,GL_ATI_pn_triangles,GL_ATI_separate_stencil,GL_ATI_text_fragment_shader,GL_ATI_texture_env_combine3,GL_ATI_texture_float,GL_ATI_texture_mirror_once,GL_ATI_vertex_array_object,GL_ATI_vertex_attrib_array_object,GL_ATI_vertex_streams,GL_EXT_422_pixels,GL_EXT_EGL_image_storage,GL_EXT_abgr,GL_EXT_bgra,GL_EXT_bindable_uniform,GL_EXT_blend_color,GL_EXT_blend_equation_separate,GL_EXT_blend_func_separate,GL_EXT_blend_logic_op,GL_EXT_blend_minmax,GL_EXT_blend_subtract,GL_EXT_clip_volume_hint,GL_EXT_cmyka,GL_EXT_color_subtable,GL_EXT_compiled_vertex_array,GL_EXT_convolution,GL_EXT_coordinate_frame,GL_EXT_copy_texture,GL_EXT_cull_vertex,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_depth_bounds_test,GL_EXT_direct_state_access,GL_EXT_draw_buffers2,GL_EXT_draw_instanced,GL_EXT_draw_range_elements,GL_EXT_external_buffer,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_program_parameters,GL_EXT_gpu_shader4,GL_EXT_histogram,GL_EXT_index_array_formats,GL_EXT_index_func,GL_EXT_index_material,GL_EXT_index_texture,GL_EXT_light_texture,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_memory_object_win32,GL_EXT_misc_attribute,GL_EXT_multi_draw_arrays,GL_EXT_multisample,GL_EXT_packed_depth_stencil,GL_EXT_packed_float,GL_EXT_packed_pixels,GL_EXT_paletted_texture,GL_EXT_pixel_buffer_object,GL_EXT_pixel_transform,GL_EXT_pixel_transform_color_table,GL_EXT_point_parameters,GL_EXT_polygon_offset,GL_EXT_polygon_offset_clamp,GL_EXT_post_depth_coverage,GL_EXT_provoking_vertex,GL_EXT_raster_multisample,GL_EXT_rescale_normal,GL_EXT_secondary_color,GL_EXT_semaphore,GL_EXT_semaphore_fd,GL_EXT_semaphore_win32,GL_EXT_separate_shader_objects,GL_EXT_separate_specular_color,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_framebuffer_fetch_non_coherent,GL_EXT_shader_image_load_formatted,GL_EXT_shader_image_load_store,GL_EXT_shader_integer_mix,GL_EXT_shadow_funcs,GL_EXT_shared_texture_palette,GL_EXT_sparse_texture2,GL_EXT_stencil_clear_tag,GL_EXT_stencil_two_side,GL_EXT_stencil_wrap,GL_EXT_subtexture,GL_EXT_texture,GL_EXT_texture3D,GL_EXT_texture_array,GL_EXT_texture_buffer_object,GL_EXT_texture_compression_latc,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_cube_map,GL_EXT_texture_env_add,GL_EXT_texture_env_combine,GL_EXT_texture_env_dot3,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_filter_minmax,GL_EXT_texture_integer,GL_EXT_texture_lod_bias,GL_EXT_texture_mirror_clamp,GL_EXT_texture_object,GL_EXT_texture_perturb_normal,GL_EXT_texture_sRGB,GL_EXT_texture_sRGB_decode,GL_EXT_texture_shared_exponent,GL_EXT_texture_snorm,GL_EXT_texture_swizzle,GL_EXT_timer_query,GL_EXT_transform_feedback,GL_EXT_vertex_array,GL_EXT_vertex_array_bgra,GL_EXT_vertex_attrib_64bit,GL_EXT_vertex_shader,GL_EXT_vertex_weighting,GL_EXT_win32_keyed_mutex,GL_EXT_window_rectangles,GL_EXT_x11_sync_object,GL_GREMEDY_frame_terminator,GL_GREMEDY_string_marker,GL_HP_convolution_border_modes,GL_HP_image_transform,GL_HP_occlusion_test,GL_HP_texture_lighting,GL_IBM_cull_vertex,GL_IBM_multimode_draw_arrays,GL_IBM_rasterpos_clip,GL_IBM_static_data,GL_IBM_texture_mirrored_repeat,GL_IBM_vertex_array_lists,GL_INGR_blend_func_separate,GL_INGR_color_clamp,GL_INGR_interlace_read,GL_INTEL_blackhole_render,GL_INTEL_conservative_rasterization,GL_INTEL_fragment_shader_ordering,GL_INTEL_framebuffer_CMAA,GL_INTEL_map_texture,GL_INTEL_parallel_arrays,GL_INTEL_performance_query,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_context_flush_control,GL_KHR_debug,GL_KHR_no_error,GL_KHR_parallel_shader_compile,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_MESAX_texture_stack,GL_MESA_pack_invert,GL_MESA_program_binary_formats,GL_MESA_resize_buffers,GL_MESA_shader_integer_functions,GL_MESA_tile_raster_order,GL_MESA_window_pos,GL_MESA_ycbcr_texture,GL_NVX_blend_equation_advanced_multi_draw_buffers,GL_NVX_conditional_render,GL_NVX_gpu_memory_info,GL_NVX_linked_gpu_multicast,GL_NV_alpha_to_coverage_dither_control,GL_NV_bindless_multi_draw_indirect,GL_NV_bindless_multi_draw_indirect_count,GL_NV_bindless_texture,GL_NV_blend_equation_advanced,GL_NV_blend_equation_advanced_coherent,GL_NV_blend_minmax_factor,GL_NV_blend_square,GL_NV_clip_space_w_scaling,GL_NV_command_list,GL_NV_compute_program5,GL_NV_conditional_render,GL_NV_conservative_raster,GL_NV_conservative_raster_dilate,GL_NV_conservative_raster_pre_snap,GL_NV_conservative_raster_pre_snap_triangles,GL_NV_conservative_raster_underestimation,GL_NV_copy_depth_to_color,GL_NV_copy_image,GL_NV_deep_texture3D,GL_NV_depth_buffer_float,GL_NV_depth_clamp,GL_NV_draw_texture,GL_NV_draw_vulkan_image,GL_NV_evaluators,GL_NV_explicit_multisample,GL_NV_fence,GL_NV_fill_rectangle,GL_NV_float_buffer,GL_NV_fog_distance,GL_NV_fragment_coverage_to_color,GL_NV_fragment_program,GL_NV_fragment_program2,GL_NV_fragment_program4,GL_NV_fragment_program_option,GL_NV_fragment_shader_interlock,GL_NV_framebuffer_mixed_samples,GL_NV_framebuffer_multisample_coverage,GL_NV_geometry_program4,GL_NV_geometry_shader4,GL_NV_geometry_shader_passthrough,GL_NV_gpu_multicast,GL_NV_gpu_program4,GL_NV_gpu_program5,GL_NV_gpu_program5_mem_extended,GL_NV_gpu_shader5,GL_NV_half_float,GL_NV_internalformat_sample_query,GL_NV_light_max_exponent,GL_NV_multisample_coverage,GL_NV_multisample_filter_hint,GL_NV_occlusion_query,GL_NV_packed_depth_stencil,GL_NV_parameter_buffer_object,GL_NV_parameter_buffer_object2,GL_NV_path_rendering,GL_NV_path_rendering_shared_edge,GL_NV_pixel_data_range,GL_NV_point_sprite,GL_NV_present_video,GL_NV_primitive_restart,GL_NV_query_resource,GL_NV_query_resource_tag,GL_NV_register_combiners,GL_NV_register_combiners2,GL_NV_robustness_video_memory_purge,GL_NV_sample_locations,GL_NV_sample_mask_override_coverage,GL_NV_shader_atomic_counters,GL_NV_shader_atomic_float,GL_NV_shader_atomic_float64,GL_NV_shader_atomic_fp16_vector,GL_NV_shader_atomic_int64,GL_NV_shader_buffer_load,GL_NV_shader_buffer_store,GL_NV_shader_storage_buffer_object,GL_NV_shader_thread_group,GL_NV_shader_thread_shuffle,GL_NV_stereo_view_rendering,GL_NV_tessellation_program5,GL_NV_texgen_emboss,GL_NV_texgen_reflection,GL_NV_texture_barrier,GL_NV_texture_compression_vtc,GL_NV_texture_env_combine4,GL_NV_texture_expand_normal,GL_NV_texture_multisample,GL_NV_texture_rectangle,GL_NV_texture_rectangle_compressed,GL_NV_texture_shader,GL_NV_texture_shader2,GL_NV_texture_shader3,GL_NV_transform_feedback,GL_NV_transform_feedback2,GL_NV_uniform_buffer_unified_memory,GL_NV_vdpau_interop,GL_NV_vertex_array_range,GL_NV_vertex_array_range2,GL_NV_vertex_attrib_integer_64bit,GL_NV_vertex_buffer_unified_memory,GL_NV_vertex_program,GL_NV_vertex_program1_1,GL_NV_vertex_program2,GL_NV_vertex_program2_option,GL_NV_vertex_program3,GL_NV_vertex_program4,GL_NV_video_capture,GL_NV_viewport_array2,GL_NV_viewport_swizzle,GL_OES_byte_coordinates,GL_OES_compressed_paletted_texture,GL_OES_fixed_point,GL_OES_query_matrix,GL_OES_read_format,GL_OES_single_precision,GL_OML_interlace,GL_OML_resample,GL_OML_subsample,GL_OVR_multiview,GL_OVR_multiview2,GL_PGI_misc_hints,GL_PGI_vertex_hints,GL_REND_screen_coordinates,GL_S3_s3tc,GL_SGIS_detail_texture,GL_SGIS_fog_function,GL_SGIS_generate_mipmap,GL_SGIS_multisample,GL_SGIS_pixel_texture,GL_SGIS_point_line_texgen,GL_SGIS_point_parameters,GL_SGIS_sharpen_texture,GL_SGIS_texture4D,GL_SGIS_texture_border_clamp,GL_SGIS_texture_color_mask,GL_SGIS_texture_edge_clamp,GL_SGIS_texture_filter4,GL_SGIS_texture_lod,GL_SGIS_texture_select,GL_SGIX_async,GL_SGIX_async_histogram,GL_SGIX_async_pixel,GL_SGIX_blend_alpha_minmax,GL_SGIX_calligraphic_fragment,GL_SGIX_clipmap,GL_SGIX_convolution_accuracy,GL_SGIX_depth_pass_instrument,GL_SGIX_depth_texture,GL_SGIX_flush_raster,GL_SGIX_fog_offset,GL_SGIX_fragment_lighting,GL_SGIX_framezoom,GL_SGIX_igloo_interface,GL_SGIX_instruments,GL_SGIX_interlace,GL_SGIX_ir_instrument1,GL_SGIX_list_priority,GL_SGIX_pixel_texture,GL_SGIX_pixel_tiles,GL_SGIX_polynomial_ffd,GL_SGIX_reference_plane,GL_SGIX_resample,GL_SGIX_scalebias_hint,GL_SGIX_shadow,GL_SGIX_shadow_ambient,GL_SGIX_sprite,GL_SGIX_subsample,GL_SGIX_tag_sample_buffer,GL_SGIX_texture_add_env,GL_SGIX_texture_coordinate_clamp,GL_SGIX_texture_lod_bias,GL_SGIX_texture_multi_buffer,GL_SGIX_texture_scale_bias,GL_SGIX_vertex_preclip,GL_SGIX_ycrcb,GL_SGIX_ycrcb_subsample,GL_SGIX_ycrcba,GL_SGI_color_matrix,GL_SGI_color_table,GL_SGI_texture_color_table,GL_SUNX_constant_data,GL_SUN_convolution_border_modes,GL_SUN_global_alpha,GL_SUN_mesh_array,GL_SUN_slice_accum,GL_SUN_triangle_list,GL_SUN_vertex,GL_WIN_phong_shading,GL_WIN_specular_fog"
Online:
Too many extensions
*/
@@ -1409,7 +1410,6 @@ typedef void (APIENTRY *GLVULKANPROCNV)(void);
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
#define GL_MAX_SAMPLES 0x8D57
-#define GL_INDEX 0x8222
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#define GL_HALF_FLOAT 0x140B
#define GL_MAP_READ_BIT 0x0001
@@ -2780,6 +2780,12 @@ GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E
#define GL_DEPTH_CLAMP_FAR_AMD 0x901F
+#define GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2
+#define GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3
+#define GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4
+#define GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5
+#define GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6
+#define GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7
#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
#define GL_PIXELS_PER_SAMPLE_PATTERN_X_AMD 0x91AE
#define GL_PIXELS_PER_SAMPLE_PATTERN_Y_AMD 0x91AF
@@ -3157,6 +3163,7 @@ GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_INDEX 0x8222
#define GL_LINES_ADJACENCY_ARB 0x000A
#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
@@ -6433,6 +6440,16 @@ typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC)(GLuint buf, GL
GLAPI PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC glad_glBlendEquationSeparateIndexedAMD;
#define glBlendEquationSeparateIndexedAMD glad_glBlendEquationSeparateIndexedAMD
#endif
+#ifndef GL_AMD_framebuffer_multisample_advanced
+#define GL_AMD_framebuffer_multisample_advanced 1
+GLAPI int GLAD_GL_AMD_framebuffer_multisample_advanced;
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC)(GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC glad_glRenderbufferStorageMultisampleAdvancedAMD;
+#define glRenderbufferStorageMultisampleAdvancedAMD glad_glRenderbufferStorageMultisampleAdvancedAMD
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC)(GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC glad_glNamedRenderbufferStorageMultisampleAdvancedAMD;
+#define glNamedRenderbufferStorageMultisampleAdvancedAMD glad_glNamedRenderbufferStorageMultisampleAdvancedAMD
+#endif
#ifndef GL_AMD_framebuffer_sample_positions
#define GL_AMD_framebuffer_sample_positions 1
GLAPI int GLAD_GL_AMD_framebuffer_sample_positions;
diff --git a/externals/glad/src/glad.c b/externals/glad/src/glad.c
index 13607e449..1cf0890b9 100644
--- a/externals/glad/src/glad.c
+++ b/externals/glad/src/glad.c
@@ -1,6 +1,6 @@
/*
- OpenGL loader generated by glad 0.1.25 on Fri Jul 20 07:59:28 2018.
+ OpenGL loader generated by glad 0.1.26 on Tue Aug 7 08:21:50 2018.
Language/Generator: C/C++
Specification: gl
@@ -15,6 +15,7 @@
GL_AMD_debug_output,
GL_AMD_depth_clamp_separate,
GL_AMD_draw_buffers_blend,
+ GL_AMD_framebuffer_multisample_advanced,
GL_AMD_framebuffer_sample_positions,
GL_AMD_gcn_shader,
GL_AMD_gpu_shader_half_float,
@@ -600,7 +601,7 @@
Omit khrplatform: False
Commandline:
- --profile="core" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_3DFX_multisample,GL_3DFX_tbuffer,GL_3DFX_texture_compression_FXT1,GL_AMD_blend_minmax_factor,GL_AMD_conservative_depth,GL_AMD_debug_output,GL_AMD_depth_clamp_separate,GL_AMD_draw_buffers_blend,GL_AMD_framebuffer_sample_positions,GL_AMD_gcn_shader,GL_AMD_gpu_shader_half_float,GL_AMD_gpu_shader_int16,GL_AMD_gpu_shader_int64,GL_AMD_interleaved_elements,GL_AMD_multi_draw_indirect,GL_AMD_name_gen_delete,GL_AMD_occlusion_query_event,GL_AMD_performance_monitor,GL_AMD_pinned_memory,GL_AMD_query_buffer_object,GL_AMD_sample_positions,GL_AMD_seamless_cubemap_per_texture,GL_AMD_shader_atomic_counter_ops,GL_AMD_shader_ballot,GL_AMD_shader_explicit_vertex_parameter,GL_AMD_shader_gpu_shader_half_float_fetch,GL_AMD_shader_image_load_store_lod,GL_AMD_shader_stencil_export,GL_AMD_shader_trinary_minmax,GL_AMD_sparse_texture,GL_AMD_stencil_operation_extended,GL_AMD_texture_gather_bias_lod,GL_AMD_texture_texture4,GL_AMD_transform_feedback3_lines_triangles,GL_AMD_transform_feedback4,GL_AMD_vertex_shader_layer,GL_AMD_vertex_shader_tessellator,GL_AMD_vertex_shader_viewport_index,GL_APPLE_aux_depth_stencil,GL_APPLE_client_storage,GL_APPLE_element_array,GL_APPLE_fence,GL_APPLE_float_pixels,GL_APPLE_flush_buffer_range,GL_APPLE_object_purgeable,GL_APPLE_rgb_422,GL_APPLE_row_bytes,GL_APPLE_specular_vector,GL_APPLE_texture_range,GL_APPLE_transform_hint,GL_APPLE_vertex_array_object,GL_APPLE_vertex_array_range,GL_APPLE_vertex_program_evaluators,GL_APPLE_ycbcr_422,GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_arrays_of_arrays,GL_ARB_base_instance,GL_ARB_bindless_texture,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_cl_event,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_clip_control,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_conditional_render_inverted,GL_ARB_conservative_depth,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_cull_distance,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_derivative_control,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_imaging,GL_ARB_indirect_parameters,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_invalidate_subdata,GL_ARB_map_buffer_alignment,GL_ARB_map_buffer_range,GL_ARB_matrix_palette,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_parallel_shader_compile,GL_ARB_pipeline_statistics_query,GL_ARB_pixel_buffer_object,GL_ARB_point_parameters,GL_ARB_point_sprite,GL_ARB_polygon_offset_clamp,GL_ARB_post_depth_coverage,GL_ARB_program_interface_query,GL_ARB_provoking_vertex,GL_ARB_query_buffer_object,GL_ARB_robust_buffer_access_behavior,GL_ARB_robustness,GL_ARB_robustness_isolation,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_sampler_objects,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_separate_shader_objects,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_ballot,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_draw_parameters,GL_ARB_shader_group_vote,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_precision,GL_ARB_shader_stencil_export,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_subroutine,GL_ARB_shader_texture_image_samples,GL_ARB_shader_texture_lod,GL_ARB_shader_viewport_layer_array,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_shadow,GL_ARB_shadow_ambient,GL_ARB_sparse_buffer,GL_ARB_sparse_texture,GL_ARB_sparse_texture2,GL_ARB_sparse_texture_clamp,GL_ARB_spirv_extensions,GL_ARB_stencil_texturing,GL_ARB_sync,GL_ARB_tessellation_shader,GL_ARB_texture_barrier,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_buffer_range,GL_ARB_texture_compression,GL_ARB_texture_compression_bptc,GL_ARB_texture_compression_rgtc,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_env_combine,GL_ARB_texture_env_crossbar,GL_ARB_texture_env_dot3,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_gather,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_query_levels,GL_ARB_texture_query_lod,GL_ARB_texture_rectangle,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_texture_stencil8,GL_ARB_texture_storage,GL_ARB_texture_storage_multisample,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transform_feedback2,GL_ARB_transform_feedback3,GL_ARB_transform_feedback_instanced,GL_ARB_transform_feedback_overflow_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_64bit,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_blend,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_10f_11f_11f_rev,GL_ARB_vertex_type_2_10_10_10_rev,GL_ARB_viewport_array,GL_ARB_window_pos,GL_ATI_draw_buffers,GL_ATI_element_array,GL_ATI_envmap_bumpmap,GL_ATI_fragment_shader,GL_ATI_map_object_buffer,GL_ATI_meminfo,GL_ATI_pixel_format_float,GL_ATI_pn_triangles,GL_ATI_separate_stencil,GL_ATI_text_fragment_shader,GL_ATI_texture_env_combine3,GL_ATI_texture_float,GL_ATI_texture_mirror_once,GL_ATI_vertex_array_object,GL_ATI_vertex_attrib_array_object,GL_ATI_vertex_streams,GL_EXT_422_pixels,GL_EXT_EGL_image_storage,GL_EXT_abgr,GL_EXT_bgra,GL_EXT_bindable_uniform,GL_EXT_blend_color,GL_EXT_blend_equation_separate,GL_EXT_blend_func_separate,GL_EXT_blend_logic_op,GL_EXT_blend_minmax,GL_EXT_blend_subtract,GL_EXT_clip_volume_hint,GL_EXT_cmyka,GL_EXT_color_subtable,GL_EXT_compiled_vertex_array,GL_EXT_convolution,GL_EXT_coordinate_frame,GL_EXT_copy_texture,GL_EXT_cull_vertex,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_depth_bounds_test,GL_EXT_direct_state_access,GL_EXT_draw_buffers2,GL_EXT_draw_instanced,GL_EXT_draw_range_elements,GL_EXT_external_buffer,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_program_parameters,GL_EXT_gpu_shader4,GL_EXT_histogram,GL_EXT_index_array_formats,GL_EXT_index_func,GL_EXT_index_material,GL_EXT_index_texture,GL_EXT_light_texture,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_memory_object_win32,GL_EXT_misc_attribute,GL_EXT_multi_draw_arrays,GL_EXT_multisample,GL_EXT_packed_depth_stencil,GL_EXT_packed_float,GL_EXT_packed_pixels,GL_EXT_paletted_texture,GL_EXT_pixel_buffer_object,GL_EXT_pixel_transform,GL_EXT_pixel_transform_color_table,GL_EXT_point_parameters,GL_EXT_polygon_offset,GL_EXT_polygon_offset_clamp,GL_EXT_post_depth_coverage,GL_EXT_provoking_vertex,GL_EXT_raster_multisample,GL_EXT_rescale_normal,GL_EXT_secondary_color,GL_EXT_semaphore,GL_EXT_semaphore_fd,GL_EXT_semaphore_win32,GL_EXT_separate_shader_objects,GL_EXT_separate_specular_color,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_framebuffer_fetch_non_coherent,GL_EXT_shader_image_load_formatted,GL_EXT_shader_image_load_store,GL_EXT_shader_integer_mix,GL_EXT_shadow_funcs,GL_EXT_shared_texture_palette,GL_EXT_sparse_texture2,GL_EXT_stencil_clear_tag,GL_EXT_stencil_two_side,GL_EXT_stencil_wrap,GL_EXT_subtexture,GL_EXT_texture,GL_EXT_texture3D,GL_EXT_texture_array,GL_EXT_texture_buffer_object,GL_EXT_texture_compression_latc,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_cube_map,GL_EXT_texture_env_add,GL_EXT_texture_env_combine,GL_EXT_texture_env_dot3,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_filter_minmax,GL_EXT_texture_integer,GL_EXT_texture_lod_bias,GL_EXT_texture_mirror_clamp,GL_EXT_texture_object,GL_EXT_texture_perturb_normal,GL_EXT_texture_sRGB,GL_EXT_texture_sRGB_decode,GL_EXT_texture_shared_exponent,GL_EXT_texture_snorm,GL_EXT_texture_swizzle,GL_EXT_timer_query,GL_EXT_transform_feedback,GL_EXT_vertex_array,GL_EXT_vertex_array_bgra,GL_EXT_vertex_attrib_64bit,GL_EXT_vertex_shader,GL_EXT_vertex_weighting,GL_EXT_win32_keyed_mutex,GL_EXT_window_rectangles,GL_EXT_x11_sync_object,GL_GREMEDY_frame_terminator,GL_GREMEDY_string_marker,GL_HP_convolution_border_modes,GL_HP_image_transform,GL_HP_occlusion_test,GL_HP_texture_lighting,GL_IBM_cull_vertex,GL_IBM_multimode_draw_arrays,GL_IBM_rasterpos_clip,GL_IBM_static_data,GL_IBM_texture_mirrored_repeat,GL_IBM_vertex_array_lists,GL_INGR_blend_func_separate,GL_INGR_color_clamp,GL_INGR_interlace_read,GL_INTEL_blackhole_render,GL_INTEL_conservative_rasterization,GL_INTEL_fragment_shader_ordering,GL_INTEL_framebuffer_CMAA,GL_INTEL_map_texture,GL_INTEL_parallel_arrays,GL_INTEL_performance_query,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_context_flush_control,GL_KHR_debug,GL_KHR_no_error,GL_KHR_parallel_shader_compile,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_MESAX_texture_stack,GL_MESA_pack_invert,GL_MESA_program_binary_formats,GL_MESA_resize_buffers,GL_MESA_shader_integer_functions,GL_MESA_tile_raster_order,GL_MESA_window_pos,GL_MESA_ycbcr_texture,GL_NVX_blend_equation_advanced_multi_draw_buffers,GL_NVX_conditional_render,GL_NVX_gpu_memory_info,GL_NVX_linked_gpu_multicast,GL_NV_alpha_to_coverage_dither_control,GL_NV_bindless_multi_draw_indirect,GL_NV_bindless_multi_draw_indirect_count,GL_NV_bindless_texture,GL_NV_blend_equation_advanced,GL_NV_blend_equation_advanced_coherent,GL_NV_blend_minmax_factor,GL_NV_blend_square,GL_NV_clip_space_w_scaling,GL_NV_command_list,GL_NV_compute_program5,GL_NV_conditional_render,GL_NV_conservative_raster,GL_NV_conservative_raster_dilate,GL_NV_conservative_raster_pre_snap,GL_NV_conservative_raster_pre_snap_triangles,GL_NV_conservative_raster_underestimation,GL_NV_copy_depth_to_color,GL_NV_copy_image,GL_NV_deep_texture3D,GL_NV_depth_buffer_float,GL_NV_depth_clamp,GL_NV_draw_texture,GL_NV_draw_vulkan_image,GL_NV_evaluators,GL_NV_explicit_multisample,GL_NV_fence,GL_NV_fill_rectangle,GL_NV_float_buffer,GL_NV_fog_distance,GL_NV_fragment_coverage_to_color,GL_NV_fragment_program,GL_NV_fragment_program2,GL_NV_fragment_program4,GL_NV_fragment_program_option,GL_NV_fragment_shader_interlock,GL_NV_framebuffer_mixed_samples,GL_NV_framebuffer_multisample_coverage,GL_NV_geometry_program4,GL_NV_geometry_shader4,GL_NV_geometry_shader_passthrough,GL_NV_gpu_multicast,GL_NV_gpu_program4,GL_NV_gpu_program5,GL_NV_gpu_program5_mem_extended,GL_NV_gpu_shader5,GL_NV_half_float,GL_NV_internalformat_sample_query,GL_NV_light_max_exponent,GL_NV_multisample_coverage,GL_NV_multisample_filter_hint,GL_NV_occlusion_query,GL_NV_packed_depth_stencil,GL_NV_parameter_buffer_object,GL_NV_parameter_buffer_object2,GL_NV_path_rendering,GL_NV_path_rendering_shared_edge,GL_NV_pixel_data_range,GL_NV_point_sprite,GL_NV_present_video,GL_NV_primitive_restart,GL_NV_query_resource,GL_NV_query_resource_tag,GL_NV_register_combiners,GL_NV_register_combiners2,GL_NV_robustness_video_memory_purge,GL_NV_sample_locations,GL_NV_sample_mask_override_coverage,GL_NV_shader_atomic_counters,GL_NV_shader_atomic_float,GL_NV_shader_atomic_float64,GL_NV_shader_atomic_fp16_vector,GL_NV_shader_atomic_int64,GL_NV_shader_buffer_load,GL_NV_shader_buffer_store,GL_NV_shader_storage_buffer_object,GL_NV_shader_thread_group,GL_NV_shader_thread_shuffle,GL_NV_stereo_view_rendering,GL_NV_tessellation_program5,GL_NV_texgen_emboss,GL_NV_texgen_reflection,GL_NV_texture_barrier,GL_NV_texture_compression_vtc,GL_NV_texture_env_combine4,GL_NV_texture_expand_normal,GL_NV_texture_multisample,GL_NV_texture_rectangle,GL_NV_texture_rectangle_compressed,GL_NV_texture_shader,GL_NV_texture_shader2,GL_NV_texture_shader3,GL_NV_transform_feedback,GL_NV_transform_feedback2,GL_NV_uniform_buffer_unified_memory,GL_NV_vdpau_interop,GL_NV_vertex_array_range,GL_NV_vertex_array_range2,GL_NV_vertex_attrib_integer_64bit,GL_NV_vertex_buffer_unified_memory,GL_NV_vertex_program,GL_NV_vertex_program1_1,GL_NV_vertex_program2,GL_NV_vertex_program2_option,GL_NV_vertex_program3,GL_NV_vertex_program4,GL_NV_video_capture,GL_NV_viewport_array2,GL_NV_viewport_swizzle,GL_OES_byte_coordinates,GL_OES_compressed_paletted_texture,GL_OES_fixed_point,GL_OES_query_matrix,GL_OES_read_format,GL_OES_single_precision,GL_OML_interlace,GL_OML_resample,GL_OML_subsample,GL_OVR_multiview,GL_OVR_multiview2,GL_PGI_misc_hints,GL_PGI_vertex_hints,GL_REND_screen_coordinates,GL_S3_s3tc,GL_SGIS_detail_texture,GL_SGIS_fog_function,GL_SGIS_generate_mipmap,GL_SGIS_multisample,GL_SGIS_pixel_texture,GL_SGIS_point_line_texgen,GL_SGIS_point_parameters,GL_SGIS_sharpen_texture,GL_SGIS_texture4D,GL_SGIS_texture_border_clamp,GL_SGIS_texture_color_mask,GL_SGIS_texture_edge_clamp,GL_SGIS_texture_filter4,GL_SGIS_texture_lod,GL_SGIS_texture_select,GL_SGIX_async,GL_SGIX_async_histogram,GL_SGIX_async_pixel,GL_SGIX_blend_alpha_minmax,GL_SGIX_calligraphic_fragment,GL_SGIX_clipmap,GL_SGIX_convolution_accuracy,GL_SGIX_depth_pass_instrument,GL_SGIX_depth_texture,GL_SGIX_flush_raster,GL_SGIX_fog_offset,GL_SGIX_fragment_lighting,GL_SGIX_framezoom,GL_SGIX_igloo_interface,GL_SGIX_instruments,GL_SGIX_interlace,GL_SGIX_ir_instrument1,GL_SGIX_list_priority,GL_SGIX_pixel_texture,GL_SGIX_pixel_tiles,GL_SGIX_polynomial_ffd,GL_SGIX_reference_plane,GL_SGIX_resample,GL_SGIX_scalebias_hint,GL_SGIX_shadow,GL_SGIX_shadow_ambient,GL_SGIX_sprite,GL_SGIX_subsample,GL_SGIX_tag_sample_buffer,GL_SGIX_texture_add_env,GL_SGIX_texture_coordinate_clamp,GL_SGIX_texture_lod_bias,GL_SGIX_texture_multi_buffer,GL_SGIX_texture_scale_bias,GL_SGIX_vertex_preclip,GL_SGIX_ycrcb,GL_SGIX_ycrcb_subsample,GL_SGIX_ycrcba,GL_SGI_color_matrix,GL_SGI_color_table,GL_SGI_texture_color_table,GL_SUNX_constant_data,GL_SUN_convolution_border_modes,GL_SUN_global_alpha,GL_SUN_mesh_array,GL_SUN_slice_accum,GL_SUN_triangle_list,GL_SUN_vertex,GL_WIN_phong_shading,GL_WIN_specular_fog"
+ --profile="core" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_3DFX_multisample,GL_3DFX_tbuffer,GL_3DFX_texture_compression_FXT1,GL_AMD_blend_minmax_factor,GL_AMD_conservative_depth,GL_AMD_debug_output,GL_AMD_depth_clamp_separate,GL_AMD_draw_buffers_blend,GL_AMD_framebuffer_multisample_advanced,GL_AMD_framebuffer_sample_positions,GL_AMD_gcn_shader,GL_AMD_gpu_shader_half_float,GL_AMD_gpu_shader_int16,GL_AMD_gpu_shader_int64,GL_AMD_interleaved_elements,GL_AMD_multi_draw_indirect,GL_AMD_name_gen_delete,GL_AMD_occlusion_query_event,GL_AMD_performance_monitor,GL_AMD_pinned_memory,GL_AMD_query_buffer_object,GL_AMD_sample_positions,GL_AMD_seamless_cubemap_per_texture,GL_AMD_shader_atomic_counter_ops,GL_AMD_shader_ballot,GL_AMD_shader_explicit_vertex_parameter,GL_AMD_shader_gpu_shader_half_float_fetch,GL_AMD_shader_image_load_store_lod,GL_AMD_shader_stencil_export,GL_AMD_shader_trinary_minmax,GL_AMD_sparse_texture,GL_AMD_stencil_operation_extended,GL_AMD_texture_gather_bias_lod,GL_AMD_texture_texture4,GL_AMD_transform_feedback3_lines_triangles,GL_AMD_transform_feedback4,GL_AMD_vertex_shader_layer,GL_AMD_vertex_shader_tessellator,GL_AMD_vertex_shader_viewport_index,GL_APPLE_aux_depth_stencil,GL_APPLE_client_storage,GL_APPLE_element_array,GL_APPLE_fence,GL_APPLE_float_pixels,GL_APPLE_flush_buffer_range,GL_APPLE_object_purgeable,GL_APPLE_rgb_422,GL_APPLE_row_bytes,GL_APPLE_specular_vector,GL_APPLE_texture_range,GL_APPLE_transform_hint,GL_APPLE_vertex_array_object,GL_APPLE_vertex_array_range,GL_APPLE_vertex_program_evaluators,GL_APPLE_ycbcr_422,GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_arrays_of_arrays,GL_ARB_base_instance,GL_ARB_bindless_texture,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_cl_event,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_clip_control,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_conditional_render_inverted,GL_ARB_conservative_depth,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_cull_distance,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_derivative_control,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_imaging,GL_ARB_indirect_parameters,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_invalidate_subdata,GL_ARB_map_buffer_alignment,GL_ARB_map_buffer_range,GL_ARB_matrix_palette,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_parallel_shader_compile,GL_ARB_pipeline_statistics_query,GL_ARB_pixel_buffer_object,GL_ARB_point_parameters,GL_ARB_point_sprite,GL_ARB_polygon_offset_clamp,GL_ARB_post_depth_coverage,GL_ARB_program_interface_query,GL_ARB_provoking_vertex,GL_ARB_query_buffer_object,GL_ARB_robust_buffer_access_behavior,GL_ARB_robustness,GL_ARB_robustness_isolation,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_sampler_objects,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_separate_shader_objects,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_ballot,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_draw_parameters,GL_ARB_shader_group_vote,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_precision,GL_ARB_shader_stencil_export,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_subroutine,GL_ARB_shader_texture_image_samples,GL_ARB_shader_texture_lod,GL_ARB_shader_viewport_layer_array,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_shadow,GL_ARB_shadow_ambient,GL_ARB_sparse_buffer,GL_ARB_sparse_texture,GL_ARB_sparse_texture2,GL_ARB_sparse_texture_clamp,GL_ARB_spirv_extensions,GL_ARB_stencil_texturing,GL_ARB_sync,GL_ARB_tessellation_shader,GL_ARB_texture_barrier,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_buffer_range,GL_ARB_texture_compression,GL_ARB_texture_compression_bptc,GL_ARB_texture_compression_rgtc,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_env_combine,GL_ARB_texture_env_crossbar,GL_ARB_texture_env_dot3,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_gather,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_query_levels,GL_ARB_texture_query_lod,GL_ARB_texture_rectangle,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_texture_stencil8,GL_ARB_texture_storage,GL_ARB_texture_storage_multisample,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transform_feedback2,GL_ARB_transform_feedback3,GL_ARB_transform_feedback_instanced,GL_ARB_transform_feedback_overflow_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_64bit,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_blend,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_10f_11f_11f_rev,GL_ARB_vertex_type_2_10_10_10_rev,GL_ARB_viewport_array,GL_ARB_window_pos,GL_ATI_draw_buffers,GL_ATI_element_array,GL_ATI_envmap_bumpmap,GL_ATI_fragment_shader,GL_ATI_map_object_buffer,GL_ATI_meminfo,GL_ATI_pixel_format_float,GL_ATI_pn_triangles,GL_ATI_separate_stencil,GL_ATI_text_fragment_shader,GL_ATI_texture_env_combine3,GL_ATI_texture_float,GL_ATI_texture_mirror_once,GL_ATI_vertex_array_object,GL_ATI_vertex_attrib_array_object,GL_ATI_vertex_streams,GL_EXT_422_pixels,GL_EXT_EGL_image_storage,GL_EXT_abgr,GL_EXT_bgra,GL_EXT_bindable_uniform,GL_EXT_blend_color,GL_EXT_blend_equation_separate,GL_EXT_blend_func_separate,GL_EXT_blend_logic_op,GL_EXT_blend_minmax,GL_EXT_blend_subtract,GL_EXT_clip_volume_hint,GL_EXT_cmyka,GL_EXT_color_subtable,GL_EXT_compiled_vertex_array,GL_EXT_convolution,GL_EXT_coordinate_frame,GL_EXT_copy_texture,GL_EXT_cull_vertex,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_depth_bounds_test,GL_EXT_direct_state_access,GL_EXT_draw_buffers2,GL_EXT_draw_instanced,GL_EXT_draw_range_elements,GL_EXT_external_buffer,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_program_parameters,GL_EXT_gpu_shader4,GL_EXT_histogram,GL_EXT_index_array_formats,GL_EXT_index_func,GL_EXT_index_material,GL_EXT_index_texture,GL_EXT_light_texture,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_memory_object_win32,GL_EXT_misc_attribute,GL_EXT_multi_draw_arrays,GL_EXT_multisample,GL_EXT_packed_depth_stencil,GL_EXT_packed_float,GL_EXT_packed_pixels,GL_EXT_paletted_texture,GL_EXT_pixel_buffer_object,GL_EXT_pixel_transform,GL_EXT_pixel_transform_color_table,GL_EXT_point_parameters,GL_EXT_polygon_offset,GL_EXT_polygon_offset_clamp,GL_EXT_post_depth_coverage,GL_EXT_provoking_vertex,GL_EXT_raster_multisample,GL_EXT_rescale_normal,GL_EXT_secondary_color,GL_EXT_semaphore,GL_EXT_semaphore_fd,GL_EXT_semaphore_win32,GL_EXT_separate_shader_objects,GL_EXT_separate_specular_color,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_framebuffer_fetch_non_coherent,GL_EXT_shader_image_load_formatted,GL_EXT_shader_image_load_store,GL_EXT_shader_integer_mix,GL_EXT_shadow_funcs,GL_EXT_shared_texture_palette,GL_EXT_sparse_texture2,GL_EXT_stencil_clear_tag,GL_EXT_stencil_two_side,GL_EXT_stencil_wrap,GL_EXT_subtexture,GL_EXT_texture,GL_EXT_texture3D,GL_EXT_texture_array,GL_EXT_texture_buffer_object,GL_EXT_texture_compression_latc,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_cube_map,GL_EXT_texture_env_add,GL_EXT_texture_env_combine,GL_EXT_texture_env_dot3,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_filter_minmax,GL_EXT_texture_integer,GL_EXT_texture_lod_bias,GL_EXT_texture_mirror_clamp,GL_EXT_texture_object,GL_EXT_texture_perturb_normal,GL_EXT_texture_sRGB,GL_EXT_texture_sRGB_decode,GL_EXT_texture_shared_exponent,GL_EXT_texture_snorm,GL_EXT_texture_swizzle,GL_EXT_timer_query,GL_EXT_transform_feedback,GL_EXT_vertex_array,GL_EXT_vertex_array_bgra,GL_EXT_vertex_attrib_64bit,GL_EXT_vertex_shader,GL_EXT_vertex_weighting,GL_EXT_win32_keyed_mutex,GL_EXT_window_rectangles,GL_EXT_x11_sync_object,GL_GREMEDY_frame_terminator,GL_GREMEDY_string_marker,GL_HP_convolution_border_modes,GL_HP_image_transform,GL_HP_occlusion_test,GL_HP_texture_lighting,GL_IBM_cull_vertex,GL_IBM_multimode_draw_arrays,GL_IBM_rasterpos_clip,GL_IBM_static_data,GL_IBM_texture_mirrored_repeat,GL_IBM_vertex_array_lists,GL_INGR_blend_func_separate,GL_INGR_color_clamp,GL_INGR_interlace_read,GL_INTEL_blackhole_render,GL_INTEL_conservative_rasterization,GL_INTEL_fragment_shader_ordering,GL_INTEL_framebuffer_CMAA,GL_INTEL_map_texture,GL_INTEL_parallel_arrays,GL_INTEL_performance_query,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_context_flush_control,GL_KHR_debug,GL_KHR_no_error,GL_KHR_parallel_shader_compile,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_MESAX_texture_stack,GL_MESA_pack_invert,GL_MESA_program_binary_formats,GL_MESA_resize_buffers,GL_MESA_shader_integer_functions,GL_MESA_tile_raster_order,GL_MESA_window_pos,GL_MESA_ycbcr_texture,GL_NVX_blend_equation_advanced_multi_draw_buffers,GL_NVX_conditional_render,GL_NVX_gpu_memory_info,GL_NVX_linked_gpu_multicast,GL_NV_alpha_to_coverage_dither_control,GL_NV_bindless_multi_draw_indirect,GL_NV_bindless_multi_draw_indirect_count,GL_NV_bindless_texture,GL_NV_blend_equation_advanced,GL_NV_blend_equation_advanced_coherent,GL_NV_blend_minmax_factor,GL_NV_blend_square,GL_NV_clip_space_w_scaling,GL_NV_command_list,GL_NV_compute_program5,GL_NV_conditional_render,GL_NV_conservative_raster,GL_NV_conservative_raster_dilate,GL_NV_conservative_raster_pre_snap,GL_NV_conservative_raster_pre_snap_triangles,GL_NV_conservative_raster_underestimation,GL_NV_copy_depth_to_color,GL_NV_copy_image,GL_NV_deep_texture3D,GL_NV_depth_buffer_float,GL_NV_depth_clamp,GL_NV_draw_texture,GL_NV_draw_vulkan_image,GL_NV_evaluators,GL_NV_explicit_multisample,GL_NV_fence,GL_NV_fill_rectangle,GL_NV_float_buffer,GL_NV_fog_distance,GL_NV_fragment_coverage_to_color,GL_NV_fragment_program,GL_NV_fragment_program2,GL_NV_fragment_program4,GL_NV_fragment_program_option,GL_NV_fragment_shader_interlock,GL_NV_framebuffer_mixed_samples,GL_NV_framebuffer_multisample_coverage,GL_NV_geometry_program4,GL_NV_geometry_shader4,GL_NV_geometry_shader_passthrough,GL_NV_gpu_multicast,GL_NV_gpu_program4,GL_NV_gpu_program5,GL_NV_gpu_program5_mem_extended,GL_NV_gpu_shader5,GL_NV_half_float,GL_NV_internalformat_sample_query,GL_NV_light_max_exponent,GL_NV_multisample_coverage,GL_NV_multisample_filter_hint,GL_NV_occlusion_query,GL_NV_packed_depth_stencil,GL_NV_parameter_buffer_object,GL_NV_parameter_buffer_object2,GL_NV_path_rendering,GL_NV_path_rendering_shared_edge,GL_NV_pixel_data_range,GL_NV_point_sprite,GL_NV_present_video,GL_NV_primitive_restart,GL_NV_query_resource,GL_NV_query_resource_tag,GL_NV_register_combiners,GL_NV_register_combiners2,GL_NV_robustness_video_memory_purge,GL_NV_sample_locations,GL_NV_sample_mask_override_coverage,GL_NV_shader_atomic_counters,GL_NV_shader_atomic_float,GL_NV_shader_atomic_float64,GL_NV_shader_atomic_fp16_vector,GL_NV_shader_atomic_int64,GL_NV_shader_buffer_load,GL_NV_shader_buffer_store,GL_NV_shader_storage_buffer_object,GL_NV_shader_thread_group,GL_NV_shader_thread_shuffle,GL_NV_stereo_view_rendering,GL_NV_tessellation_program5,GL_NV_texgen_emboss,GL_NV_texgen_reflection,GL_NV_texture_barrier,GL_NV_texture_compression_vtc,GL_NV_texture_env_combine4,GL_NV_texture_expand_normal,GL_NV_texture_multisample,GL_NV_texture_rectangle,GL_NV_texture_rectangle_compressed,GL_NV_texture_shader,GL_NV_texture_shader2,GL_NV_texture_shader3,GL_NV_transform_feedback,GL_NV_transform_feedback2,GL_NV_uniform_buffer_unified_memory,GL_NV_vdpau_interop,GL_NV_vertex_array_range,GL_NV_vertex_array_range2,GL_NV_vertex_attrib_integer_64bit,GL_NV_vertex_buffer_unified_memory,GL_NV_vertex_program,GL_NV_vertex_program1_1,GL_NV_vertex_program2,GL_NV_vertex_program2_option,GL_NV_vertex_program3,GL_NV_vertex_program4,GL_NV_video_capture,GL_NV_viewport_array2,GL_NV_viewport_swizzle,GL_OES_byte_coordinates,GL_OES_compressed_paletted_texture,GL_OES_fixed_point,GL_OES_query_matrix,GL_OES_read_format,GL_OES_single_precision,GL_OML_interlace,GL_OML_resample,GL_OML_subsample,GL_OVR_multiview,GL_OVR_multiview2,GL_PGI_misc_hints,GL_PGI_vertex_hints,GL_REND_screen_coordinates,GL_S3_s3tc,GL_SGIS_detail_texture,GL_SGIS_fog_function,GL_SGIS_generate_mipmap,GL_SGIS_multisample,GL_SGIS_pixel_texture,GL_SGIS_point_line_texgen,GL_SGIS_point_parameters,GL_SGIS_sharpen_texture,GL_SGIS_texture4D,GL_SGIS_texture_border_clamp,GL_SGIS_texture_color_mask,GL_SGIS_texture_edge_clamp,GL_SGIS_texture_filter4,GL_SGIS_texture_lod,GL_SGIS_texture_select,GL_SGIX_async,GL_SGIX_async_histogram,GL_SGIX_async_pixel,GL_SGIX_blend_alpha_minmax,GL_SGIX_calligraphic_fragment,GL_SGIX_clipmap,GL_SGIX_convolution_accuracy,GL_SGIX_depth_pass_instrument,GL_SGIX_depth_texture,GL_SGIX_flush_raster,GL_SGIX_fog_offset,GL_SGIX_fragment_lighting,GL_SGIX_framezoom,GL_SGIX_igloo_interface,GL_SGIX_instruments,GL_SGIX_interlace,GL_SGIX_ir_instrument1,GL_SGIX_list_priority,GL_SGIX_pixel_texture,GL_SGIX_pixel_tiles,GL_SGIX_polynomial_ffd,GL_SGIX_reference_plane,GL_SGIX_resample,GL_SGIX_scalebias_hint,GL_SGIX_shadow,GL_SGIX_shadow_ambient,GL_SGIX_sprite,GL_SGIX_subsample,GL_SGIX_tag_sample_buffer,GL_SGIX_texture_add_env,GL_SGIX_texture_coordinate_clamp,GL_SGIX_texture_lod_bias,GL_SGIX_texture_multi_buffer,GL_SGIX_texture_scale_bias,GL_SGIX_vertex_preclip,GL_SGIX_ycrcb,GL_SGIX_ycrcb_subsample,GL_SGIX_ycrcba,GL_SGI_color_matrix,GL_SGI_color_table,GL_SGI_texture_color_table,GL_SUNX_constant_data,GL_SUN_convolution_border_modes,GL_SUN_global_alpha,GL_SUN_mesh_array,GL_SUN_slice_accum,GL_SUN_triangle_list,GL_SUN_vertex,GL_WIN_phong_shading,GL_WIN_specular_fog"
Online:
Too many extensions
*/
@@ -739,7 +740,7 @@ int gladLoadGL(void) {
return status;
}
-struct gladGLversionStruct GLVersion;
+struct gladGLversionStruct GLVersion = { 0, 0 };
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
#define _GLAD_IS_SOME_NEW_VERSION 1
@@ -838,3190 +839,3193 @@ static int has_ext(const char *ext) {
return 0;
}
-int GLAD_GL_VERSION_1_0;
-int GLAD_GL_VERSION_1_1;
-int GLAD_GL_VERSION_1_2;
-int GLAD_GL_VERSION_1_3;
-int GLAD_GL_VERSION_1_4;
-int GLAD_GL_VERSION_1_5;
-int GLAD_GL_VERSION_2_0;
-int GLAD_GL_VERSION_2_1;
-int GLAD_GL_VERSION_3_0;
-int GLAD_GL_VERSION_3_1;
-int GLAD_GL_VERSION_3_2;
-int GLAD_GL_VERSION_3_3;
-PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
-PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
-PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
-PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
-PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
-PFNGLBINDSAMPLERPROC glad_glBindSampler;
-PFNGLLINEWIDTHPROC glad_glLineWidth;
-PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
-PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
-PFNGLCOMPILESHADERPROC glad_glCompileShader;
-PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
-PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
-PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
-PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
-PFNGLENABLEIPROC glad_glEnablei;
-PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
-PFNGLCREATESHADERPROC glad_glCreateShader;
-PFNGLISBUFFERPROC glad_glIsBuffer;
-PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
-PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
-PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
-PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
-PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
-PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
-PFNGLHINTPROC glad_glHint;
-PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
-PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
-PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
-PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
-PFNGLPOINTSIZEPROC glad_glPointSize;
-PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
-PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
-PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
-PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
-PFNGLWAITSYNCPROC glad_glWaitSync;
-PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
-PFNGLUNIFORM3IPROC glad_glUniform3i;
-PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
-PFNGLUNIFORM3FPROC glad_glUniform3f;
-PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
-PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
-PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
-PFNGLCOLORMASKIPROC glad_glColorMaski;
-PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
-PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
-PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
-PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
-PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
-PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
-PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
-PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
-PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
-PFNGLDRAWARRAYSPROC glad_glDrawArrays;
-PFNGLUNIFORM1UIPROC glad_glUniform1ui;
-PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
-PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
-PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
-PFNGLCLEARPROC glad_glClear;
-PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
-PFNGLISENABLEDPROC glad_glIsEnabled;
-PFNGLSTENCILOPPROC glad_glStencilOp;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
-PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
-PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
-PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
-PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
-PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
-PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
-PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
-PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
-PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
-PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
-PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
-PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
-PFNGLGETQUERYIVPROC glad_glGetQueryiv;
-PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
-PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
-PFNGLISSHADERPROC glad_glIsShader;
-PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
-PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
-PFNGLENABLEPROC glad_glEnable;
-PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
-PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
-PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
-PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
-PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
-PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
-PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
-PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
-PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
-PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
-PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
-PFNGLFLUSHPROC glad_glFlush;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
-PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
-PFNGLFENCESYNCPROC glad_glFenceSync;
-PFNGLCOLORP3UIPROC glad_glColorP3ui;
-PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
-PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
-PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
-PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
-PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
-PFNGLGENSAMPLERSPROC glad_glGenSamplers;
-PFNGLCLAMPCOLORPROC glad_glClampColor;
-PFNGLUNIFORM4IVPROC glad_glUniform4iv;
-PFNGLCLEARSTENCILPROC glad_glClearStencil;
-PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
-PFNGLGENTEXTURESPROC glad_glGenTextures;
-PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
-PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
-PFNGLISSYNCPROC glad_glIsSync;
-PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
-PFNGLUNIFORM2IPROC glad_glUniform2i;
-PFNGLUNIFORM2FPROC glad_glUniform2f;
-PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
-PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
-PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
-PFNGLGENQUERIESPROC glad_glGenQueries;
-PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
-PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
-PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
-PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
-PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
-PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
-PFNGLISENABLEDIPROC glad_glIsEnabledi;
-PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
-PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
-PFNGLUNIFORM2IVPROC glad_glUniform2iv;
-PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
-PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
-PFNGLGETSHADERIVPROC glad_glGetShaderiv;
-PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
-PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
-PFNGLGETDOUBLEVPROC glad_glGetDoublev;
-PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
-PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
-PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
-PFNGLUNIFORM3FVPROC glad_glUniform3fv;
-PFNGLDEPTHRANGEPROC glad_glDepthRange;
-PFNGLMAPBUFFERPROC glad_glMapBuffer;
-PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
-PFNGLDELETESYNCPROC glad_glDeleteSync;
-PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
-PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
-PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
-PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
-PFNGLUNIFORM3IVPROC glad_glUniform3iv;
-PFNGLPOLYGONMODEPROC glad_glPolygonMode;
-PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
-PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
-PFNGLUSEPROGRAMPROC glad_glUseProgram;
-PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
-PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
-PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
-PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
-PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
-PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
-PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
-PFNGLFINISHPROC glad_glFinish;
-PFNGLDELETESHADERPROC glad_glDeleteShader;
-PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
-PFNGLVIEWPORTPROC glad_glViewport;
-PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
-PFNGLUNIFORM2UIPROC glad_glUniform2ui;
-PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
-PFNGLCLEARDEPTHPROC glad_glClearDepth;
-PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
-PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
-PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
-PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
-PFNGLTEXBUFFERPROC glad_glTexBuffer;
-PFNGLPIXELSTOREIPROC glad_glPixelStorei;
-PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
-PFNGLPIXELSTOREFPROC glad_glPixelStoref;
-PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
-PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
-PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
-PFNGLLINKPROGRAMPROC glad_glLinkProgram;
-PFNGLBINDTEXTUREPROC glad_glBindTexture;
-PFNGLGETSTRINGPROC glad_glGetString;
-PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
-PFNGLDETACHSHADERPROC glad_glDetachShader;
-PFNGLENDQUERYPROC glad_glEndQuery;
-PFNGLNORMALP3UIPROC glad_glNormalP3ui;
-PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
-PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
-PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
-PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
-PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
-PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
-PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
-PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
-PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
-PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
-PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
-PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
-PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
-PFNGLUNIFORM1FPROC glad_glUniform1f;
-PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
-PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
-PFNGLUNIFORM1IPROC glad_glUniform1i;
-PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
-PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
-PFNGLDISABLEPROC glad_glDisable;
-PFNGLLOGICOPPROC glad_glLogicOp;
-PFNGLUNIFORM4UIPROC glad_glUniform4ui;
-PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
-PFNGLCULLFACEPROC glad_glCullFace;
-PFNGLGETSTRINGIPROC glad_glGetStringi;
-PFNGLATTACHSHADERPROC glad_glAttachShader;
-PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
-PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
-PFNGLDRAWELEMENTSPROC glad_glDrawElements;
-PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
-PFNGLUNIFORM1IVPROC glad_glUniform1iv;
-PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
-PFNGLREADBUFFERPROC glad_glReadBuffer;
-PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
-PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
-PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
-PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
-PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
-PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
-PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
-PFNGLBLENDCOLORPROC glad_glBlendColor;
-PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
-PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
-PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
-PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
-PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
-PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
-PFNGLISPROGRAMPROC glad_glIsProgram;
-PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
-PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
-PFNGLUNIFORM4IPROC glad_glUniform4i;
-PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
-PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
-PFNGLREADPIXELSPROC glad_glReadPixels;
-PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
-PFNGLUNIFORM4FPROC glad_glUniform4f;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
-PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
-PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
-PFNGLSTENCILFUNCPROC glad_glStencilFunc;
-PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
-PFNGLCOLORP4UIPROC glad_glColorP4ui;
-PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
-PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
-PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
-PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
-PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
-PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
-PFNGLGENBUFFERSPROC glad_glGenBuffers;
-PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
-PFNGLBLENDFUNCPROC glad_glBlendFunc;
-PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
-PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
-PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
-PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
-PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
-PFNGLSCISSORPROC glad_glScissor;
-PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
-PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
-PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
-PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
-PFNGLCLEARCOLORPROC glad_glClearColor;
-PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
-PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
-PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
-PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
-PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
-PFNGLUNIFORM3UIPROC glad_glUniform3ui;
-PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
-PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
-PFNGLUNIFORM2FVPROC glad_glUniform2fv;
-PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
-PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
-PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
-PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
-PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
-PFNGLDEPTHFUNCPROC glad_glDepthFunc;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
-PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
-PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
-PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
-PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
-PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
-PFNGLCOLORMASKPROC glad_glColorMask;
-PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
-PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
-PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
-PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
-PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
-PFNGLUNIFORM4FVPROC glad_glUniform4fv;
-PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
-PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
-PFNGLISSAMPLERPROC glad_glIsSampler;
-PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
-PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
-PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
-PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
-PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
-PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
-PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
-PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
-PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
-PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
-PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
-PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
-PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
-PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
-PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
-PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
-PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
-PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
-PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
-PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
-PFNGLDISABLEIPROC glad_glDisablei;
-PFNGLSHADERSOURCEPROC glad_glShaderSource;
-PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
-PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
-PFNGLGETSYNCIVPROC glad_glGetSynciv;
-PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
-PFNGLBEGINQUERYPROC glad_glBeginQuery;
-PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
-PFNGLBINDBUFFERPROC glad_glBindBuffer;
-PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
-PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
-PFNGLBUFFERDATAPROC glad_glBufferData;
-PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
-PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
-PFNGLGETERRORPROC glad_glGetError;
-PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
-PFNGLGETFLOATVPROC glad_glGetFloatv;
-PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
-PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
-PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
-PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
-PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
-PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
-PFNGLGETINTEGERVPROC glad_glGetIntegerv;
-PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
-PFNGLISQUERYPROC glad_glIsQuery;
-PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
-PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
-PFNGLSTENCILMASKPROC glad_glStencilMask;
-PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
-PFNGLISTEXTUREPROC glad_glIsTexture;
-PFNGLUNIFORM1FVPROC glad_glUniform1fv;
-PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
-PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
-PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
-PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
-PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
-PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
-PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
-PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
-PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
-PFNGLDEPTHMASKPROC glad_glDepthMask;
-PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
-PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
-PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
-PFNGLFRONTFACEPROC glad_glFrontFace;
-int GLAD_GL_SGIX_pixel_tiles;
-int GLAD_GL_EXT_post_depth_coverage;
-int GLAD_GL_APPLE_element_array;
-int GLAD_GL_AMD_multi_draw_indirect;
-int GLAD_GL_EXT_blend_subtract;
-int GLAD_GL_SGIX_tag_sample_buffer;
-int GLAD_GL_NV_point_sprite;
-int GLAD_GL_IBM_texture_mirrored_repeat;
-int GLAD_GL_APPLE_transform_hint;
-int GLAD_GL_ATI_separate_stencil;
-int GLAD_GL_NV_shader_atomic_int64;
-int GLAD_GL_EXT_semaphore_win32;
-int GLAD_GL_NV_vertex_program2_option;
-int GLAD_GL_EXT_texture_buffer_object;
-int GLAD_GL_ARB_vertex_blend;
-int GLAD_GL_OVR_multiview;
-int GLAD_GL_AMD_shader_gpu_shader_half_float_fetch;
-int GLAD_GL_NV_vertex_program2;
-int GLAD_GL_ARB_program_interface_query;
-int GLAD_GL_EXT_misc_attribute;
-int GLAD_GL_NV_multisample_coverage;
-int GLAD_GL_ARB_shading_language_packing;
-int GLAD_GL_EXT_texture_cube_map;
-int GLAD_GL_NV_viewport_array2;
-int GLAD_GL_ARB_texture_stencil8;
-int GLAD_GL_EXT_index_func;
-int GLAD_GL_EXT_memory_object_fd;
-int GLAD_GL_OES_compressed_paletted_texture;
-int GLAD_GL_MESA_shader_integer_functions;
-int GLAD_GL_NV_shader_buffer_load;
-int GLAD_GL_EXT_color_subtable;
-int GLAD_GL_SUNX_constant_data;
-int GLAD_GL_EXT_texture_compression_s3tc;
-int GLAD_GL_EXT_multi_draw_arrays;
-int GLAD_GL_ARB_shader_atomic_counters;
-int GLAD_GL_ARB_arrays_of_arrays;
-int GLAD_GL_NV_conditional_render;
-int GLAD_GL_EXT_texture_env_combine;
-int GLAD_GL_NV_fog_distance;
-int GLAD_GL_SGIX_async_histogram;
-int GLAD_GL_MESA_resize_buffers;
-int GLAD_GL_NV_light_max_exponent;
-int GLAD_GL_NV_texture_env_combine4;
-int GLAD_GL_ARB_spirv_extensions;
-int GLAD_GL_ARB_texture_view;
-int GLAD_GL_ARB_texture_env_combine;
-int GLAD_GL_ARB_map_buffer_range;
-int GLAD_GL_EXT_convolution;
-int GLAD_GL_NV_compute_program5;
-int GLAD_GL_NV_vertex_attrib_integer_64bit;
-int GLAD_GL_EXT_paletted_texture;
-int GLAD_GL_ARB_texture_buffer_object;
-int GLAD_GL_ATI_pn_triangles;
-int GLAD_GL_SGIX_resample;
-int GLAD_GL_SGIX_flush_raster;
-int GLAD_GL_EXT_light_texture;
-int GLAD_GL_ARB_point_sprite;
-int GLAD_GL_SUN_convolution_border_modes;
-int GLAD_GL_EXT_semaphore_fd;
-int GLAD_GL_NV_parameter_buffer_object2;
-int GLAD_GL_ARB_half_float_pixel;
-int GLAD_GL_NV_tessellation_program5;
-int GLAD_GL_REND_screen_coordinates;
-int GLAD_GL_EXT_shared_texture_palette;
-int GLAD_GL_EXT_packed_float;
-int GLAD_GL_OML_subsample;
-int GLAD_GL_SGIX_vertex_preclip;
-int GLAD_GL_SGIX_texture_scale_bias;
-int GLAD_GL_AMD_draw_buffers_blend;
-int GLAD_GL_APPLE_texture_range;
-int GLAD_GL_EXT_texture_array;
-int GLAD_GL_NV_texture_barrier;
-int GLAD_GL_ARB_texture_query_levels;
-int GLAD_GL_NV_texgen_emboss;
-int GLAD_GL_EXT_texture_swizzle;
-int GLAD_GL_ARB_texture_rg;
-int GLAD_GL_ARB_vertex_type_2_10_10_10_rev;
-int GLAD_GL_ARB_fragment_shader;
-int GLAD_GL_3DFX_tbuffer;
-int GLAD_GL_GREMEDY_frame_terminator;
-int GLAD_GL_IBM_cull_vertex;
-int GLAD_GL_EXT_separate_shader_objects;
-int GLAD_GL_NV_texture_multisample;
-int GLAD_GL_ARB_shader_objects;
-int GLAD_GL_ARB_framebuffer_object;
-int GLAD_GL_EXT_external_buffer;
-int GLAD_GL_ATI_envmap_bumpmap;
-int GLAD_GL_AMD_shader_explicit_vertex_parameter;
-int GLAD_GL_ARB_robust_buffer_access_behavior;
-int GLAD_GL_ARB_shader_stencil_export;
-int GLAD_GL_NV_texture_rectangle;
-int GLAD_GL_ARB_enhanced_layouts;
-int GLAD_GL_ARB_texture_rectangle;
-int GLAD_GL_SGI_texture_color_table;
-int GLAD_GL_NV_viewport_swizzle;
-int GLAD_GL_ATI_map_object_buffer;
-int GLAD_GL_ARB_robustness;
-int GLAD_GL_NV_pixel_data_range;
-int GLAD_GL_EXT_framebuffer_blit;
-int GLAD_GL_ARB_gpu_shader_fp64;
-int GLAD_GL_NV_command_list;
-int GLAD_GL_SGIX_depth_texture;
-int GLAD_GL_AMD_framebuffer_sample_positions;
-int GLAD_GL_GREMEDY_string_marker;
-int GLAD_GL_ARB_texture_compression_bptc;
-int GLAD_GL_EXT_subtexture;
-int GLAD_GL_EXT_pixel_transform_color_table;
-int GLAD_GL_EXT_texture_compression_rgtc;
-int GLAD_GL_ARB_shader_atomic_counter_ops;
-int GLAD_GL_SGIX_depth_pass_instrument;
-int GLAD_GL_EXT_gpu_program_parameters;
-int GLAD_GL_NV_evaluators;
-int GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent;
-int GLAD_GL_SGIS_texture_filter4;
-int GLAD_GL_AMD_performance_monitor;
-int GLAD_GL_NV_geometry_shader4;
-int GLAD_GL_EXT_stencil_clear_tag;
-int GLAD_GL_NV_vertex_program1_1;
-int GLAD_GL_NV_present_video;
-int GLAD_GL_ARB_texture_compression_rgtc;
-int GLAD_GL_HP_convolution_border_modes;
-int GLAD_GL_EXT_shader_integer_mix;
-int GLAD_GL_SGIX_framezoom;
-int GLAD_GL_ARB_stencil_texturing;
-int GLAD_GL_ARB_shader_clock;
-int GLAD_GL_NV_shader_atomic_fp16_vector;
-int GLAD_GL_SGIX_fog_offset;
-int GLAD_GL_ARB_draw_elements_base_vertex;
-int GLAD_GL_INGR_interlace_read;
-int GLAD_GL_NV_transform_feedback;
-int GLAD_GL_NV_fragment_program;
-int GLAD_GL_AMD_stencil_operation_extended;
-int GLAD_GL_ARB_seamless_cubemap_per_texture;
-int GLAD_GL_ARB_instanced_arrays;
-int GLAD_GL_ARB_get_texture_sub_image;
-int GLAD_GL_NV_vertex_array_range2;
-int GLAD_GL_KHR_robustness;
-int GLAD_GL_AMD_sparse_texture;
-int GLAD_GL_ARB_clip_control;
-int GLAD_GL_NV_fragment_coverage_to_color;
-int GLAD_GL_NV_fence;
-int GLAD_GL_ARB_texture_buffer_range;
-int GLAD_GL_SUN_mesh_array;
-int GLAD_GL_ARB_vertex_attrib_binding;
-int GLAD_GL_ARB_framebuffer_no_attachments;
-int GLAD_GL_ARB_cl_event;
-int GLAD_GL_EXT_vertex_weighting;
-int GLAD_GL_ARB_derivative_control;
-int GLAD_GL_NV_packed_depth_stencil;
-int GLAD_GL_OES_single_precision;
-int GLAD_GL_NV_primitive_restart;
-int GLAD_GL_SUN_global_alpha;
-int GLAD_GL_ARB_fragment_shader_interlock;
-int GLAD_GL_EXT_texture_object;
-int GLAD_GL_AMD_name_gen_delete;
-int GLAD_GL_NV_texture_compression_vtc;
-int GLAD_GL_NV_sample_mask_override_coverage;
-int GLAD_GL_NV_texture_shader3;
-int GLAD_GL_MESA_tile_raster_order;
-int GLAD_GL_ARB_texture_filter_anisotropic;
-int GLAD_GL_EXT_texture;
-int GLAD_GL_ARB_buffer_storage;
-int GLAD_GL_AMD_shader_atomic_counter_ops;
-int GLAD_GL_APPLE_vertex_program_evaluators;
-int GLAD_GL_AMD_texture_gather_bias_lod;
-int GLAD_GL_NV_texgen_reflection;
-int GLAD_GL_ARB_explicit_uniform_location;
-int GLAD_GL_ARB_depth_buffer_float;
-int GLAD_GL_NV_path_rendering_shared_edge;
-int GLAD_GL_SGIX_shadow_ambient;
-int GLAD_GL_ARB_texture_cube_map;
-int GLAD_GL_AMD_vertex_shader_viewport_index;
-int GLAD_GL_SGIX_list_priority;
-int GLAD_GL_NV_vertex_buffer_unified_memory;
-int GLAD_GL_NV_uniform_buffer_unified_memory;
-int GLAD_GL_ARB_clear_texture;
-int GLAD_GL_ATI_texture_env_combine3;
-int GLAD_GL_NV_depth_clamp;
-int GLAD_GL_ARB_map_buffer_alignment;
-int GLAD_GL_EXT_memory_object;
-int GLAD_GL_NV_blend_equation_advanced;
-int GLAD_GL_SGIS_sharpen_texture;
-int GLAD_GL_KHR_robust_buffer_access_behavior;
-int GLAD_GL_ARB_pipeline_statistics_query;
-int GLAD_GL_ARB_vertex_program;
-int GLAD_GL_ARB_texture_rgb10_a2ui;
-int GLAD_GL_OML_interlace;
-int GLAD_GL_ATI_pixel_format_float;
-int GLAD_GL_NV_clip_space_w_scaling;
-int GLAD_GL_ARB_vertex_buffer_object;
-int GLAD_GL_EXT_shadow_funcs;
-int GLAD_GL_ATI_text_fragment_shader;
-int GLAD_GL_NV_vertex_array_range;
-int GLAD_GL_SGIX_fragment_lighting;
-int GLAD_GL_AMD_shader_ballot;
-int GLAD_GL_NV_texture_expand_normal;
-int GLAD_GL_NV_framebuffer_multisample_coverage;
-int GLAD_GL_EXT_timer_query;
-int GLAD_GL_EXT_vertex_array_bgra;
-int GLAD_GL_NV_bindless_texture;
-int GLAD_GL_KHR_debug;
-int GLAD_GL_SGIS_texture_border_clamp;
-int GLAD_GL_ATI_vertex_attrib_array_object;
-int GLAD_GL_SGIX_clipmap;
-int GLAD_GL_EXT_geometry_shader4;
-int GLAD_GL_ARB_shader_texture_image_samples;
-int GLAD_GL_MESA_ycbcr_texture;
-int GLAD_GL_MESAX_texture_stack;
-int GLAD_GL_AMD_seamless_cubemap_per_texture;
-int GLAD_GL_EXT_bindable_uniform;
-int GLAD_GL_KHR_texture_compression_astc_hdr;
-int GLAD_GL_ARB_shader_ballot;
-int GLAD_GL_KHR_blend_equation_advanced;
-int GLAD_GL_ARB_fragment_program_shadow;
-int GLAD_GL_ATI_element_array;
-int GLAD_GL_AMD_texture_texture4;
-int GLAD_GL_SGIX_reference_plane;
-int GLAD_GL_EXT_stencil_two_side;
-int GLAD_GL_ARB_transform_feedback_overflow_query;
-int GLAD_GL_SGIX_texture_lod_bias;
-int GLAD_GL_KHR_no_error;
-int GLAD_GL_NV_explicit_multisample;
-int GLAD_GL_NV_stereo_view_rendering;
-int GLAD_GL_IBM_static_data;
-int GLAD_GL_EXT_clip_volume_hint;
-int GLAD_GL_EXT_texture_perturb_normal;
-int GLAD_GL_NV_fragment_program2;
-int GLAD_GL_NV_fragment_program4;
-int GLAD_GL_EXT_point_parameters;
-int GLAD_GL_PGI_misc_hints;
-int GLAD_GL_EXT_EGL_image_storage;
-int GLAD_GL_SGIX_subsample;
-int GLAD_GL_AMD_shader_stencil_export;
-int GLAD_GL_ARB_shader_texture_lod;
-int GLAD_GL_ARB_vertex_shader;
-int GLAD_GL_ARB_depth_clamp;
-int GLAD_GL_SGIS_texture_select;
-int GLAD_GL_NV_texture_shader;
-int GLAD_GL_ARB_tessellation_shader;
-int GLAD_GL_EXT_draw_buffers2;
-int GLAD_GL_ARB_vertex_attrib_64bit;
-int GLAD_GL_EXT_texture_filter_minmax;
-int GLAD_GL_NV_query_resource;
-int GLAD_GL_AMD_interleaved_elements;
-int GLAD_GL_ARB_fragment_program;
-int GLAD_GL_OML_resample;
-int GLAD_GL_APPLE_ycbcr_422;
-int GLAD_GL_SGIX_texture_add_env;
-int GLAD_GL_ARB_shadow_ambient;
-int GLAD_GL_ARB_texture_storage;
-int GLAD_GL_EXT_pixel_buffer_object;
-int GLAD_GL_ARB_copy_image;
-int GLAD_GL_SGIS_pixel_texture;
-int GLAD_GL_SGIS_generate_mipmap;
-int GLAD_GL_SGIX_instruments;
-int GLAD_GL_ARB_fragment_layer_viewport;
-int GLAD_GL_ARB_shader_storage_buffer_object;
-int GLAD_GL_EXT_sparse_texture2;
-int GLAD_GL_EXT_blend_minmax;
-int GLAD_GL_MESA_pack_invert;
-int GLAD_GL_ARB_base_instance;
-int GLAD_GL_SGIX_convolution_accuracy;
-int GLAD_GL_PGI_vertex_hints;
-int GLAD_GL_AMD_transform_feedback4;
-int GLAD_GL_ARB_ES3_1_compatibility;
-int GLAD_GL_EXT_memory_object_win32;
-int GLAD_GL_EXT_texture_integer;
-int GLAD_GL_ARB_texture_multisample;
-int GLAD_GL_ATI_vertex_streams;
-int GLAD_GL_AMD_gpu_shader_int64;
-int GLAD_GL_S3_s3tc;
-int GLAD_GL_ARB_query_buffer_object;
-int GLAD_GL_AMD_vertex_shader_tessellator;
-int GLAD_GL_ARB_invalidate_subdata;
-int GLAD_GL_NV_draw_vulkan_image;
-int GLAD_GL_EXT_index_material;
-int GLAD_GL_NVX_linked_gpu_multicast;
-int GLAD_GL_NV_blend_equation_advanced_coherent;
-int GLAD_GL_KHR_texture_compression_astc_sliced_3d;
-int GLAD_GL_INTEL_parallel_arrays;
-int GLAD_GL_ATI_draw_buffers;
-int GLAD_GL_WIN_specular_fog;
-int GLAD_GL_EXT_cmyka;
-int GLAD_GL_SGIX_pixel_texture;
-int GLAD_GL_APPLE_specular_vector;
-int GLAD_GL_ARB_compatibility;
-int GLAD_GL_ARB_timer_query;
-int GLAD_GL_SGIX_interlace;
-int GLAD_GL_NV_parameter_buffer_object;
-int GLAD_GL_AMD_shader_trinary_minmax;
-int GLAD_GL_ARB_direct_state_access;
-int GLAD_GL_EXT_rescale_normal;
-int GLAD_GL_ARB_pixel_buffer_object;
-int GLAD_GL_ARB_uniform_buffer_object;
-int GLAD_GL_ARB_vertex_type_10f_11f_11f_rev;
-int GLAD_GL_ARB_texture_swizzle;
-int GLAD_GL_NV_transform_feedback2;
-int GLAD_GL_SGIX_async_pixel;
-int GLAD_GL_NV_fragment_program_option;
-int GLAD_GL_ARB_explicit_attrib_location;
-int GLAD_GL_EXT_blend_color;
-int GLAD_GL_NV_shader_thread_group;
-int GLAD_GL_EXT_stencil_wrap;
-int GLAD_GL_EXT_index_array_formats;
-int GLAD_GL_OVR_multiview2;
-int GLAD_GL_EXT_histogram;
-int GLAD_GL_EXT_polygon_offset;
-int GLAD_GL_SGIS_point_parameters;
-int GLAD_GL_SGIX_ycrcb;
-int GLAD_GL_EXT_direct_state_access;
-int GLAD_GL_ARB_cull_distance;
-int GLAD_GL_AMD_sample_positions;
-int GLAD_GL_NV_vertex_program;
-int GLAD_GL_NV_shader_thread_shuffle;
-int GLAD_GL_ARB_shader_precision;
-int GLAD_GL_EXT_vertex_shader;
-int GLAD_GL_EXT_blend_func_separate;
-int GLAD_GL_APPLE_fence;
-int GLAD_GL_NV_query_resource_tag;
-int GLAD_GL_OES_byte_coordinates;
-int GLAD_GL_ARB_transpose_matrix;
-int GLAD_GL_ARB_provoking_vertex;
-int GLAD_GL_EXT_fog_coord;
-int GLAD_GL_EXT_vertex_array;
-int GLAD_GL_ARB_half_float_vertex;
-int GLAD_GL_EXT_blend_equation_separate;
-int GLAD_GL_NV_framebuffer_mixed_samples;
-int GLAD_GL_NVX_conditional_render;
-int GLAD_GL_ARB_multi_draw_indirect;
-int GLAD_GL_EXT_raster_multisample;
-int GLAD_GL_NV_copy_image;
-int GLAD_GL_HP_texture_lighting;
-int GLAD_GL_INTEL_framebuffer_CMAA;
-int GLAD_GL_ARB_transform_feedback2;
-int GLAD_GL_ARB_transform_feedback3;
-int GLAD_GL_SGIX_ycrcba;
-int GLAD_GL_EXT_debug_marker;
-int GLAD_GL_EXT_bgra;
-int GLAD_GL_ARB_sparse_texture_clamp;
-int GLAD_GL_EXT_pixel_transform;
-int GLAD_GL_ARB_conservative_depth;
-int GLAD_GL_ATI_fragment_shader;
-int GLAD_GL_ARB_vertex_array_object;
-int GLAD_GL_SUN_triangle_list;
-int GLAD_GL_EXT_texture_env_add;
-int GLAD_GL_EXT_packed_depth_stencil;
-int GLAD_GL_EXT_texture_mirror_clamp;
-int GLAD_GL_NV_multisample_filter_hint;
-int GLAD_GL_APPLE_float_pixels;
-int GLAD_GL_ARB_transform_feedback_instanced;
-int GLAD_GL_SGIX_async;
-int GLAD_GL_EXT_texture_compression_latc;
-int GLAD_GL_NV_robustness_video_memory_purge;
-int GLAD_GL_ARB_shading_language_100;
-int GLAD_GL_INTEL_performance_query;
-int GLAD_GL_ARB_texture_mirror_clamp_to_edge;
-int GLAD_GL_NV_gpu_shader5;
-int GLAD_GL_NV_bindless_multi_draw_indirect_count;
-int GLAD_GL_ARB_ES2_compatibility;
-int GLAD_GL_ARB_indirect_parameters;
-int GLAD_GL_EXT_window_rectangles;
-int GLAD_GL_NV_half_float;
-int GLAD_GL_ARB_ES3_2_compatibility;
-int GLAD_GL_ATI_texture_mirror_once;
-int GLAD_GL_IBM_rasterpos_clip;
-int GLAD_GL_EXT_semaphore;
-int GLAD_GL_SGIX_shadow;
-int GLAD_GL_EXT_polygon_offset_clamp;
-int GLAD_GL_NV_deep_texture3D;
-int GLAD_GL_ARB_shader_draw_parameters;
-int GLAD_GL_SGIX_calligraphic_fragment;
-int GLAD_GL_ARB_shader_bit_encoding;
-int GLAD_GL_EXT_compiled_vertex_array;
-int GLAD_GL_NV_depth_buffer_float;
-int GLAD_GL_NV_occlusion_query;
-int GLAD_GL_APPLE_flush_buffer_range;
-int GLAD_GL_ARB_imaging;
-int GLAD_GL_NV_shader_atomic_float;
-int GLAD_GL_ARB_draw_buffers_blend;
-int GLAD_GL_AMD_gcn_shader;
-int GLAD_GL_AMD_blend_minmax_factor;
-int GLAD_GL_EXT_texture_sRGB_decode;
-int GLAD_GL_ARB_shading_language_420pack;
-int GLAD_GL_ARB_shader_viewport_layer_array;
-int GLAD_GL_ATI_meminfo;
-int GLAD_GL_EXT_abgr;
-int GLAD_GL_AMD_pinned_memory;
-int GLAD_GL_EXT_texture_snorm;
-int GLAD_GL_SGIX_texture_coordinate_clamp;
-int GLAD_GL_ARB_clear_buffer_object;
-int GLAD_GL_ARB_multisample;
-int GLAD_GL_EXT_debug_label;
-int GLAD_GL_ARB_sample_shading;
-int GLAD_GL_NV_internalformat_sample_query;
-int GLAD_GL_INTEL_map_texture;
-int GLAD_GL_ARB_texture_env_crossbar;
-int GLAD_GL_EXT_422_pixels;
-int GLAD_GL_NV_blend_minmax_factor;
-int GLAD_GL_NV_conservative_raster_pre_snap_triangles;
-int GLAD_GL_ARB_compute_shader;
-int GLAD_GL_EXT_blend_logic_op;
-int GLAD_GL_ARB_blend_func_extended;
-int GLAD_GL_IBM_vertex_array_lists;
-int GLAD_GL_ARB_color_buffer_float;
-int GLAD_GL_ARB_bindless_texture;
-int GLAD_GL_ARB_window_pos;
-int GLAD_GL_ARB_internalformat_query;
-int GLAD_GL_ARB_shadow;
-int GLAD_GL_ARB_texture_mirrored_repeat;
-int GLAD_GL_EXT_shader_image_load_store;
-int GLAD_GL_EXT_copy_texture;
-int GLAD_GL_NV_register_combiners2;
-int GLAD_GL_SGIX_ycrcb_subsample;
-int GLAD_GL_NV_alpha_to_coverage_dither_control;
-int GLAD_GL_SGIX_ir_instrument1;
-int GLAD_GL_NV_draw_texture;
-int GLAD_GL_EXT_texture_shared_exponent;
-int GLAD_GL_NV_texture_shader2;
-int GLAD_GL_EXT_draw_instanced;
-int GLAD_GL_NV_copy_depth_to_color;
-int GLAD_GL_ARB_viewport_array;
-int GLAD_GL_ARB_separate_shader_objects;
-int GLAD_GL_NV_conservative_raster_pre_snap;
-int GLAD_GL_EXT_depth_bounds_test;
-int GLAD_GL_HP_image_transform;
-int GLAD_GL_ARB_texture_env_add;
-int GLAD_GL_NV_video_capture;
-int GLAD_GL_ARB_sampler_objects;
-int GLAD_GL_ARB_matrix_palette;
-int GLAD_GL_SGIS_texture_color_mask;
-int GLAD_GL_EXT_packed_pixels;
-int GLAD_GL_EXT_coordinate_frame;
-int GLAD_GL_ARB_texture_compression;
-int GLAD_GL_ARB_multi_bind;
-int GLAD_GL_APPLE_aux_depth_stencil;
-int GLAD_GL_ARB_shader_subroutine;
-int GLAD_GL_EXT_framebuffer_sRGB;
-int GLAD_GL_ARB_texture_storage_multisample;
-int GLAD_GL_KHR_blend_equation_advanced_coherent;
-int GLAD_GL_EXT_vertex_attrib_64bit;
-int GLAD_GL_NV_shader_atomic_float64;
-int GLAD_GL_ARB_depth_texture;
-int GLAD_GL_NV_shader_buffer_store;
-int GLAD_GL_OES_query_matrix;
-int GLAD_GL_MESA_window_pos;
-int GLAD_GL_NV_fill_rectangle;
-int GLAD_GL_NV_shader_storage_buffer_object;
-int GLAD_GL_ARB_texture_query_lod;
-int GLAD_GL_ARB_copy_buffer;
-int GLAD_GL_ARB_shader_image_size;
-int GLAD_GL_NV_shader_atomic_counters;
-int GLAD_GL_APPLE_object_purgeable;
-int GLAD_GL_ARB_occlusion_query;
-int GLAD_GL_INGR_color_clamp;
-int GLAD_GL_SGI_color_table;
-int GLAD_GL_NV_gpu_program5_mem_extended;
-int GLAD_GL_ARB_texture_cube_map_array;
-int GLAD_GL_SGIX_scalebias_hint;
-int GLAD_GL_EXT_gpu_shader4;
-int GLAD_GL_NV_geometry_program4;
-int GLAD_GL_EXT_framebuffer_multisample_blit_scaled;
-int GLAD_GL_AMD_debug_output;
-int GLAD_GL_ARB_texture_border_clamp;
-int GLAD_GL_EXT_win32_keyed_mutex;
-int GLAD_GL_ARB_fragment_coord_conventions;
-int GLAD_GL_ARB_multitexture;
-int GLAD_GL_SGIX_polynomial_ffd;
-int GLAD_GL_EXT_texture_env_dot3;
-int GLAD_GL_EXT_provoking_vertex;
-int GLAD_GL_ARB_point_parameters;
-int GLAD_GL_ARB_shader_image_load_store;
-int GLAD_GL_ARB_conditional_render_inverted;
-int GLAD_GL_HP_occlusion_test;
-int GLAD_GL_ARB_ES3_compatibility;
-int GLAD_GL_ARB_texture_barrier;
-int GLAD_GL_ARB_texture_buffer_object_rgb32;
-int GLAD_GL_NV_bindless_multi_draw_indirect;
-int GLAD_GL_SGIX_texture_multi_buffer;
-int GLAD_GL_INTEL_blackhole_render;
-int GLAD_GL_AMD_shader_image_load_store_lod;
-int GLAD_GL_KHR_texture_compression_astc_ldr;
-int GLAD_GL_3DFX_multisample;
-int GLAD_GL_INTEL_fragment_shader_ordering;
-int GLAD_GL_ARB_texture_env_dot3;
-int GLAD_GL_NV_gpu_program4;
-int GLAD_GL_NV_gpu_program5;
-int GLAD_GL_NV_float_buffer;
-int GLAD_GL_SGIS_texture_edge_clamp;
-int GLAD_GL_ARB_framebuffer_sRGB;
-int GLAD_GL_SUN_slice_accum;
-int GLAD_GL_EXT_index_texture;
-int GLAD_GL_EXT_shader_image_load_formatted;
-int GLAD_GL_ARB_geometry_shader4;
-int GLAD_GL_EXT_separate_specular_color;
-int GLAD_GL_AMD_depth_clamp_separate;
-int GLAD_GL_NV_conservative_raster;
-int GLAD_GL_ARB_sparse_texture2;
-int GLAD_GL_SGIX_sprite;
-int GLAD_GL_ARB_get_program_binary;
-int GLAD_GL_AMD_occlusion_query_event;
-int GLAD_GL_SGIS_multisample;
-int GLAD_GL_EXT_framebuffer_object;
-int GLAD_GL_ARB_robustness_isolation;
-int GLAD_GL_ARB_vertex_array_bgra;
-int GLAD_GL_APPLE_vertex_array_range;
-int GLAD_GL_AMD_query_buffer_object;
-int GLAD_GL_NV_register_combiners;
-int GLAD_GL_ARB_draw_buffers;
-int GLAD_GL_NVX_blend_equation_advanced_multi_draw_buffers;
-int GLAD_GL_AMD_gpu_shader_int16;
-int GLAD_GL_ARB_debug_output;
-int GLAD_GL_EXT_shader_framebuffer_fetch;
-int GLAD_GL_SGI_color_matrix;
-int GLAD_GL_EXT_cull_vertex;
-int GLAD_GL_EXT_texture_sRGB;
-int GLAD_GL_APPLE_row_bytes;
-int GLAD_GL_NV_conservative_raster_underestimation;
-int GLAD_GL_IBM_multimode_draw_arrays;
-int GLAD_GL_KHR_parallel_shader_compile;
-int GLAD_GL_APPLE_vertex_array_object;
-int GLAD_GL_3DFX_texture_compression_FXT1;
-int GLAD_GL_NV_fragment_shader_interlock;
-int GLAD_GL_AMD_conservative_depth;
-int GLAD_GL_ARB_texture_float;
-int GLAD_GL_ARB_compressed_texture_pixel_storage;
-int GLAD_GL_SGIS_detail_texture;
-int GLAD_GL_NV_geometry_shader_passthrough;
-int GLAD_GL_ARB_draw_instanced;
-int GLAD_GL_OES_read_format;
-int GLAD_GL_ATI_texture_float;
-int GLAD_GL_ARB_texture_gather;
-int GLAD_GL_AMD_vertex_shader_layer;
-int GLAD_GL_ARB_shading_language_include;
-int GLAD_GL_APPLE_client_storage;
-int GLAD_GL_WIN_phong_shading;
-int GLAD_GL_INGR_blend_func_separate;
-int GLAD_GL_NV_path_rendering;
-int GLAD_GL_NV_conservative_raster_dilate;
-int GLAD_GL_AMD_gpu_shader_half_float;
-int GLAD_GL_ARB_post_depth_coverage;
-int GLAD_GL_ARB_texture_non_power_of_two;
-int GLAD_GL_APPLE_rgb_422;
-int GLAD_GL_EXT_texture_lod_bias;
-int GLAD_GL_ARB_gpu_shader_int64;
-int GLAD_GL_ARB_seamless_cube_map;
-int GLAD_GL_ARB_shader_group_vote;
-int GLAD_GL_NV_vdpau_interop;
-int GLAD_GL_ARB_occlusion_query2;
-int GLAD_GL_ARB_internalformat_query2;
-int GLAD_GL_EXT_texture_filter_anisotropic;
-int GLAD_GL_SUN_vertex;
-int GLAD_GL_EXT_transform_feedback;
-int GLAD_GL_SGIX_igloo_interface;
-int GLAD_GL_SGIS_texture_lod;
-int GLAD_GL_NV_vertex_program3;
-int GLAD_GL_ARB_draw_indirect;
-int GLAD_GL_NV_vertex_program4;
-int GLAD_GL_AMD_transform_feedback3_lines_triangles;
-int GLAD_GL_SGIS_fog_function;
-int GLAD_GL_EXT_x11_sync_object;
-int GLAD_GL_ARB_sync;
-int GLAD_GL_NV_texture_rectangle_compressed;
-int GLAD_GL_NV_sample_locations;
-int GLAD_GL_NV_gpu_multicast;
-int GLAD_GL_ARB_gl_spirv;
-int GLAD_GL_ARB_compute_variable_group_size;
-int GLAD_GL_OES_fixed_point;
-int GLAD_GL_MESA_program_binary_formats;
-int GLAD_GL_NV_blend_square;
-int GLAD_GL_EXT_framebuffer_multisample;
-int GLAD_GL_ARB_gpu_shader5;
-int GLAD_GL_SGIS_texture4D;
-int GLAD_GL_EXT_texture3D;
-int GLAD_GL_EXT_multisample;
-int GLAD_GL_EXT_secondary_color;
-int GLAD_GL_INTEL_conservative_rasterization;
-int GLAD_GL_ARB_texture_filter_minmax;
-int GLAD_GL_ATI_vertex_array_object;
-int GLAD_GL_ARB_parallel_shader_compile;
-int GLAD_GL_NVX_gpu_memory_info;
-int GLAD_GL_ARB_sparse_texture;
-int GLAD_GL_SGIS_point_line_texgen;
-int GLAD_GL_ARB_sample_locations;
-int GLAD_GL_ARB_sparse_buffer;
-int GLAD_GL_ARB_polygon_offset_clamp;
-int GLAD_GL_EXT_draw_range_elements;
-int GLAD_GL_SGIX_blend_alpha_minmax;
-int GLAD_GL_KHR_context_flush_control;
-PFNGLTBUFFERMASK3DFXPROC glad_glTbufferMask3DFX;
-PFNGLDEBUGMESSAGEENABLEAMDPROC glad_glDebugMessageEnableAMD;
-PFNGLDEBUGMESSAGEINSERTAMDPROC glad_glDebugMessageInsertAMD;
-PFNGLDEBUGMESSAGECALLBACKAMDPROC glad_glDebugMessageCallbackAMD;
-PFNGLGETDEBUGMESSAGELOGAMDPROC glad_glGetDebugMessageLogAMD;
-PFNGLBLENDFUNCINDEXEDAMDPROC glad_glBlendFuncIndexedAMD;
-PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC glad_glBlendFuncSeparateIndexedAMD;
-PFNGLBLENDEQUATIONINDEXEDAMDPROC glad_glBlendEquationIndexedAMD;
-PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC glad_glBlendEquationSeparateIndexedAMD;
-PFNGLFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC glad_glFramebufferSamplePositionsfvAMD;
-PFNGLNAMEDFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC glad_glNamedFramebufferSamplePositionsfvAMD;
-PFNGLGETFRAMEBUFFERPARAMETERFVAMDPROC glad_glGetFramebufferParameterfvAMD;
-PFNGLGETNAMEDFRAMEBUFFERPARAMETERFVAMDPROC glad_glGetNamedFramebufferParameterfvAMD;
-PFNGLUNIFORM1I64NVPROC glad_glUniform1i64NV;
-PFNGLUNIFORM2I64NVPROC glad_glUniform2i64NV;
-PFNGLUNIFORM3I64NVPROC glad_glUniform3i64NV;
-PFNGLUNIFORM4I64NVPROC glad_glUniform4i64NV;
-PFNGLUNIFORM1I64VNVPROC glad_glUniform1i64vNV;
-PFNGLUNIFORM2I64VNVPROC glad_glUniform2i64vNV;
-PFNGLUNIFORM3I64VNVPROC glad_glUniform3i64vNV;
-PFNGLUNIFORM4I64VNVPROC glad_glUniform4i64vNV;
-PFNGLUNIFORM1UI64NVPROC glad_glUniform1ui64NV;
-PFNGLUNIFORM2UI64NVPROC glad_glUniform2ui64NV;
-PFNGLUNIFORM3UI64NVPROC glad_glUniform3ui64NV;
-PFNGLUNIFORM4UI64NVPROC glad_glUniform4ui64NV;
-PFNGLUNIFORM1UI64VNVPROC glad_glUniform1ui64vNV;
-PFNGLUNIFORM2UI64VNVPROC glad_glUniform2ui64vNV;
-PFNGLUNIFORM3UI64VNVPROC glad_glUniform3ui64vNV;
-PFNGLUNIFORM4UI64VNVPROC glad_glUniform4ui64vNV;
-PFNGLGETUNIFORMI64VNVPROC glad_glGetUniformi64vNV;
-PFNGLGETUNIFORMUI64VNVPROC glad_glGetUniformui64vNV;
-PFNGLPROGRAMUNIFORM1I64NVPROC glad_glProgramUniform1i64NV;
-PFNGLPROGRAMUNIFORM2I64NVPROC glad_glProgramUniform2i64NV;
-PFNGLPROGRAMUNIFORM3I64NVPROC glad_glProgramUniform3i64NV;
-PFNGLPROGRAMUNIFORM4I64NVPROC glad_glProgramUniform4i64NV;
-PFNGLPROGRAMUNIFORM1I64VNVPROC glad_glProgramUniform1i64vNV;
-PFNGLPROGRAMUNIFORM2I64VNVPROC glad_glProgramUniform2i64vNV;
-PFNGLPROGRAMUNIFORM3I64VNVPROC glad_glProgramUniform3i64vNV;
-PFNGLPROGRAMUNIFORM4I64VNVPROC glad_glProgramUniform4i64vNV;
-PFNGLPROGRAMUNIFORM1UI64NVPROC glad_glProgramUniform1ui64NV;
-PFNGLPROGRAMUNIFORM2UI64NVPROC glad_glProgramUniform2ui64NV;
-PFNGLPROGRAMUNIFORM3UI64NVPROC glad_glProgramUniform3ui64NV;
-PFNGLPROGRAMUNIFORM4UI64NVPROC glad_glProgramUniform4ui64NV;
-PFNGLPROGRAMUNIFORM1UI64VNVPROC glad_glProgramUniform1ui64vNV;
-PFNGLPROGRAMUNIFORM2UI64VNVPROC glad_glProgramUniform2ui64vNV;
-PFNGLPROGRAMUNIFORM3UI64VNVPROC glad_glProgramUniform3ui64vNV;
-PFNGLPROGRAMUNIFORM4UI64VNVPROC glad_glProgramUniform4ui64vNV;
-PFNGLVERTEXATTRIBPARAMETERIAMDPROC glad_glVertexAttribParameteriAMD;
-PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC glad_glMultiDrawArraysIndirectAMD;
-PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC glad_glMultiDrawElementsIndirectAMD;
-PFNGLGENNAMESAMDPROC glad_glGenNamesAMD;
-PFNGLDELETENAMESAMDPROC glad_glDeleteNamesAMD;
-PFNGLISNAMEAMDPROC glad_glIsNameAMD;
-PFNGLQUERYOBJECTPARAMETERUIAMDPROC glad_glQueryObjectParameteruiAMD;
-PFNGLGETPERFMONITORGROUPSAMDPROC glad_glGetPerfMonitorGroupsAMD;
-PFNGLGETPERFMONITORCOUNTERSAMDPROC glad_glGetPerfMonitorCountersAMD;
-PFNGLGETPERFMONITORGROUPSTRINGAMDPROC glad_glGetPerfMonitorGroupStringAMD;
-PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC glad_glGetPerfMonitorCounterStringAMD;
-PFNGLGETPERFMONITORCOUNTERINFOAMDPROC glad_glGetPerfMonitorCounterInfoAMD;
-PFNGLGENPERFMONITORSAMDPROC glad_glGenPerfMonitorsAMD;
-PFNGLDELETEPERFMONITORSAMDPROC glad_glDeletePerfMonitorsAMD;
-PFNGLSELECTPERFMONITORCOUNTERSAMDPROC glad_glSelectPerfMonitorCountersAMD;
-PFNGLBEGINPERFMONITORAMDPROC glad_glBeginPerfMonitorAMD;
-PFNGLENDPERFMONITORAMDPROC glad_glEndPerfMonitorAMD;
-PFNGLGETPERFMONITORCOUNTERDATAAMDPROC glad_glGetPerfMonitorCounterDataAMD;
-PFNGLSETMULTISAMPLEFVAMDPROC glad_glSetMultisamplefvAMD;
-PFNGLTEXSTORAGESPARSEAMDPROC glad_glTexStorageSparseAMD;
-PFNGLTEXTURESTORAGESPARSEAMDPROC glad_glTextureStorageSparseAMD;
-PFNGLSTENCILOPVALUEAMDPROC glad_glStencilOpValueAMD;
-PFNGLTESSELLATIONFACTORAMDPROC glad_glTessellationFactorAMD;
-PFNGLTESSELLATIONMODEAMDPROC glad_glTessellationModeAMD;
-PFNGLELEMENTPOINTERAPPLEPROC glad_glElementPointerAPPLE;
-PFNGLDRAWELEMENTARRAYAPPLEPROC glad_glDrawElementArrayAPPLE;
-PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC glad_glDrawRangeElementArrayAPPLE;
-PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC glad_glMultiDrawElementArrayAPPLE;
-PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC glad_glMultiDrawRangeElementArrayAPPLE;
-PFNGLGENFENCESAPPLEPROC glad_glGenFencesAPPLE;
-PFNGLDELETEFENCESAPPLEPROC glad_glDeleteFencesAPPLE;
-PFNGLSETFENCEAPPLEPROC glad_glSetFenceAPPLE;
-PFNGLISFENCEAPPLEPROC glad_glIsFenceAPPLE;
-PFNGLTESTFENCEAPPLEPROC glad_glTestFenceAPPLE;
-PFNGLFINISHFENCEAPPLEPROC glad_glFinishFenceAPPLE;
-PFNGLTESTOBJECTAPPLEPROC glad_glTestObjectAPPLE;
-PFNGLFINISHOBJECTAPPLEPROC glad_glFinishObjectAPPLE;
-PFNGLBUFFERPARAMETERIAPPLEPROC glad_glBufferParameteriAPPLE;
-PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glad_glFlushMappedBufferRangeAPPLE;
-PFNGLOBJECTPURGEABLEAPPLEPROC glad_glObjectPurgeableAPPLE;
-PFNGLOBJECTUNPURGEABLEAPPLEPROC glad_glObjectUnpurgeableAPPLE;
-PFNGLGETOBJECTPARAMETERIVAPPLEPROC glad_glGetObjectParameterivAPPLE;
-PFNGLTEXTURERANGEAPPLEPROC glad_glTextureRangeAPPLE;
-PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC glad_glGetTexParameterPointervAPPLE;
-PFNGLBINDVERTEXARRAYAPPLEPROC glad_glBindVertexArrayAPPLE;
-PFNGLDELETEVERTEXARRAYSAPPLEPROC glad_glDeleteVertexArraysAPPLE;
-PFNGLGENVERTEXARRAYSAPPLEPROC glad_glGenVertexArraysAPPLE;
-PFNGLISVERTEXARRAYAPPLEPROC glad_glIsVertexArrayAPPLE;
-PFNGLVERTEXARRAYRANGEAPPLEPROC glad_glVertexArrayRangeAPPLE;
-PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC glad_glFlushVertexArrayRangeAPPLE;
-PFNGLVERTEXARRAYPARAMETERIAPPLEPROC glad_glVertexArrayParameteriAPPLE;
-PFNGLENABLEVERTEXATTRIBAPPLEPROC glad_glEnableVertexAttribAPPLE;
-PFNGLDISABLEVERTEXATTRIBAPPLEPROC glad_glDisableVertexAttribAPPLE;
-PFNGLISVERTEXATTRIBENABLEDAPPLEPROC glad_glIsVertexAttribEnabledAPPLE;
-PFNGLMAPVERTEXATTRIB1DAPPLEPROC glad_glMapVertexAttrib1dAPPLE;
-PFNGLMAPVERTEXATTRIB1FAPPLEPROC glad_glMapVertexAttrib1fAPPLE;
-PFNGLMAPVERTEXATTRIB2DAPPLEPROC glad_glMapVertexAttrib2dAPPLE;
-PFNGLMAPVERTEXATTRIB2FAPPLEPROC glad_glMapVertexAttrib2fAPPLE;
-PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler;
-PFNGLSHADERBINARYPROC glad_glShaderBinary;
-PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat;
-PFNGLDEPTHRANGEFPROC glad_glDepthRangef;
-PFNGLCLEARDEPTHFPROC glad_glClearDepthf;
-PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion;
-PFNGLPRIMITIVEBOUNDINGBOXARBPROC glad_glPrimitiveBoundingBoxARB;
-PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance;
-PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance;
-PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance;
-PFNGLGETTEXTUREHANDLEARBPROC glad_glGetTextureHandleARB;
-PFNGLGETTEXTURESAMPLERHANDLEARBPROC glad_glGetTextureSamplerHandleARB;
-PFNGLMAKETEXTUREHANDLERESIDENTARBPROC glad_glMakeTextureHandleResidentARB;
-PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC glad_glMakeTextureHandleNonResidentARB;
-PFNGLGETIMAGEHANDLEARBPROC glad_glGetImageHandleARB;
-PFNGLMAKEIMAGEHANDLERESIDENTARBPROC glad_glMakeImageHandleResidentARB;
-PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC glad_glMakeImageHandleNonResidentARB;
-PFNGLUNIFORMHANDLEUI64ARBPROC glad_glUniformHandleui64ARB;
-PFNGLUNIFORMHANDLEUI64VARBPROC glad_glUniformHandleui64vARB;
-PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC glad_glProgramUniformHandleui64ARB;
-PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC glad_glProgramUniformHandleui64vARB;
-PFNGLISTEXTUREHANDLERESIDENTARBPROC glad_glIsTextureHandleResidentARB;
-PFNGLISIMAGEHANDLERESIDENTARBPROC glad_glIsImageHandleResidentARB;
-PFNGLVERTEXATTRIBL1UI64ARBPROC glad_glVertexAttribL1ui64ARB;
-PFNGLVERTEXATTRIBL1UI64VARBPROC glad_glVertexAttribL1ui64vARB;
-PFNGLGETVERTEXATTRIBLUI64VARBPROC glad_glGetVertexAttribLui64vARB;
-PFNGLBUFFERSTORAGEPROC glad_glBufferStorage;
-PFNGLCREATESYNCFROMCLEVENTARBPROC glad_glCreateSyncFromCLeventARB;
-PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData;
-PFNGLCLEARBUFFERSUBDATAPROC glad_glClearBufferSubData;
-PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage;
-PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage;
-PFNGLCLIPCONTROLPROC glad_glClipControl;
-PFNGLCLAMPCOLORARBPROC glad_glClampColorARB;
-PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute;
-PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect;
-PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC glad_glDispatchComputeGroupSizeARB;
-PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData;
-PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
-PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
-PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
-PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
-PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks;
-PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase;
-PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange;
-PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv;
-PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v;
-PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v;
-PFNGLCREATEBUFFERSPROC glad_glCreateBuffers;
-PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage;
-PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData;
-PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData;
-PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData;
-PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData;
-PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData;
-PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer;
-PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange;
-PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer;
-PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange;
-PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv;
-PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v;
-PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv;
-PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData;
-PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers;
-PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer;
-PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri;
-PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture;
-PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer;
-PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer;
-PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers;
-PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer;
-PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData;
-PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData;
-PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv;
-PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv;
-PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv;
-PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi;
-PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer;
-PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus;
-PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv;
-PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv;
-PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers;
-PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage;
-PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample;
-PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv;
-PFNGLCREATETEXTURESPROC glad_glCreateTextures;
-PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer;
-PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange;
-PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D;
-PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D;
-PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D;
-PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample;
-PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample;
-PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D;
-PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D;
-PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D;
-PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D;
-PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D;
-PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D;
-PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D;
-PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D;
-PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D;
-PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf;
-PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv;
-PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri;
-PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv;
-PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv;
-PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv;
-PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap;
-PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit;
-PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage;
-PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage;
-PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv;
-PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv;
-PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv;
-PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv;
-PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv;
-PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv;
-PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays;
-PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib;
-PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib;
-PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer;
-PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer;
-PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers;
-PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding;
-PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat;
-PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat;
-PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat;
-PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor;
-PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv;
-PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv;
-PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv;
-PFNGLCREATESAMPLERSPROC glad_glCreateSamplers;
-PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines;
-PFNGLCREATEQUERIESPROC glad_glCreateQueries;
-PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v;
-PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv;
-PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v;
-PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv;
-PFNGLDRAWBUFFERSARBPROC glad_glDrawBuffersARB;
-PFNGLBLENDEQUATIONIARBPROC glad_glBlendEquationiARB;
-PFNGLBLENDEQUATIONSEPARATEIARBPROC glad_glBlendEquationSeparateiARB;
-PFNGLBLENDFUNCIARBPROC glad_glBlendFunciARB;
-PFNGLBLENDFUNCSEPARATEIARBPROC glad_glBlendFuncSeparateiARB;
-PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect;
-PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect;
-PFNGLDRAWARRAYSINSTANCEDARBPROC glad_glDrawArraysInstancedARB;
-PFNGLDRAWELEMENTSINSTANCEDARBPROC glad_glDrawElementsInstancedARB;
-PFNGLPROGRAMSTRINGARBPROC glad_glProgramStringARB;
-PFNGLBINDPROGRAMARBPROC glad_glBindProgramARB;
-PFNGLDELETEPROGRAMSARBPROC glad_glDeleteProgramsARB;
-PFNGLGENPROGRAMSARBPROC glad_glGenProgramsARB;
-PFNGLPROGRAMENVPARAMETER4DARBPROC glad_glProgramEnvParameter4dARB;
-PFNGLPROGRAMENVPARAMETER4DVARBPROC glad_glProgramEnvParameter4dvARB;
-PFNGLPROGRAMENVPARAMETER4FARBPROC glad_glProgramEnvParameter4fARB;
-PFNGLPROGRAMENVPARAMETER4FVARBPROC glad_glProgramEnvParameter4fvARB;
-PFNGLPROGRAMLOCALPARAMETER4DARBPROC glad_glProgramLocalParameter4dARB;
-PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glad_glProgramLocalParameter4dvARB;
-PFNGLPROGRAMLOCALPARAMETER4FARBPROC glad_glProgramLocalParameter4fARB;
-PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glad_glProgramLocalParameter4fvARB;
-PFNGLGETPROGRAMENVPARAMETERDVARBPROC glad_glGetProgramEnvParameterdvARB;
-PFNGLGETPROGRAMENVPARAMETERFVARBPROC glad_glGetProgramEnvParameterfvARB;
-PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glad_glGetProgramLocalParameterdvARB;
-PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glad_glGetProgramLocalParameterfvARB;
-PFNGLGETPROGRAMIVARBPROC glad_glGetProgramivARB;
-PFNGLGETPROGRAMSTRINGARBPROC glad_glGetProgramStringARB;
-PFNGLISPROGRAMARBPROC glad_glIsProgramARB;
-PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri;
-PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv;
-PFNGLPROGRAMPARAMETERIARBPROC glad_glProgramParameteriARB;
-PFNGLFRAMEBUFFERTEXTUREARBPROC glad_glFramebufferTextureARB;
-PFNGLFRAMEBUFFERTEXTURELAYERARBPROC glad_glFramebufferTextureLayerARB;
-PFNGLFRAMEBUFFERTEXTUREFACEARBPROC glad_glFramebufferTextureFaceARB;
-PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary;
-PFNGLPROGRAMBINARYPROC glad_glProgramBinary;
-PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri;
-PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage;
-PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage;
-PFNGLSPECIALIZESHADERARBPROC glad_glSpecializeShaderARB;
-PFNGLUNIFORM1DPROC glad_glUniform1d;
-PFNGLUNIFORM2DPROC glad_glUniform2d;
-PFNGLUNIFORM3DPROC glad_glUniform3d;
-PFNGLUNIFORM4DPROC glad_glUniform4d;
-PFNGLUNIFORM1DVPROC glad_glUniform1dv;
-PFNGLUNIFORM2DVPROC glad_glUniform2dv;
-PFNGLUNIFORM3DVPROC glad_glUniform3dv;
-PFNGLUNIFORM4DVPROC glad_glUniform4dv;
-PFNGLUNIFORMMATRIX2DVPROC glad_glUniformMatrix2dv;
-PFNGLUNIFORMMATRIX3DVPROC glad_glUniformMatrix3dv;
-PFNGLUNIFORMMATRIX4DVPROC glad_glUniformMatrix4dv;
-PFNGLUNIFORMMATRIX2X3DVPROC glad_glUniformMatrix2x3dv;
-PFNGLUNIFORMMATRIX2X4DVPROC glad_glUniformMatrix2x4dv;
-PFNGLUNIFORMMATRIX3X2DVPROC glad_glUniformMatrix3x2dv;
-PFNGLUNIFORMMATRIX3X4DVPROC glad_glUniformMatrix3x4dv;
-PFNGLUNIFORMMATRIX4X2DVPROC glad_glUniformMatrix4x2dv;
-PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv;
-PFNGLGETUNIFORMDVPROC glad_glGetUniformdv;
-PFNGLUNIFORM1I64ARBPROC glad_glUniform1i64ARB;
-PFNGLUNIFORM2I64ARBPROC glad_glUniform2i64ARB;
-PFNGLUNIFORM3I64ARBPROC glad_glUniform3i64ARB;
-PFNGLUNIFORM4I64ARBPROC glad_glUniform4i64ARB;
-PFNGLUNIFORM1I64VARBPROC glad_glUniform1i64vARB;
-PFNGLUNIFORM2I64VARBPROC glad_glUniform2i64vARB;
-PFNGLUNIFORM3I64VARBPROC glad_glUniform3i64vARB;
-PFNGLUNIFORM4I64VARBPROC glad_glUniform4i64vARB;
-PFNGLUNIFORM1UI64ARBPROC glad_glUniform1ui64ARB;
-PFNGLUNIFORM2UI64ARBPROC glad_glUniform2ui64ARB;
-PFNGLUNIFORM3UI64ARBPROC glad_glUniform3ui64ARB;
-PFNGLUNIFORM4UI64ARBPROC glad_glUniform4ui64ARB;
-PFNGLUNIFORM1UI64VARBPROC glad_glUniform1ui64vARB;
-PFNGLUNIFORM2UI64VARBPROC glad_glUniform2ui64vARB;
-PFNGLUNIFORM3UI64VARBPROC glad_glUniform3ui64vARB;
-PFNGLUNIFORM4UI64VARBPROC glad_glUniform4ui64vARB;
-PFNGLGETUNIFORMI64VARBPROC glad_glGetUniformi64vARB;
-PFNGLGETUNIFORMUI64VARBPROC glad_glGetUniformui64vARB;
-PFNGLGETNUNIFORMI64VARBPROC glad_glGetnUniformi64vARB;
-PFNGLGETNUNIFORMUI64VARBPROC glad_glGetnUniformui64vARB;
-PFNGLPROGRAMUNIFORM1I64ARBPROC glad_glProgramUniform1i64ARB;
-PFNGLPROGRAMUNIFORM2I64ARBPROC glad_glProgramUniform2i64ARB;
-PFNGLPROGRAMUNIFORM3I64ARBPROC glad_glProgramUniform3i64ARB;
-PFNGLPROGRAMUNIFORM4I64ARBPROC glad_glProgramUniform4i64ARB;
-PFNGLPROGRAMUNIFORM1I64VARBPROC glad_glProgramUniform1i64vARB;
-PFNGLPROGRAMUNIFORM2I64VARBPROC glad_glProgramUniform2i64vARB;
-PFNGLPROGRAMUNIFORM3I64VARBPROC glad_glProgramUniform3i64vARB;
-PFNGLPROGRAMUNIFORM4I64VARBPROC glad_glProgramUniform4i64vARB;
-PFNGLPROGRAMUNIFORM1UI64ARBPROC glad_glProgramUniform1ui64ARB;
-PFNGLPROGRAMUNIFORM2UI64ARBPROC glad_glProgramUniform2ui64ARB;
-PFNGLPROGRAMUNIFORM3UI64ARBPROC glad_glProgramUniform3ui64ARB;
-PFNGLPROGRAMUNIFORM4UI64ARBPROC glad_glProgramUniform4ui64ARB;
-PFNGLPROGRAMUNIFORM1UI64VARBPROC glad_glProgramUniform1ui64vARB;
-PFNGLPROGRAMUNIFORM2UI64VARBPROC glad_glProgramUniform2ui64vARB;
-PFNGLPROGRAMUNIFORM3UI64VARBPROC glad_glProgramUniform3ui64vARB;
-PFNGLPROGRAMUNIFORM4UI64VARBPROC glad_glProgramUniform4ui64vARB;
-PFNGLCOLORTABLEPROC glad_glColorTable;
-PFNGLCOLORTABLEPARAMETERFVPROC glad_glColorTableParameterfv;
-PFNGLCOLORTABLEPARAMETERIVPROC glad_glColorTableParameteriv;
-PFNGLCOPYCOLORTABLEPROC glad_glCopyColorTable;
-PFNGLGETCOLORTABLEPROC glad_glGetColorTable;
-PFNGLGETCOLORTABLEPARAMETERFVPROC glad_glGetColorTableParameterfv;
-PFNGLGETCOLORTABLEPARAMETERIVPROC glad_glGetColorTableParameteriv;
-PFNGLCOLORSUBTABLEPROC glad_glColorSubTable;
-PFNGLCOPYCOLORSUBTABLEPROC glad_glCopyColorSubTable;
-PFNGLCONVOLUTIONFILTER1DPROC glad_glConvolutionFilter1D;
-PFNGLCONVOLUTIONFILTER2DPROC glad_glConvolutionFilter2D;
-PFNGLCONVOLUTIONPARAMETERFPROC glad_glConvolutionParameterf;
-PFNGLCONVOLUTIONPARAMETERFVPROC glad_glConvolutionParameterfv;
-PFNGLCONVOLUTIONPARAMETERIPROC glad_glConvolutionParameteri;
-PFNGLCONVOLUTIONPARAMETERIVPROC glad_glConvolutionParameteriv;
-PFNGLCOPYCONVOLUTIONFILTER1DPROC glad_glCopyConvolutionFilter1D;
-PFNGLCOPYCONVOLUTIONFILTER2DPROC glad_glCopyConvolutionFilter2D;
-PFNGLGETCONVOLUTIONFILTERPROC glad_glGetConvolutionFilter;
-PFNGLGETCONVOLUTIONPARAMETERFVPROC glad_glGetConvolutionParameterfv;
-PFNGLGETCONVOLUTIONPARAMETERIVPROC glad_glGetConvolutionParameteriv;
-PFNGLGETSEPARABLEFILTERPROC glad_glGetSeparableFilter;
-PFNGLSEPARABLEFILTER2DPROC glad_glSeparableFilter2D;
-PFNGLGETHISTOGRAMPROC glad_glGetHistogram;
-PFNGLGETHISTOGRAMPARAMETERFVPROC glad_glGetHistogramParameterfv;
-PFNGLGETHISTOGRAMPARAMETERIVPROC glad_glGetHistogramParameteriv;
-PFNGLGETMINMAXPROC glad_glGetMinmax;
-PFNGLGETMINMAXPARAMETERFVPROC glad_glGetMinmaxParameterfv;
-PFNGLGETMINMAXPARAMETERIVPROC glad_glGetMinmaxParameteriv;
-PFNGLHISTOGRAMPROC glad_glHistogram;
-PFNGLMINMAXPROC glad_glMinmax;
-PFNGLRESETHISTOGRAMPROC glad_glResetHistogram;
-PFNGLRESETMINMAXPROC glad_glResetMinmax;
-PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC glad_glMultiDrawArraysIndirectCountARB;
-PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC glad_glMultiDrawElementsIndirectCountARB;
-PFNGLVERTEXATTRIBDIVISORARBPROC glad_glVertexAttribDivisorARB;
-PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ;
-PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v;
-PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage;
-PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage;
-PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData;
-PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData;
-PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer;
-PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer;
-PFNGLCURRENTPALETTEMATRIXARBPROC glad_glCurrentPaletteMatrixARB;
-PFNGLMATRIXINDEXUBVARBPROC glad_glMatrixIndexubvARB;
-PFNGLMATRIXINDEXUSVARBPROC glad_glMatrixIndexusvARB;
-PFNGLMATRIXINDEXUIVARBPROC glad_glMatrixIndexuivARB;
-PFNGLMATRIXINDEXPOINTERARBPROC glad_glMatrixIndexPointerARB;
-PFNGLBINDBUFFERSBASEPROC glad_glBindBuffersBase;
-PFNGLBINDBUFFERSRANGEPROC glad_glBindBuffersRange;
-PFNGLBINDTEXTURESPROC glad_glBindTextures;
-PFNGLBINDSAMPLERSPROC glad_glBindSamplers;
-PFNGLBINDIMAGETEXTURESPROC glad_glBindImageTextures;
-PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers;
-PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect;
-PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect;
-PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB;
-PFNGLACTIVETEXTUREARBPROC glad_glActiveTextureARB;
-PFNGLCLIENTACTIVETEXTUREARBPROC glad_glClientActiveTextureARB;
-PFNGLMULTITEXCOORD1DARBPROC glad_glMultiTexCoord1dARB;
-PFNGLMULTITEXCOORD1DVARBPROC glad_glMultiTexCoord1dvARB;
-PFNGLMULTITEXCOORD1FARBPROC glad_glMultiTexCoord1fARB;
-PFNGLMULTITEXCOORD1FVARBPROC glad_glMultiTexCoord1fvARB;
-PFNGLMULTITEXCOORD1IARBPROC glad_glMultiTexCoord1iARB;
-PFNGLMULTITEXCOORD1IVARBPROC glad_glMultiTexCoord1ivARB;
-PFNGLMULTITEXCOORD1SARBPROC glad_glMultiTexCoord1sARB;
-PFNGLMULTITEXCOORD1SVARBPROC glad_glMultiTexCoord1svARB;
-PFNGLMULTITEXCOORD2DARBPROC glad_glMultiTexCoord2dARB;
-PFNGLMULTITEXCOORD2DVARBPROC glad_glMultiTexCoord2dvARB;
-PFNGLMULTITEXCOORD2FARBPROC glad_glMultiTexCoord2fARB;
-PFNGLMULTITEXCOORD2FVARBPROC glad_glMultiTexCoord2fvARB;
-PFNGLMULTITEXCOORD2IARBPROC glad_glMultiTexCoord2iARB;
-PFNGLMULTITEXCOORD2IVARBPROC glad_glMultiTexCoord2ivARB;
-PFNGLMULTITEXCOORD2SARBPROC glad_glMultiTexCoord2sARB;
-PFNGLMULTITEXCOORD2SVARBPROC glad_glMultiTexCoord2svARB;
-PFNGLMULTITEXCOORD3DARBPROC glad_glMultiTexCoord3dARB;
-PFNGLMULTITEXCOORD3DVARBPROC glad_glMultiTexCoord3dvARB;
-PFNGLMULTITEXCOORD3FARBPROC glad_glMultiTexCoord3fARB;
-PFNGLMULTITEXCOORD3FVARBPROC glad_glMultiTexCoord3fvARB;
-PFNGLMULTITEXCOORD3IARBPROC glad_glMultiTexCoord3iARB;
-PFNGLMULTITEXCOORD3IVARBPROC glad_glMultiTexCoord3ivARB;
-PFNGLMULTITEXCOORD3SARBPROC glad_glMultiTexCoord3sARB;
-PFNGLMULTITEXCOORD3SVARBPROC glad_glMultiTexCoord3svARB;
-PFNGLMULTITEXCOORD4DARBPROC glad_glMultiTexCoord4dARB;
-PFNGLMULTITEXCOORD4DVARBPROC glad_glMultiTexCoord4dvARB;
-PFNGLMULTITEXCOORD4FARBPROC glad_glMultiTexCoord4fARB;
-PFNGLMULTITEXCOORD4FVARBPROC glad_glMultiTexCoord4fvARB;
-PFNGLMULTITEXCOORD4IARBPROC glad_glMultiTexCoord4iARB;
-PFNGLMULTITEXCOORD4IVARBPROC glad_glMultiTexCoord4ivARB;
-PFNGLMULTITEXCOORD4SARBPROC glad_glMultiTexCoord4sARB;
-PFNGLMULTITEXCOORD4SVARBPROC glad_glMultiTexCoord4svARB;
-PFNGLGENQUERIESARBPROC glad_glGenQueriesARB;
-PFNGLDELETEQUERIESARBPROC glad_glDeleteQueriesARB;
-PFNGLISQUERYARBPROC glad_glIsQueryARB;
-PFNGLBEGINQUERYARBPROC glad_glBeginQueryARB;
-PFNGLENDQUERYARBPROC glad_glEndQueryARB;
-PFNGLGETQUERYIVARBPROC glad_glGetQueryivARB;
-PFNGLGETQUERYOBJECTIVARBPROC glad_glGetQueryObjectivARB;
-PFNGLGETQUERYOBJECTUIVARBPROC glad_glGetQueryObjectuivARB;
-PFNGLMAXSHADERCOMPILERTHREADSARBPROC glad_glMaxShaderCompilerThreadsARB;
-PFNGLPOINTPARAMETERFARBPROC glad_glPointParameterfARB;
-PFNGLPOINTPARAMETERFVARBPROC glad_glPointParameterfvARB;
-PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp;
-PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv;
-PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex;
-PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName;
-PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv;
-PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation;
-PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glad_glGetProgramResourceLocationIndex;
-PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB;
-PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB;
-PFNGLREADNPIXELSARBPROC glad_glReadnPixelsARB;
-PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC glad_glGetnCompressedTexImageARB;
-PFNGLGETNUNIFORMFVARBPROC glad_glGetnUniformfvARB;
-PFNGLGETNUNIFORMIVARBPROC glad_glGetnUniformivARB;
-PFNGLGETNUNIFORMUIVARBPROC glad_glGetnUniformuivARB;
-PFNGLGETNUNIFORMDVARBPROC glad_glGetnUniformdvARB;
-PFNGLGETNMAPDVARBPROC glad_glGetnMapdvARB;
-PFNGLGETNMAPFVARBPROC glad_glGetnMapfvARB;
-PFNGLGETNMAPIVARBPROC glad_glGetnMapivARB;
-PFNGLGETNPIXELMAPFVARBPROC glad_glGetnPixelMapfvARB;
-PFNGLGETNPIXELMAPUIVARBPROC glad_glGetnPixelMapuivARB;
-PFNGLGETNPIXELMAPUSVARBPROC glad_glGetnPixelMapusvARB;
-PFNGLGETNPOLYGONSTIPPLEARBPROC glad_glGetnPolygonStippleARB;
-PFNGLGETNCOLORTABLEARBPROC glad_glGetnColorTableARB;
-PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB;
-PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB;
-PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB;
-PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB;
-PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glFramebufferSampleLocationsfvARB;
-PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glNamedFramebufferSampleLocationsfvARB;
-PFNGLEVALUATEDEPTHVALUESARBPROC glad_glEvaluateDepthValuesARB;
-PFNGLMINSAMPLESHADINGARBPROC glad_glMinSampleShadingARB;
-PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages;
-PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram;
-PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv;
-PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline;
-PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines;
-PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines;
-PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline;
-PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv;
-PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i;
-PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv;
-PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f;
-PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv;
-PFNGLPROGRAMUNIFORM1DPROC glad_glProgramUniform1d;
-PFNGLPROGRAMUNIFORM1DVPROC glad_glProgramUniform1dv;
-PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui;
-PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv;
-PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i;
-PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv;
-PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f;
-PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv;
-PFNGLPROGRAMUNIFORM2DPROC glad_glProgramUniform2d;
-PFNGLPROGRAMUNIFORM2DVPROC glad_glProgramUniform2dv;
-PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui;
-PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv;
-PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i;
-PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv;
-PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f;
-PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv;
-PFNGLPROGRAMUNIFORM3DPROC glad_glProgramUniform3d;
-PFNGLPROGRAMUNIFORM3DVPROC glad_glProgramUniform3dv;
-PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui;
-PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv;
-PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i;
-PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv;
-PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f;
-PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv;
-PFNGLPROGRAMUNIFORM4DPROC glad_glProgramUniform4d;
-PFNGLPROGRAMUNIFORM4DVPROC glad_glProgramUniform4dv;
-PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui;
-PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv;
-PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv;
-PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv;
-PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv;
-PFNGLPROGRAMUNIFORMMATRIX2DVPROC glad_glProgramUniformMatrix2dv;
-PFNGLPROGRAMUNIFORMMATRIX3DVPROC glad_glProgramUniformMatrix3dv;
-PFNGLPROGRAMUNIFORMMATRIX4DVPROC glad_glProgramUniformMatrix4dv;
-PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv;
-PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv;
-PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv;
-PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv;
-PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv;
-PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv;
-PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glad_glProgramUniformMatrix2x3dv;
-PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glad_glProgramUniformMatrix3x2dv;
-PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glad_glProgramUniformMatrix2x4dv;
-PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glad_glProgramUniformMatrix4x2dv;
-PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glad_glProgramUniformMatrix3x4dv;
-PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glad_glProgramUniformMatrix4x3dv;
-PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline;
-PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog;
-PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv;
-PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture;
-PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier;
-PFNGLDELETEOBJECTARBPROC glad_glDeleteObjectARB;
-PFNGLGETHANDLEARBPROC glad_glGetHandleARB;
-PFNGLDETACHOBJECTARBPROC glad_glDetachObjectARB;
-PFNGLCREATESHADEROBJECTARBPROC glad_glCreateShaderObjectARB;
-PFNGLSHADERSOURCEARBPROC glad_glShaderSourceARB;
-PFNGLCOMPILESHADERARBPROC glad_glCompileShaderARB;
-PFNGLCREATEPROGRAMOBJECTARBPROC glad_glCreateProgramObjectARB;
-PFNGLATTACHOBJECTARBPROC glad_glAttachObjectARB;
-PFNGLLINKPROGRAMARBPROC glad_glLinkProgramARB;
-PFNGLUSEPROGRAMOBJECTARBPROC glad_glUseProgramObjectARB;
-PFNGLVALIDATEPROGRAMARBPROC glad_glValidateProgramARB;
-PFNGLUNIFORM1FARBPROC glad_glUniform1fARB;
-PFNGLUNIFORM2FARBPROC glad_glUniform2fARB;
-PFNGLUNIFORM3FARBPROC glad_glUniform3fARB;
-PFNGLUNIFORM4FARBPROC glad_glUniform4fARB;
-PFNGLUNIFORM1IARBPROC glad_glUniform1iARB;
-PFNGLUNIFORM2IARBPROC glad_glUniform2iARB;
-PFNGLUNIFORM3IARBPROC glad_glUniform3iARB;
-PFNGLUNIFORM4IARBPROC glad_glUniform4iARB;
-PFNGLUNIFORM1FVARBPROC glad_glUniform1fvARB;
-PFNGLUNIFORM2FVARBPROC glad_glUniform2fvARB;
-PFNGLUNIFORM3FVARBPROC glad_glUniform3fvARB;
-PFNGLUNIFORM4FVARBPROC glad_glUniform4fvARB;
-PFNGLUNIFORM1IVARBPROC glad_glUniform1ivARB;
-PFNGLUNIFORM2IVARBPROC glad_glUniform2ivARB;
-PFNGLUNIFORM3IVARBPROC glad_glUniform3ivARB;
-PFNGLUNIFORM4IVARBPROC glad_glUniform4ivARB;
-PFNGLUNIFORMMATRIX2FVARBPROC glad_glUniformMatrix2fvARB;
-PFNGLUNIFORMMATRIX3FVARBPROC glad_glUniformMatrix3fvARB;
-PFNGLUNIFORMMATRIX4FVARBPROC glad_glUniformMatrix4fvARB;
-PFNGLGETOBJECTPARAMETERFVARBPROC glad_glGetObjectParameterfvARB;
-PFNGLGETOBJECTPARAMETERIVARBPROC glad_glGetObjectParameterivARB;
-PFNGLGETINFOLOGARBPROC glad_glGetInfoLogARB;
-PFNGLGETATTACHEDOBJECTSARBPROC glad_glGetAttachedObjectsARB;
-PFNGLGETUNIFORMLOCATIONARBPROC glad_glGetUniformLocationARB;
-PFNGLGETACTIVEUNIFORMARBPROC glad_glGetActiveUniformARB;
-PFNGLGETUNIFORMFVARBPROC glad_glGetUniformfvARB;
-PFNGLGETUNIFORMIVARBPROC glad_glGetUniformivARB;
-PFNGLGETSHADERSOURCEARBPROC glad_glGetShaderSourceARB;
-PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding;
-PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glad_glGetSubroutineUniformLocation;
-PFNGLGETSUBROUTINEINDEXPROC glad_glGetSubroutineIndex;
-PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glad_glGetActiveSubroutineUniformiv;
-PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glad_glGetActiveSubroutineUniformName;
-PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName;
-PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv;
-PFNGLGETUNIFORMSUBROUTINEUIVPROC glad_glGetUniformSubroutineuiv;
-PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv;
-PFNGLNAMEDSTRINGARBPROC glad_glNamedStringARB;
-PFNGLDELETENAMEDSTRINGARBPROC glad_glDeleteNamedStringARB;
-PFNGLCOMPILESHADERINCLUDEARBPROC glad_glCompileShaderIncludeARB;
-PFNGLISNAMEDSTRINGARBPROC glad_glIsNamedStringARB;
-PFNGLGETNAMEDSTRINGARBPROC glad_glGetNamedStringARB;
-PFNGLGETNAMEDSTRINGIVARBPROC glad_glGetNamedStringivARB;
-PFNGLBUFFERPAGECOMMITMENTARBPROC glad_glBufferPageCommitmentARB;
-PFNGLNAMEDBUFFERPAGECOMMITMENTEXTPROC glad_glNamedBufferPageCommitmentEXT;
-PFNGLNAMEDBUFFERPAGECOMMITMENTARBPROC glad_glNamedBufferPageCommitmentARB;
-PFNGLTEXPAGECOMMITMENTARBPROC glad_glTexPageCommitmentARB;
-PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri;
-PFNGLPATCHPARAMETERFVPROC glad_glPatchParameterfv;
-PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier;
-PFNGLTEXBUFFERARBPROC glad_glTexBufferARB;
-PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange;
-PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glad_glCompressedTexImage3DARB;
-PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glad_glCompressedTexImage2DARB;
-PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glad_glCompressedTexImage1DARB;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glad_glCompressedTexSubImage3DARB;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glad_glCompressedTexSubImage2DARB;
-PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glad_glCompressedTexSubImage1DARB;
-PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glad_glGetCompressedTexImageARB;
-PFNGLTEXSTORAGE1DPROC glad_glTexStorage1D;
-PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D;
-PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D;
-PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample;
-PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample;
-PFNGLTEXTUREVIEWPROC glad_glTextureView;
-PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback;
-PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks;
-PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks;
-PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback;
-PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback;
-PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback;
-PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback;
-PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream;
-PFNGLBEGINQUERYINDEXEDPROC glad_glBeginQueryIndexed;
-PFNGLENDQUERYINDEXEDPROC glad_glEndQueryIndexed;
-PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv;
-PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced;
-PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced;
-PFNGLLOADTRANSPOSEMATRIXFARBPROC glad_glLoadTransposeMatrixfARB;
-PFNGLLOADTRANSPOSEMATRIXDARBPROC glad_glLoadTransposeMatrixdARB;
-PFNGLMULTTRANSPOSEMATRIXFARBPROC glad_glMultTransposeMatrixfARB;
-PFNGLMULTTRANSPOSEMATRIXDARBPROC glad_glMultTransposeMatrixdARB;
-PFNGLVERTEXATTRIBL1DPROC glad_glVertexAttribL1d;
-PFNGLVERTEXATTRIBL2DPROC glad_glVertexAttribL2d;
-PFNGLVERTEXATTRIBL3DPROC glad_glVertexAttribL3d;
-PFNGLVERTEXATTRIBL4DPROC glad_glVertexAttribL4d;
-PFNGLVERTEXATTRIBL1DVPROC glad_glVertexAttribL1dv;
-PFNGLVERTEXATTRIBL2DVPROC glad_glVertexAttribL2dv;
-PFNGLVERTEXATTRIBL3DVPROC glad_glVertexAttribL3dv;
-PFNGLVERTEXATTRIBL4DVPROC glad_glVertexAttribL4dv;
-PFNGLVERTEXATTRIBLPOINTERPROC glad_glVertexAttribLPointer;
-PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv;
-PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer;
-PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat;
-PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat;
-PFNGLVERTEXATTRIBLFORMATPROC glad_glVertexAttribLFormat;
-PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding;
-PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor;
-PFNGLWEIGHTBVARBPROC glad_glWeightbvARB;
-PFNGLWEIGHTSVARBPROC glad_glWeightsvARB;
-PFNGLWEIGHTIVARBPROC glad_glWeightivARB;
-PFNGLWEIGHTFVARBPROC glad_glWeightfvARB;
-PFNGLWEIGHTDVARBPROC glad_glWeightdvARB;
-PFNGLWEIGHTUBVARBPROC glad_glWeightubvARB;
-PFNGLWEIGHTUSVARBPROC glad_glWeightusvARB;
-PFNGLWEIGHTUIVARBPROC glad_glWeightuivARB;
-PFNGLWEIGHTPOINTERARBPROC glad_glWeightPointerARB;
-PFNGLVERTEXBLENDARBPROC glad_glVertexBlendARB;
-PFNGLBINDBUFFERARBPROC glad_glBindBufferARB;
-PFNGLDELETEBUFFERSARBPROC glad_glDeleteBuffersARB;
-PFNGLGENBUFFERSARBPROC glad_glGenBuffersARB;
-PFNGLISBUFFERARBPROC glad_glIsBufferARB;
-PFNGLBUFFERDATAARBPROC glad_glBufferDataARB;
-PFNGLBUFFERSUBDATAARBPROC glad_glBufferSubDataARB;
-PFNGLGETBUFFERSUBDATAARBPROC glad_glGetBufferSubDataARB;
-PFNGLMAPBUFFERARBPROC glad_glMapBufferARB;
-PFNGLUNMAPBUFFERARBPROC glad_glUnmapBufferARB;
-PFNGLGETBUFFERPARAMETERIVARBPROC glad_glGetBufferParameterivARB;
-PFNGLGETBUFFERPOINTERVARBPROC glad_glGetBufferPointervARB;
-PFNGLVERTEXATTRIB1DARBPROC glad_glVertexAttrib1dARB;
-PFNGLVERTEXATTRIB1DVARBPROC glad_glVertexAttrib1dvARB;
-PFNGLVERTEXATTRIB1FARBPROC glad_glVertexAttrib1fARB;
-PFNGLVERTEXATTRIB1FVARBPROC glad_glVertexAttrib1fvARB;
-PFNGLVERTEXATTRIB1SARBPROC glad_glVertexAttrib1sARB;
-PFNGLVERTEXATTRIB1SVARBPROC glad_glVertexAttrib1svARB;
-PFNGLVERTEXATTRIB2DARBPROC glad_glVertexAttrib2dARB;
-PFNGLVERTEXATTRIB2DVARBPROC glad_glVertexAttrib2dvARB;
-PFNGLVERTEXATTRIB2FARBPROC glad_glVertexAttrib2fARB;
-PFNGLVERTEXATTRIB2FVARBPROC glad_glVertexAttrib2fvARB;
-PFNGLVERTEXATTRIB2SARBPROC glad_glVertexAttrib2sARB;
-PFNGLVERTEXATTRIB2SVARBPROC glad_glVertexAttrib2svARB;
-PFNGLVERTEXATTRIB3DARBPROC glad_glVertexAttrib3dARB;
-PFNGLVERTEXATTRIB3DVARBPROC glad_glVertexAttrib3dvARB;
-PFNGLVERTEXATTRIB3FARBPROC glad_glVertexAttrib3fARB;
-PFNGLVERTEXATTRIB3FVARBPROC glad_glVertexAttrib3fvARB;
-PFNGLVERTEXATTRIB3SARBPROC glad_glVertexAttrib3sARB;
-PFNGLVERTEXATTRIB3SVARBPROC glad_glVertexAttrib3svARB;
-PFNGLVERTEXATTRIB4NBVARBPROC glad_glVertexAttrib4NbvARB;
-PFNGLVERTEXATTRIB4NIVARBPROC glad_glVertexAttrib4NivARB;
-PFNGLVERTEXATTRIB4NSVARBPROC glad_glVertexAttrib4NsvARB;
-PFNGLVERTEXATTRIB4NUBARBPROC glad_glVertexAttrib4NubARB;
-PFNGLVERTEXATTRIB4NUBVARBPROC glad_glVertexAttrib4NubvARB;
-PFNGLVERTEXATTRIB4NUIVARBPROC glad_glVertexAttrib4NuivARB;
-PFNGLVERTEXATTRIB4NUSVARBPROC glad_glVertexAttrib4NusvARB;
-PFNGLVERTEXATTRIB4BVARBPROC glad_glVertexAttrib4bvARB;
-PFNGLVERTEXATTRIB4DARBPROC glad_glVertexAttrib4dARB;
-PFNGLVERTEXATTRIB4DVARBPROC glad_glVertexAttrib4dvARB;
-PFNGLVERTEXATTRIB4FARBPROC glad_glVertexAttrib4fARB;
-PFNGLVERTEXATTRIB4FVARBPROC glad_glVertexAttrib4fvARB;
-PFNGLVERTEXATTRIB4IVARBPROC glad_glVertexAttrib4ivARB;
-PFNGLVERTEXATTRIB4SARBPROC glad_glVertexAttrib4sARB;
-PFNGLVERTEXATTRIB4SVARBPROC glad_glVertexAttrib4svARB;
-PFNGLVERTEXATTRIB4UBVARBPROC glad_glVertexAttrib4ubvARB;
-PFNGLVERTEXATTRIB4UIVARBPROC glad_glVertexAttrib4uivARB;
-PFNGLVERTEXATTRIB4USVARBPROC glad_glVertexAttrib4usvARB;
-PFNGLVERTEXATTRIBPOINTERARBPROC glad_glVertexAttribPointerARB;
-PFNGLENABLEVERTEXATTRIBARRAYARBPROC glad_glEnableVertexAttribArrayARB;
-PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glad_glDisableVertexAttribArrayARB;
-PFNGLGETVERTEXATTRIBDVARBPROC glad_glGetVertexAttribdvARB;
-PFNGLGETVERTEXATTRIBFVARBPROC glad_glGetVertexAttribfvARB;
-PFNGLGETVERTEXATTRIBIVARBPROC glad_glGetVertexAttribivARB;
-PFNGLGETVERTEXATTRIBPOINTERVARBPROC glad_glGetVertexAttribPointervARB;
-PFNGLBINDATTRIBLOCATIONARBPROC glad_glBindAttribLocationARB;
-PFNGLGETACTIVEATTRIBARBPROC glad_glGetActiveAttribARB;
-PFNGLGETATTRIBLOCATIONARBPROC glad_glGetAttribLocationARB;
-PFNGLVIEWPORTARRAYVPROC glad_glViewportArrayv;
-PFNGLVIEWPORTINDEXEDFPROC glad_glViewportIndexedf;
-PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv;
-PFNGLSCISSORARRAYVPROC glad_glScissorArrayv;
-PFNGLSCISSORINDEXEDPROC glad_glScissorIndexed;
-PFNGLSCISSORINDEXEDVPROC glad_glScissorIndexedv;
-PFNGLDEPTHRANGEARRAYVPROC glad_glDepthRangeArrayv;
-PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed;
-PFNGLGETFLOATI_VPROC glad_glGetFloati_v;
-PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v;
-PFNGLWINDOWPOS2DARBPROC glad_glWindowPos2dARB;
-PFNGLWINDOWPOS2DVARBPROC glad_glWindowPos2dvARB;
-PFNGLWINDOWPOS2FARBPROC glad_glWindowPos2fARB;
-PFNGLWINDOWPOS2FVARBPROC glad_glWindowPos2fvARB;
-PFNGLWINDOWPOS2IARBPROC glad_glWindowPos2iARB;
-PFNGLWINDOWPOS2IVARBPROC glad_glWindowPos2ivARB;
-PFNGLWINDOWPOS2SARBPROC glad_glWindowPos2sARB;
-PFNGLWINDOWPOS2SVARBPROC glad_glWindowPos2svARB;
-PFNGLWINDOWPOS3DARBPROC glad_glWindowPos3dARB;
-PFNGLWINDOWPOS3DVARBPROC glad_glWindowPos3dvARB;
-PFNGLWINDOWPOS3FARBPROC glad_glWindowPos3fARB;
-PFNGLWINDOWPOS3FVARBPROC glad_glWindowPos3fvARB;
-PFNGLWINDOWPOS3IARBPROC glad_glWindowPos3iARB;
-PFNGLWINDOWPOS3IVARBPROC glad_glWindowPos3ivARB;
-PFNGLWINDOWPOS3SARBPROC glad_glWindowPos3sARB;
-PFNGLWINDOWPOS3SVARBPROC glad_glWindowPos3svARB;
-PFNGLDRAWBUFFERSATIPROC glad_glDrawBuffersATI;
-PFNGLELEMENTPOINTERATIPROC glad_glElementPointerATI;
-PFNGLDRAWELEMENTARRAYATIPROC glad_glDrawElementArrayATI;
-PFNGLDRAWRANGEELEMENTARRAYATIPROC glad_glDrawRangeElementArrayATI;
-PFNGLTEXBUMPPARAMETERIVATIPROC glad_glTexBumpParameterivATI;
-PFNGLTEXBUMPPARAMETERFVATIPROC glad_glTexBumpParameterfvATI;
-PFNGLGETTEXBUMPPARAMETERIVATIPROC glad_glGetTexBumpParameterivATI;
-PFNGLGETTEXBUMPPARAMETERFVATIPROC glad_glGetTexBumpParameterfvATI;
-PFNGLGENFRAGMENTSHADERSATIPROC glad_glGenFragmentShadersATI;
-PFNGLBINDFRAGMENTSHADERATIPROC glad_glBindFragmentShaderATI;
-PFNGLDELETEFRAGMENTSHADERATIPROC glad_glDeleteFragmentShaderATI;
-PFNGLBEGINFRAGMENTSHADERATIPROC glad_glBeginFragmentShaderATI;
-PFNGLENDFRAGMENTSHADERATIPROC glad_glEndFragmentShaderATI;
-PFNGLPASSTEXCOORDATIPROC glad_glPassTexCoordATI;
-PFNGLSAMPLEMAPATIPROC glad_glSampleMapATI;
-PFNGLCOLORFRAGMENTOP1ATIPROC glad_glColorFragmentOp1ATI;
-PFNGLCOLORFRAGMENTOP2ATIPROC glad_glColorFragmentOp2ATI;
-PFNGLCOLORFRAGMENTOP3ATIPROC glad_glColorFragmentOp3ATI;
-PFNGLALPHAFRAGMENTOP1ATIPROC glad_glAlphaFragmentOp1ATI;
-PFNGLALPHAFRAGMENTOP2ATIPROC glad_glAlphaFragmentOp2ATI;
-PFNGLALPHAFRAGMENTOP3ATIPROC glad_glAlphaFragmentOp3ATI;
-PFNGLSETFRAGMENTSHADERCONSTANTATIPROC glad_glSetFragmentShaderConstantATI;
-PFNGLMAPOBJECTBUFFERATIPROC glad_glMapObjectBufferATI;
-PFNGLUNMAPOBJECTBUFFERATIPROC glad_glUnmapObjectBufferATI;
-PFNGLPNTRIANGLESIATIPROC glad_glPNTrianglesiATI;
-PFNGLPNTRIANGLESFATIPROC glad_glPNTrianglesfATI;
-PFNGLSTENCILOPSEPARATEATIPROC glad_glStencilOpSeparateATI;
-PFNGLSTENCILFUNCSEPARATEATIPROC glad_glStencilFuncSeparateATI;
-PFNGLNEWOBJECTBUFFERATIPROC glad_glNewObjectBufferATI;
-PFNGLISOBJECTBUFFERATIPROC glad_glIsObjectBufferATI;
-PFNGLUPDATEOBJECTBUFFERATIPROC glad_glUpdateObjectBufferATI;
-PFNGLGETOBJECTBUFFERFVATIPROC glad_glGetObjectBufferfvATI;
-PFNGLGETOBJECTBUFFERIVATIPROC glad_glGetObjectBufferivATI;
-PFNGLFREEOBJECTBUFFERATIPROC glad_glFreeObjectBufferATI;
-PFNGLARRAYOBJECTATIPROC glad_glArrayObjectATI;
-PFNGLGETARRAYOBJECTFVATIPROC glad_glGetArrayObjectfvATI;
-PFNGLGETARRAYOBJECTIVATIPROC glad_glGetArrayObjectivATI;
-PFNGLVARIANTARRAYOBJECTATIPROC glad_glVariantArrayObjectATI;
-PFNGLGETVARIANTARRAYOBJECTFVATIPROC glad_glGetVariantArrayObjectfvATI;
-PFNGLGETVARIANTARRAYOBJECTIVATIPROC glad_glGetVariantArrayObjectivATI;
-PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glad_glVertexAttribArrayObjectATI;
-PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC glad_glGetVertexAttribArrayObjectfvATI;
-PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC glad_glGetVertexAttribArrayObjectivATI;
-PFNGLVERTEXSTREAM1SATIPROC glad_glVertexStream1sATI;
-PFNGLVERTEXSTREAM1SVATIPROC glad_glVertexStream1svATI;
-PFNGLVERTEXSTREAM1IATIPROC glad_glVertexStream1iATI;
-PFNGLVERTEXSTREAM1IVATIPROC glad_glVertexStream1ivATI;
-PFNGLVERTEXSTREAM1FATIPROC glad_glVertexStream1fATI;
-PFNGLVERTEXSTREAM1FVATIPROC glad_glVertexStream1fvATI;
-PFNGLVERTEXSTREAM1DATIPROC glad_glVertexStream1dATI;
-PFNGLVERTEXSTREAM1DVATIPROC glad_glVertexStream1dvATI;
-PFNGLVERTEXSTREAM2SATIPROC glad_glVertexStream2sATI;
-PFNGLVERTEXSTREAM2SVATIPROC glad_glVertexStream2svATI;
-PFNGLVERTEXSTREAM2IATIPROC glad_glVertexStream2iATI;
-PFNGLVERTEXSTREAM2IVATIPROC glad_glVertexStream2ivATI;
-PFNGLVERTEXSTREAM2FATIPROC glad_glVertexStream2fATI;
-PFNGLVERTEXSTREAM2FVATIPROC glad_glVertexStream2fvATI;
-PFNGLVERTEXSTREAM2DATIPROC glad_glVertexStream2dATI;
-PFNGLVERTEXSTREAM2DVATIPROC glad_glVertexStream2dvATI;
-PFNGLVERTEXSTREAM3SATIPROC glad_glVertexStream3sATI;
-PFNGLVERTEXSTREAM3SVATIPROC glad_glVertexStream3svATI;
-PFNGLVERTEXSTREAM3IATIPROC glad_glVertexStream3iATI;
-PFNGLVERTEXSTREAM3IVATIPROC glad_glVertexStream3ivATI;
-PFNGLVERTEXSTREAM3FATIPROC glad_glVertexStream3fATI;
-PFNGLVERTEXSTREAM3FVATIPROC glad_glVertexStream3fvATI;
-PFNGLVERTEXSTREAM3DATIPROC glad_glVertexStream3dATI;
-PFNGLVERTEXSTREAM3DVATIPROC glad_glVertexStream3dvATI;
-PFNGLVERTEXSTREAM4SATIPROC glad_glVertexStream4sATI;
-PFNGLVERTEXSTREAM4SVATIPROC glad_glVertexStream4svATI;
-PFNGLVERTEXSTREAM4IATIPROC glad_glVertexStream4iATI;
-PFNGLVERTEXSTREAM4IVATIPROC glad_glVertexStream4ivATI;
-PFNGLVERTEXSTREAM4FATIPROC glad_glVertexStream4fATI;
-PFNGLVERTEXSTREAM4FVATIPROC glad_glVertexStream4fvATI;
-PFNGLVERTEXSTREAM4DATIPROC glad_glVertexStream4dATI;
-PFNGLVERTEXSTREAM4DVATIPROC glad_glVertexStream4dvATI;
-PFNGLNORMALSTREAM3BATIPROC glad_glNormalStream3bATI;
-PFNGLNORMALSTREAM3BVATIPROC glad_glNormalStream3bvATI;
-PFNGLNORMALSTREAM3SATIPROC glad_glNormalStream3sATI;
-PFNGLNORMALSTREAM3SVATIPROC glad_glNormalStream3svATI;
-PFNGLNORMALSTREAM3IATIPROC glad_glNormalStream3iATI;
-PFNGLNORMALSTREAM3IVATIPROC glad_glNormalStream3ivATI;
-PFNGLNORMALSTREAM3FATIPROC glad_glNormalStream3fATI;
-PFNGLNORMALSTREAM3FVATIPROC glad_glNormalStream3fvATI;
-PFNGLNORMALSTREAM3DATIPROC glad_glNormalStream3dATI;
-PFNGLNORMALSTREAM3DVATIPROC glad_glNormalStream3dvATI;
-PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC glad_glClientActiveVertexStreamATI;
-PFNGLVERTEXBLENDENVIATIPROC glad_glVertexBlendEnviATI;
-PFNGLVERTEXBLENDENVFATIPROC glad_glVertexBlendEnvfATI;
-PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glad_glEGLImageTargetTexStorageEXT;
-PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC glad_glEGLImageTargetTextureStorageEXT;
-PFNGLUNIFORMBUFFEREXTPROC glad_glUniformBufferEXT;
-PFNGLGETUNIFORMBUFFERSIZEEXTPROC glad_glGetUniformBufferSizeEXT;
-PFNGLGETUNIFORMOFFSETEXTPROC glad_glGetUniformOffsetEXT;
-PFNGLBLENDCOLOREXTPROC glad_glBlendColorEXT;
-PFNGLBLENDEQUATIONSEPARATEEXTPROC glad_glBlendEquationSeparateEXT;
-PFNGLBLENDFUNCSEPARATEEXTPROC glad_glBlendFuncSeparateEXT;
-PFNGLBLENDEQUATIONEXTPROC glad_glBlendEquationEXT;
-PFNGLCOLORSUBTABLEEXTPROC glad_glColorSubTableEXT;
-PFNGLCOPYCOLORSUBTABLEEXTPROC glad_glCopyColorSubTableEXT;
-PFNGLLOCKARRAYSEXTPROC glad_glLockArraysEXT;
-PFNGLUNLOCKARRAYSEXTPROC glad_glUnlockArraysEXT;
-PFNGLCONVOLUTIONFILTER1DEXTPROC glad_glConvolutionFilter1DEXT;
-PFNGLCONVOLUTIONFILTER2DEXTPROC glad_glConvolutionFilter2DEXT;
-PFNGLCONVOLUTIONPARAMETERFEXTPROC glad_glConvolutionParameterfEXT;
-PFNGLCONVOLUTIONPARAMETERFVEXTPROC glad_glConvolutionParameterfvEXT;
-PFNGLCONVOLUTIONPARAMETERIEXTPROC glad_glConvolutionParameteriEXT;
-PFNGLCONVOLUTIONPARAMETERIVEXTPROC glad_glConvolutionParameterivEXT;
-PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC glad_glCopyConvolutionFilter1DEXT;
-PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC glad_glCopyConvolutionFilter2DEXT;
-PFNGLGETCONVOLUTIONFILTEREXTPROC glad_glGetConvolutionFilterEXT;
-PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC glad_glGetConvolutionParameterfvEXT;
-PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC glad_glGetConvolutionParameterivEXT;
-PFNGLGETSEPARABLEFILTEREXTPROC glad_glGetSeparableFilterEXT;
-PFNGLSEPARABLEFILTER2DEXTPROC glad_glSeparableFilter2DEXT;
-PFNGLTANGENT3BEXTPROC glad_glTangent3bEXT;
-PFNGLTANGENT3BVEXTPROC glad_glTangent3bvEXT;
-PFNGLTANGENT3DEXTPROC glad_glTangent3dEXT;
-PFNGLTANGENT3DVEXTPROC glad_glTangent3dvEXT;
-PFNGLTANGENT3FEXTPROC glad_glTangent3fEXT;
-PFNGLTANGENT3FVEXTPROC glad_glTangent3fvEXT;
-PFNGLTANGENT3IEXTPROC glad_glTangent3iEXT;
-PFNGLTANGENT3IVEXTPROC glad_glTangent3ivEXT;
-PFNGLTANGENT3SEXTPROC glad_glTangent3sEXT;
-PFNGLTANGENT3SVEXTPROC glad_glTangent3svEXT;
-PFNGLBINORMAL3BEXTPROC glad_glBinormal3bEXT;
-PFNGLBINORMAL3BVEXTPROC glad_glBinormal3bvEXT;
-PFNGLBINORMAL3DEXTPROC glad_glBinormal3dEXT;
-PFNGLBINORMAL3DVEXTPROC glad_glBinormal3dvEXT;
-PFNGLBINORMAL3FEXTPROC glad_glBinormal3fEXT;
-PFNGLBINORMAL3FVEXTPROC glad_glBinormal3fvEXT;
-PFNGLBINORMAL3IEXTPROC glad_glBinormal3iEXT;
-PFNGLBINORMAL3IVEXTPROC glad_glBinormal3ivEXT;
-PFNGLBINORMAL3SEXTPROC glad_glBinormal3sEXT;
-PFNGLBINORMAL3SVEXTPROC glad_glBinormal3svEXT;
-PFNGLTANGENTPOINTEREXTPROC glad_glTangentPointerEXT;
-PFNGLBINORMALPOINTEREXTPROC glad_glBinormalPointerEXT;
-PFNGLCOPYTEXIMAGE1DEXTPROC glad_glCopyTexImage1DEXT;
-PFNGLCOPYTEXIMAGE2DEXTPROC glad_glCopyTexImage2DEXT;
-PFNGLCOPYTEXSUBIMAGE1DEXTPROC glad_glCopyTexSubImage1DEXT;
-PFNGLCOPYTEXSUBIMAGE2DEXTPROC glad_glCopyTexSubImage2DEXT;
-PFNGLCOPYTEXSUBIMAGE3DEXTPROC glad_glCopyTexSubImage3DEXT;
-PFNGLCULLPARAMETERDVEXTPROC glad_glCullParameterdvEXT;
-PFNGLCULLPARAMETERFVEXTPROC glad_glCullParameterfvEXT;
-PFNGLLABELOBJECTEXTPROC glad_glLabelObjectEXT;
-PFNGLGETOBJECTLABELEXTPROC glad_glGetObjectLabelEXT;
-PFNGLINSERTEVENTMARKEREXTPROC glad_glInsertEventMarkerEXT;
-PFNGLPUSHGROUPMARKEREXTPROC glad_glPushGroupMarkerEXT;
-PFNGLPOPGROUPMARKEREXTPROC glad_glPopGroupMarkerEXT;
-PFNGLDEPTHBOUNDSEXTPROC glad_glDepthBoundsEXT;
-PFNGLMATRIXLOADFEXTPROC glad_glMatrixLoadfEXT;
-PFNGLMATRIXLOADDEXTPROC glad_glMatrixLoaddEXT;
-PFNGLMATRIXMULTFEXTPROC glad_glMatrixMultfEXT;
-PFNGLMATRIXMULTDEXTPROC glad_glMatrixMultdEXT;
-PFNGLMATRIXLOADIDENTITYEXTPROC glad_glMatrixLoadIdentityEXT;
-PFNGLMATRIXROTATEFEXTPROC glad_glMatrixRotatefEXT;
-PFNGLMATRIXROTATEDEXTPROC glad_glMatrixRotatedEXT;
-PFNGLMATRIXSCALEFEXTPROC glad_glMatrixScalefEXT;
-PFNGLMATRIXSCALEDEXTPROC glad_glMatrixScaledEXT;
-PFNGLMATRIXTRANSLATEFEXTPROC glad_glMatrixTranslatefEXT;
-PFNGLMATRIXTRANSLATEDEXTPROC glad_glMatrixTranslatedEXT;
-PFNGLMATRIXFRUSTUMEXTPROC glad_glMatrixFrustumEXT;
-PFNGLMATRIXORTHOEXTPROC glad_glMatrixOrthoEXT;
-PFNGLMATRIXPOPEXTPROC glad_glMatrixPopEXT;
-PFNGLMATRIXPUSHEXTPROC glad_glMatrixPushEXT;
-PFNGLCLIENTATTRIBDEFAULTEXTPROC glad_glClientAttribDefaultEXT;
-PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC glad_glPushClientAttribDefaultEXT;
-PFNGLTEXTUREPARAMETERFEXTPROC glad_glTextureParameterfEXT;
-PFNGLTEXTUREPARAMETERFVEXTPROC glad_glTextureParameterfvEXT;
-PFNGLTEXTUREPARAMETERIEXTPROC glad_glTextureParameteriEXT;
-PFNGLTEXTUREPARAMETERIVEXTPROC glad_glTextureParameterivEXT;
-PFNGLTEXTUREIMAGE1DEXTPROC glad_glTextureImage1DEXT;
-PFNGLTEXTUREIMAGE2DEXTPROC glad_glTextureImage2DEXT;
-PFNGLTEXTURESUBIMAGE1DEXTPROC glad_glTextureSubImage1DEXT;
-PFNGLTEXTURESUBIMAGE2DEXTPROC glad_glTextureSubImage2DEXT;
-PFNGLCOPYTEXTUREIMAGE1DEXTPROC glad_glCopyTextureImage1DEXT;
-PFNGLCOPYTEXTUREIMAGE2DEXTPROC glad_glCopyTextureImage2DEXT;
-PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC glad_glCopyTextureSubImage1DEXT;
-PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC glad_glCopyTextureSubImage2DEXT;
-PFNGLGETTEXTUREIMAGEEXTPROC glad_glGetTextureImageEXT;
-PFNGLGETTEXTUREPARAMETERFVEXTPROC glad_glGetTextureParameterfvEXT;
-PFNGLGETTEXTUREPARAMETERIVEXTPROC glad_glGetTextureParameterivEXT;
-PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC glad_glGetTextureLevelParameterfvEXT;
-PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC glad_glGetTextureLevelParameterivEXT;
-PFNGLTEXTUREIMAGE3DEXTPROC glad_glTextureImage3DEXT;
-PFNGLTEXTURESUBIMAGE3DEXTPROC glad_glTextureSubImage3DEXT;
-PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC glad_glCopyTextureSubImage3DEXT;
-PFNGLBINDMULTITEXTUREEXTPROC glad_glBindMultiTextureEXT;
-PFNGLMULTITEXCOORDPOINTEREXTPROC glad_glMultiTexCoordPointerEXT;
-PFNGLMULTITEXENVFEXTPROC glad_glMultiTexEnvfEXT;
-PFNGLMULTITEXENVFVEXTPROC glad_glMultiTexEnvfvEXT;
-PFNGLMULTITEXENVIEXTPROC glad_glMultiTexEnviEXT;
-PFNGLMULTITEXENVIVEXTPROC glad_glMultiTexEnvivEXT;
-PFNGLMULTITEXGENDEXTPROC glad_glMultiTexGendEXT;
-PFNGLMULTITEXGENDVEXTPROC glad_glMultiTexGendvEXT;
-PFNGLMULTITEXGENFEXTPROC glad_glMultiTexGenfEXT;
-PFNGLMULTITEXGENFVEXTPROC glad_glMultiTexGenfvEXT;
-PFNGLMULTITEXGENIEXTPROC glad_glMultiTexGeniEXT;
-PFNGLMULTITEXGENIVEXTPROC glad_glMultiTexGenivEXT;
-PFNGLGETMULTITEXENVFVEXTPROC glad_glGetMultiTexEnvfvEXT;
-PFNGLGETMULTITEXENVIVEXTPROC glad_glGetMultiTexEnvivEXT;
-PFNGLGETMULTITEXGENDVEXTPROC glad_glGetMultiTexGendvEXT;
-PFNGLGETMULTITEXGENFVEXTPROC glad_glGetMultiTexGenfvEXT;
-PFNGLGETMULTITEXGENIVEXTPROC glad_glGetMultiTexGenivEXT;
-PFNGLMULTITEXPARAMETERIEXTPROC glad_glMultiTexParameteriEXT;
-PFNGLMULTITEXPARAMETERIVEXTPROC glad_glMultiTexParameterivEXT;
-PFNGLMULTITEXPARAMETERFEXTPROC glad_glMultiTexParameterfEXT;
-PFNGLMULTITEXPARAMETERFVEXTPROC glad_glMultiTexParameterfvEXT;
-PFNGLMULTITEXIMAGE1DEXTPROC glad_glMultiTexImage1DEXT;
-PFNGLMULTITEXIMAGE2DEXTPROC glad_glMultiTexImage2DEXT;
-PFNGLMULTITEXSUBIMAGE1DEXTPROC glad_glMultiTexSubImage1DEXT;
-PFNGLMULTITEXSUBIMAGE2DEXTPROC glad_glMultiTexSubImage2DEXT;
-PFNGLCOPYMULTITEXIMAGE1DEXTPROC glad_glCopyMultiTexImage1DEXT;
-PFNGLCOPYMULTITEXIMAGE2DEXTPROC glad_glCopyMultiTexImage2DEXT;
-PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC glad_glCopyMultiTexSubImage1DEXT;
-PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC glad_glCopyMultiTexSubImage2DEXT;
-PFNGLGETMULTITEXIMAGEEXTPROC glad_glGetMultiTexImageEXT;
-PFNGLGETMULTITEXPARAMETERFVEXTPROC glad_glGetMultiTexParameterfvEXT;
-PFNGLGETMULTITEXPARAMETERIVEXTPROC glad_glGetMultiTexParameterivEXT;
-PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC glad_glGetMultiTexLevelParameterfvEXT;
-PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC glad_glGetMultiTexLevelParameterivEXT;
-PFNGLMULTITEXIMAGE3DEXTPROC glad_glMultiTexImage3DEXT;
-PFNGLMULTITEXSUBIMAGE3DEXTPROC glad_glMultiTexSubImage3DEXT;
-PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC glad_glCopyMultiTexSubImage3DEXT;
-PFNGLENABLECLIENTSTATEINDEXEDEXTPROC glad_glEnableClientStateIndexedEXT;
-PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC glad_glDisableClientStateIndexedEXT;
-PFNGLGETFLOATINDEXEDVEXTPROC glad_glGetFloatIndexedvEXT;
-PFNGLGETDOUBLEINDEXEDVEXTPROC glad_glGetDoubleIndexedvEXT;
-PFNGLGETPOINTERINDEXEDVEXTPROC glad_glGetPointerIndexedvEXT;
-PFNGLENABLEINDEXEDEXTPROC glad_glEnableIndexedEXT;
-PFNGLDISABLEINDEXEDEXTPROC glad_glDisableIndexedEXT;
-PFNGLISENABLEDINDEXEDEXTPROC glad_glIsEnabledIndexedEXT;
-PFNGLGETINTEGERINDEXEDVEXTPROC glad_glGetIntegerIndexedvEXT;
-PFNGLGETBOOLEANINDEXEDVEXTPROC glad_glGetBooleanIndexedvEXT;
-PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC glad_glCompressedTextureImage3DEXT;
-PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC glad_glCompressedTextureImage2DEXT;
-PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC glad_glCompressedTextureImage1DEXT;
-PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC glad_glCompressedTextureSubImage3DEXT;
-PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC glad_glCompressedTextureSubImage2DEXT;
-PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC glad_glCompressedTextureSubImage1DEXT;
-PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC glad_glGetCompressedTextureImageEXT;
-PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC glad_glCompressedMultiTexImage3DEXT;
-PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC glad_glCompressedMultiTexImage2DEXT;
-PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC glad_glCompressedMultiTexImage1DEXT;
-PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC glad_glCompressedMultiTexSubImage3DEXT;
-PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC glad_glCompressedMultiTexSubImage2DEXT;
-PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC glad_glCompressedMultiTexSubImage1DEXT;
-PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC glad_glGetCompressedMultiTexImageEXT;
-PFNGLMATRIXLOADTRANSPOSEFEXTPROC glad_glMatrixLoadTransposefEXT;
-PFNGLMATRIXLOADTRANSPOSEDEXTPROC glad_glMatrixLoadTransposedEXT;
-PFNGLMATRIXMULTTRANSPOSEFEXTPROC glad_glMatrixMultTransposefEXT;
-PFNGLMATRIXMULTTRANSPOSEDEXTPROC glad_glMatrixMultTransposedEXT;
-PFNGLNAMEDBUFFERDATAEXTPROC glad_glNamedBufferDataEXT;
-PFNGLNAMEDBUFFERSUBDATAEXTPROC glad_glNamedBufferSubDataEXT;
-PFNGLMAPNAMEDBUFFEREXTPROC glad_glMapNamedBufferEXT;
-PFNGLUNMAPNAMEDBUFFEREXTPROC glad_glUnmapNamedBufferEXT;
-PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC glad_glGetNamedBufferParameterivEXT;
-PFNGLGETNAMEDBUFFERPOINTERVEXTPROC glad_glGetNamedBufferPointervEXT;
-PFNGLGETNAMEDBUFFERSUBDATAEXTPROC glad_glGetNamedBufferSubDataEXT;
-PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT;
-PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT;
-PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT;
-PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT;
-PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT;
-PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT;
-PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT;
-PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT;
-PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT;
-PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT;
-PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT;
-PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT;
-PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT;
-PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT;
-PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT;
-PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT;
-PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT;
-PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT;
-PFNGLTEXTUREBUFFEREXTPROC glad_glTextureBufferEXT;
-PFNGLMULTITEXBUFFEREXTPROC glad_glMultiTexBufferEXT;
-PFNGLTEXTUREPARAMETERIIVEXTPROC glad_glTextureParameterIivEXT;
-PFNGLTEXTUREPARAMETERIUIVEXTPROC glad_glTextureParameterIuivEXT;
-PFNGLGETTEXTUREPARAMETERIIVEXTPROC glad_glGetTextureParameterIivEXT;
-PFNGLGETTEXTUREPARAMETERIUIVEXTPROC glad_glGetTextureParameterIuivEXT;
-PFNGLMULTITEXPARAMETERIIVEXTPROC glad_glMultiTexParameterIivEXT;
-PFNGLMULTITEXPARAMETERIUIVEXTPROC glad_glMultiTexParameterIuivEXT;
-PFNGLGETMULTITEXPARAMETERIIVEXTPROC glad_glGetMultiTexParameterIivEXT;
-PFNGLGETMULTITEXPARAMETERIUIVEXTPROC glad_glGetMultiTexParameterIuivEXT;
-PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT;
-PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT;
-PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT;
-PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT;
-PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT;
-PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT;
-PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT;
-PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC glad_glNamedProgramLocalParameters4fvEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC glad_glNamedProgramLocalParameterI4iEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC glad_glNamedProgramLocalParameterI4ivEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC glad_glNamedProgramLocalParametersI4ivEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC glad_glNamedProgramLocalParameterI4uiEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC glad_glNamedProgramLocalParameterI4uivEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC glad_glNamedProgramLocalParametersI4uivEXT;
-PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC glad_glGetNamedProgramLocalParameterIivEXT;
-PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC glad_glGetNamedProgramLocalParameterIuivEXT;
-PFNGLENABLECLIENTSTATEIEXTPROC glad_glEnableClientStateiEXT;
-PFNGLDISABLECLIENTSTATEIEXTPROC glad_glDisableClientStateiEXT;
-PFNGLGETFLOATI_VEXTPROC glad_glGetFloati_vEXT;
-PFNGLGETDOUBLEI_VEXTPROC glad_glGetDoublei_vEXT;
-PFNGLGETPOINTERI_VEXTPROC glad_glGetPointeri_vEXT;
-PFNGLNAMEDPROGRAMSTRINGEXTPROC glad_glNamedProgramStringEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC glad_glNamedProgramLocalParameter4dEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC glad_glNamedProgramLocalParameter4dvEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC glad_glNamedProgramLocalParameter4fEXT;
-PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC glad_glNamedProgramLocalParameter4fvEXT;
-PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC glad_glGetNamedProgramLocalParameterdvEXT;
-PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC glad_glGetNamedProgramLocalParameterfvEXT;
-PFNGLGETNAMEDPROGRAMIVEXTPROC glad_glGetNamedProgramivEXT;
-PFNGLGETNAMEDPROGRAMSTRINGEXTPROC glad_glGetNamedProgramStringEXT;
-PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC glad_glNamedRenderbufferStorageEXT;
-PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC glad_glGetNamedRenderbufferParameterivEXT;
-PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glNamedRenderbufferStorageMultisampleEXT;
-PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC glad_glNamedRenderbufferStorageMultisampleCoverageEXT;
-PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC glad_glCheckNamedFramebufferStatusEXT;
-PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC glad_glNamedFramebufferTexture1DEXT;
-PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC glad_glNamedFramebufferTexture2DEXT;
-PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC glad_glNamedFramebufferTexture3DEXT;
-PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC glad_glNamedFramebufferRenderbufferEXT;
-PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetNamedFramebufferAttachmentParameterivEXT;
-PFNGLGENERATETEXTUREMIPMAPEXTPROC glad_glGenerateTextureMipmapEXT;
-PFNGLGENERATEMULTITEXMIPMAPEXTPROC glad_glGenerateMultiTexMipmapEXT;
-PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC glad_glFramebufferDrawBufferEXT;
-PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC glad_glFramebufferDrawBuffersEXT;
-PFNGLFRAMEBUFFERREADBUFFEREXTPROC glad_glFramebufferReadBufferEXT;
-PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetFramebufferParameterivEXT;
-PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC glad_glNamedCopyBufferSubDataEXT;
-PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC glad_glNamedFramebufferTextureEXT;
-PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC glad_glNamedFramebufferTextureLayerEXT;
-PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC glad_glNamedFramebufferTextureFaceEXT;
-PFNGLTEXTURERENDERBUFFEREXTPROC glad_glTextureRenderbufferEXT;
-PFNGLMULTITEXRENDERBUFFEREXTPROC glad_glMultiTexRenderbufferEXT;
-PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC glad_glVertexArrayVertexOffsetEXT;
-PFNGLVERTEXARRAYCOLOROFFSETEXTPROC glad_glVertexArrayColorOffsetEXT;
-PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC glad_glVertexArrayEdgeFlagOffsetEXT;
-PFNGLVERTEXARRAYINDEXOFFSETEXTPROC glad_glVertexArrayIndexOffsetEXT;
-PFNGLVERTEXARRAYNORMALOFFSETEXTPROC glad_glVertexArrayNormalOffsetEXT;
-PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC glad_glVertexArrayTexCoordOffsetEXT;
-PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC glad_glVertexArrayMultiTexCoordOffsetEXT;
-PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC glad_glVertexArrayFogCoordOffsetEXT;
-PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC glad_glVertexArraySecondaryColorOffsetEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC glad_glVertexArrayVertexAttribOffsetEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC glad_glVertexArrayVertexAttribIOffsetEXT;
-PFNGLENABLEVERTEXARRAYEXTPROC glad_glEnableVertexArrayEXT;
-PFNGLDISABLEVERTEXARRAYEXTPROC glad_glDisableVertexArrayEXT;
-PFNGLENABLEVERTEXARRAYATTRIBEXTPROC glad_glEnableVertexArrayAttribEXT;
-PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC glad_glDisableVertexArrayAttribEXT;
-PFNGLGETVERTEXARRAYINTEGERVEXTPROC glad_glGetVertexArrayIntegervEXT;
-PFNGLGETVERTEXARRAYPOINTERVEXTPROC glad_glGetVertexArrayPointervEXT;
-PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC glad_glGetVertexArrayIntegeri_vEXT;
-PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC glad_glGetVertexArrayPointeri_vEXT;
-PFNGLMAPNAMEDBUFFERRANGEEXTPROC glad_glMapNamedBufferRangeEXT;
-PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC glad_glFlushMappedNamedBufferRangeEXT;
-PFNGLNAMEDBUFFERSTORAGEEXTPROC glad_glNamedBufferStorageEXT;
-PFNGLCLEARNAMEDBUFFERDATAEXTPROC glad_glClearNamedBufferDataEXT;
-PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC glad_glClearNamedBufferSubDataEXT;
-PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC glad_glNamedFramebufferParameteriEXT;
-PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetNamedFramebufferParameterivEXT;
-PFNGLPROGRAMUNIFORM1DEXTPROC glad_glProgramUniform1dEXT;
-PFNGLPROGRAMUNIFORM2DEXTPROC glad_glProgramUniform2dEXT;
-PFNGLPROGRAMUNIFORM3DEXTPROC glad_glProgramUniform3dEXT;
-PFNGLPROGRAMUNIFORM4DEXTPROC glad_glProgramUniform4dEXT;
-PFNGLPROGRAMUNIFORM1DVEXTPROC glad_glProgramUniform1dvEXT;
-PFNGLPROGRAMUNIFORM2DVEXTPROC glad_glProgramUniform2dvEXT;
-PFNGLPROGRAMUNIFORM3DVEXTPROC glad_glProgramUniform3dvEXT;
-PFNGLPROGRAMUNIFORM4DVEXTPROC glad_glProgramUniform4dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC glad_glProgramUniformMatrix2dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC glad_glProgramUniformMatrix3dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC glad_glProgramUniformMatrix4dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC glad_glProgramUniformMatrix2x3dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC glad_glProgramUniformMatrix2x4dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC glad_glProgramUniformMatrix3x2dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC glad_glProgramUniformMatrix3x4dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC glad_glProgramUniformMatrix4x2dvEXT;
-PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC glad_glProgramUniformMatrix4x3dvEXT;
-PFNGLTEXTUREBUFFERRANGEEXTPROC glad_glTextureBufferRangeEXT;
-PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT;
-PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT;
-PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT;
-PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC glad_glTextureStorage2DMultisampleEXT;
-PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC glad_glTextureStorage3DMultisampleEXT;
-PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC glad_glVertexArrayBindVertexBufferEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC glad_glVertexArrayVertexAttribFormatEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC glad_glVertexArrayVertexAttribIFormatEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC glad_glVertexArrayVertexAttribLFormatEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC glad_glVertexArrayVertexAttribBindingEXT;
-PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC glad_glVertexArrayVertexBindingDivisorEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC glad_glVertexArrayVertexAttribLOffsetEXT;
-PFNGLTEXTUREPAGECOMMITMENTEXTPROC glad_glTexturePageCommitmentEXT;
-PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC glad_glVertexArrayVertexAttribDivisorEXT;
-PFNGLCOLORMASKINDEXEDEXTPROC glad_glColorMaskIndexedEXT;
-PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT;
-PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT;
-PFNGLDRAWRANGEELEMENTSEXTPROC glad_glDrawRangeElementsEXT;
-PFNGLBUFFERSTORAGEEXTERNALEXTPROC glad_glBufferStorageExternalEXT;
-PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC glad_glNamedBufferStorageExternalEXT;
-PFNGLFOGCOORDFEXTPROC glad_glFogCoordfEXT;
-PFNGLFOGCOORDFVEXTPROC glad_glFogCoordfvEXT;
-PFNGLFOGCOORDDEXTPROC glad_glFogCoorddEXT;
-PFNGLFOGCOORDDVEXTPROC glad_glFogCoorddvEXT;
-PFNGLFOGCOORDPOINTEREXTPROC glad_glFogCoordPointerEXT;
-PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
-PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
-PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
-PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
-PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
-PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
-PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
-PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
-PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
-PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
-PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
-PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
-PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
-PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
-PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
-PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
-PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
-PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT;
-PFNGLPROGRAMENVPARAMETERS4FVEXTPROC glad_glProgramEnvParameters4fvEXT;
-PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC glad_glProgramLocalParameters4fvEXT;
-PFNGLGETUNIFORMUIVEXTPROC glad_glGetUniformuivEXT;
-PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT;
-PFNGLGETFRAGDATALOCATIONEXTPROC glad_glGetFragDataLocationEXT;
-PFNGLUNIFORM1UIEXTPROC glad_glUniform1uiEXT;
-PFNGLUNIFORM2UIEXTPROC glad_glUniform2uiEXT;
-PFNGLUNIFORM3UIEXTPROC glad_glUniform3uiEXT;
-PFNGLUNIFORM4UIEXTPROC glad_glUniform4uiEXT;
-PFNGLUNIFORM1UIVEXTPROC glad_glUniform1uivEXT;
-PFNGLUNIFORM2UIVEXTPROC glad_glUniform2uivEXT;
-PFNGLUNIFORM3UIVEXTPROC glad_glUniform3uivEXT;
-PFNGLUNIFORM4UIVEXTPROC glad_glUniform4uivEXT;
-PFNGLGETHISTOGRAMEXTPROC glad_glGetHistogramEXT;
-PFNGLGETHISTOGRAMPARAMETERFVEXTPROC glad_glGetHistogramParameterfvEXT;
-PFNGLGETHISTOGRAMPARAMETERIVEXTPROC glad_glGetHistogramParameterivEXT;
-PFNGLGETMINMAXEXTPROC glad_glGetMinmaxEXT;
-PFNGLGETMINMAXPARAMETERFVEXTPROC glad_glGetMinmaxParameterfvEXT;
-PFNGLGETMINMAXPARAMETERIVEXTPROC glad_glGetMinmaxParameterivEXT;
-PFNGLHISTOGRAMEXTPROC glad_glHistogramEXT;
-PFNGLMINMAXEXTPROC glad_glMinmaxEXT;
-PFNGLRESETHISTOGRAMEXTPROC glad_glResetHistogramEXT;
-PFNGLRESETMINMAXEXTPROC glad_glResetMinmaxEXT;
-PFNGLINDEXFUNCEXTPROC glad_glIndexFuncEXT;
-PFNGLINDEXMATERIALEXTPROC glad_glIndexMaterialEXT;
-PFNGLAPPLYTEXTUREEXTPROC glad_glApplyTextureEXT;
-PFNGLTEXTURELIGHTEXTPROC glad_glTextureLightEXT;
-PFNGLTEXTUREMATERIALEXTPROC glad_glTextureMaterialEXT;
-PFNGLGETUNSIGNEDBYTEVEXTPROC glad_glGetUnsignedBytevEXT;
-PFNGLGETUNSIGNEDBYTEI_VEXTPROC glad_glGetUnsignedBytei_vEXT;
-PFNGLDELETEMEMORYOBJECTSEXTPROC glad_glDeleteMemoryObjectsEXT;
-PFNGLISMEMORYOBJECTEXTPROC glad_glIsMemoryObjectEXT;
-PFNGLCREATEMEMORYOBJECTSEXTPROC glad_glCreateMemoryObjectsEXT;
-PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glad_glMemoryObjectParameterivEXT;
-PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC glad_glGetMemoryObjectParameterivEXT;
-PFNGLTEXSTORAGEMEM2DEXTPROC glad_glTexStorageMem2DEXT;
-PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTexStorageMem2DMultisampleEXT;
-PFNGLTEXSTORAGEMEM3DEXTPROC glad_glTexStorageMem3DEXT;
-PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTexStorageMem3DMultisampleEXT;
-PFNGLBUFFERSTORAGEMEMEXTPROC glad_glBufferStorageMemEXT;
-PFNGLTEXTURESTORAGEMEM2DEXTPROC glad_glTextureStorageMem2DEXT;
-PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTextureStorageMem2DMultisampleEXT;
-PFNGLTEXTURESTORAGEMEM3DEXTPROC glad_glTextureStorageMem3DEXT;
-PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTextureStorageMem3DMultisampleEXT;
-PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC glad_glNamedBufferStorageMemEXT;
-PFNGLTEXSTORAGEMEM1DEXTPROC glad_glTexStorageMem1DEXT;
-PFNGLTEXTURESTORAGEMEM1DEXTPROC glad_glTextureStorageMem1DEXT;
-PFNGLIMPORTMEMORYFDEXTPROC glad_glImportMemoryFdEXT;
-PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC glad_glImportMemoryWin32HandleEXT;
-PFNGLIMPORTMEMORYWIN32NAMEEXTPROC glad_glImportMemoryWin32NameEXT;
-PFNGLMULTIDRAWARRAYSEXTPROC glad_glMultiDrawArraysEXT;
-PFNGLMULTIDRAWELEMENTSEXTPROC glad_glMultiDrawElementsEXT;
-PFNGLSAMPLEMASKEXTPROC glad_glSampleMaskEXT;
-PFNGLSAMPLEPATTERNEXTPROC glad_glSamplePatternEXT;
-PFNGLCOLORTABLEEXTPROC glad_glColorTableEXT;
-PFNGLGETCOLORTABLEEXTPROC glad_glGetColorTableEXT;
-PFNGLGETCOLORTABLEPARAMETERIVEXTPROC glad_glGetColorTableParameterivEXT;
-PFNGLGETCOLORTABLEPARAMETERFVEXTPROC glad_glGetColorTableParameterfvEXT;
-PFNGLPIXELTRANSFORMPARAMETERIEXTPROC glad_glPixelTransformParameteriEXT;
-PFNGLPIXELTRANSFORMPARAMETERFEXTPROC glad_glPixelTransformParameterfEXT;
-PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC glad_glPixelTransformParameterivEXT;
-PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC glad_glPixelTransformParameterfvEXT;
-PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC glad_glGetPixelTransformParameterivEXT;
-PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC glad_glGetPixelTransformParameterfvEXT;
-PFNGLPOINTPARAMETERFEXTPROC glad_glPointParameterfEXT;
-PFNGLPOINTPARAMETERFVEXTPROC glad_glPointParameterfvEXT;
-PFNGLPOLYGONOFFSETEXTPROC glad_glPolygonOffsetEXT;
-PFNGLPOLYGONOFFSETCLAMPEXTPROC glad_glPolygonOffsetClampEXT;
-PFNGLPROVOKINGVERTEXEXTPROC glad_glProvokingVertexEXT;
-PFNGLRASTERSAMPLESEXTPROC glad_glRasterSamplesEXT;
-PFNGLSECONDARYCOLOR3BEXTPROC glad_glSecondaryColor3bEXT;
-PFNGLSECONDARYCOLOR3BVEXTPROC glad_glSecondaryColor3bvEXT;
-PFNGLSECONDARYCOLOR3DEXTPROC glad_glSecondaryColor3dEXT;
-PFNGLSECONDARYCOLOR3DVEXTPROC glad_glSecondaryColor3dvEXT;
-PFNGLSECONDARYCOLOR3FEXTPROC glad_glSecondaryColor3fEXT;
-PFNGLSECONDARYCOLOR3FVEXTPROC glad_glSecondaryColor3fvEXT;
-PFNGLSECONDARYCOLOR3IEXTPROC glad_glSecondaryColor3iEXT;
-PFNGLSECONDARYCOLOR3IVEXTPROC glad_glSecondaryColor3ivEXT;
-PFNGLSECONDARYCOLOR3SEXTPROC glad_glSecondaryColor3sEXT;
-PFNGLSECONDARYCOLOR3SVEXTPROC glad_glSecondaryColor3svEXT;
-PFNGLSECONDARYCOLOR3UBEXTPROC glad_glSecondaryColor3ubEXT;
-PFNGLSECONDARYCOLOR3UBVEXTPROC glad_glSecondaryColor3ubvEXT;
-PFNGLSECONDARYCOLOR3UIEXTPROC glad_glSecondaryColor3uiEXT;
-PFNGLSECONDARYCOLOR3UIVEXTPROC glad_glSecondaryColor3uivEXT;
-PFNGLSECONDARYCOLOR3USEXTPROC glad_glSecondaryColor3usEXT;
-PFNGLSECONDARYCOLOR3USVEXTPROC glad_glSecondaryColor3usvEXT;
-PFNGLSECONDARYCOLORPOINTEREXTPROC glad_glSecondaryColorPointerEXT;
-PFNGLGENSEMAPHORESEXTPROC glad_glGenSemaphoresEXT;
-PFNGLDELETESEMAPHORESEXTPROC glad_glDeleteSemaphoresEXT;
-PFNGLISSEMAPHOREEXTPROC glad_glIsSemaphoreEXT;
-PFNGLSEMAPHOREPARAMETERUI64VEXTPROC glad_glSemaphoreParameterui64vEXT;
-PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC glad_glGetSemaphoreParameterui64vEXT;
-PFNGLWAITSEMAPHOREEXTPROC glad_glWaitSemaphoreEXT;
-PFNGLSIGNALSEMAPHOREEXTPROC glad_glSignalSemaphoreEXT;
-PFNGLIMPORTSEMAPHOREFDEXTPROC glad_glImportSemaphoreFdEXT;
-PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC glad_glImportSemaphoreWin32HandleEXT;
-PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC glad_glImportSemaphoreWin32NameEXT;
-PFNGLUSESHADERPROGRAMEXTPROC glad_glUseShaderProgramEXT;
-PFNGLACTIVEPROGRAMEXTPROC glad_glActiveProgramEXT;
-PFNGLCREATESHADERPROGRAMEXTPROC glad_glCreateShaderProgramEXT;
-PFNGLACTIVESHADERPROGRAMEXTPROC glad_glActiveShaderProgramEXT;
-PFNGLBINDPROGRAMPIPELINEEXTPROC glad_glBindProgramPipelineEXT;
-PFNGLCREATESHADERPROGRAMVEXTPROC glad_glCreateShaderProgramvEXT;
-PFNGLDELETEPROGRAMPIPELINESEXTPROC glad_glDeleteProgramPipelinesEXT;
-PFNGLGENPROGRAMPIPELINESEXTPROC glad_glGenProgramPipelinesEXT;
-PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC glad_glGetProgramPipelineInfoLogEXT;
-PFNGLGETPROGRAMPIPELINEIVEXTPROC glad_glGetProgramPipelineivEXT;
-PFNGLISPROGRAMPIPELINEEXTPROC glad_glIsProgramPipelineEXT;
-PFNGLUSEPROGRAMSTAGESEXTPROC glad_glUseProgramStagesEXT;
-PFNGLVALIDATEPROGRAMPIPELINEEXTPROC glad_glValidateProgramPipelineEXT;
-PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC glad_glFramebufferFetchBarrierEXT;
-PFNGLBINDIMAGETEXTUREEXTPROC glad_glBindImageTextureEXT;
-PFNGLMEMORYBARRIEREXTPROC glad_glMemoryBarrierEXT;
-PFNGLSTENCILCLEARTAGEXTPROC glad_glStencilClearTagEXT;
-PFNGLACTIVESTENCILFACEEXTPROC glad_glActiveStencilFaceEXT;
-PFNGLTEXSUBIMAGE1DEXTPROC glad_glTexSubImage1DEXT;
-PFNGLTEXSUBIMAGE2DEXTPROC glad_glTexSubImage2DEXT;
-PFNGLTEXIMAGE3DEXTPROC glad_glTexImage3DEXT;
-PFNGLTEXSUBIMAGE3DEXTPROC glad_glTexSubImage3DEXT;
-PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glad_glFramebufferTextureLayerEXT;
-PFNGLTEXBUFFEREXTPROC glad_glTexBufferEXT;
-PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT;
-PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT;
-PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT;
-PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT;
-PFNGLCLEARCOLORIIEXTPROC glad_glClearColorIiEXT;
-PFNGLCLEARCOLORIUIEXTPROC glad_glClearColorIuiEXT;
-PFNGLARETEXTURESRESIDENTEXTPROC glad_glAreTexturesResidentEXT;
-PFNGLBINDTEXTUREEXTPROC glad_glBindTextureEXT;
-PFNGLDELETETEXTURESEXTPROC glad_glDeleteTexturesEXT;
-PFNGLGENTEXTURESEXTPROC glad_glGenTexturesEXT;
-PFNGLISTEXTUREEXTPROC glad_glIsTextureEXT;
-PFNGLPRIORITIZETEXTURESEXTPROC glad_glPrioritizeTexturesEXT;
-PFNGLTEXTURENORMALEXTPROC glad_glTextureNormalEXT;
-PFNGLGETQUERYOBJECTI64VEXTPROC glad_glGetQueryObjecti64vEXT;
-PFNGLGETQUERYOBJECTUI64VEXTPROC glad_glGetQueryObjectui64vEXT;
-PFNGLBEGINTRANSFORMFEEDBACKEXTPROC glad_glBeginTransformFeedbackEXT;
-PFNGLENDTRANSFORMFEEDBACKEXTPROC glad_glEndTransformFeedbackEXT;
-PFNGLBINDBUFFERRANGEEXTPROC glad_glBindBufferRangeEXT;
-PFNGLBINDBUFFEROFFSETEXTPROC glad_glBindBufferOffsetEXT;
-PFNGLBINDBUFFERBASEEXTPROC glad_glBindBufferBaseEXT;
-PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC glad_glTransformFeedbackVaryingsEXT;
-PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC glad_glGetTransformFeedbackVaryingEXT;
-PFNGLARRAYELEMENTEXTPROC glad_glArrayElementEXT;
-PFNGLCOLORPOINTEREXTPROC glad_glColorPointerEXT;
-PFNGLDRAWARRAYSEXTPROC glad_glDrawArraysEXT;
-PFNGLEDGEFLAGPOINTEREXTPROC glad_glEdgeFlagPointerEXT;
-PFNGLGETPOINTERVEXTPROC glad_glGetPointervEXT;
-PFNGLINDEXPOINTEREXTPROC glad_glIndexPointerEXT;
-PFNGLNORMALPOINTEREXTPROC glad_glNormalPointerEXT;
-PFNGLTEXCOORDPOINTEREXTPROC glad_glTexCoordPointerEXT;
-PFNGLVERTEXPOINTEREXTPROC glad_glVertexPointerEXT;
-PFNGLVERTEXATTRIBL1DEXTPROC glad_glVertexAttribL1dEXT;
-PFNGLVERTEXATTRIBL2DEXTPROC glad_glVertexAttribL2dEXT;
-PFNGLVERTEXATTRIBL3DEXTPROC glad_glVertexAttribL3dEXT;
-PFNGLVERTEXATTRIBL4DEXTPROC glad_glVertexAttribL4dEXT;
-PFNGLVERTEXATTRIBL1DVEXTPROC glad_glVertexAttribL1dvEXT;
-PFNGLVERTEXATTRIBL2DVEXTPROC glad_glVertexAttribL2dvEXT;
-PFNGLVERTEXATTRIBL3DVEXTPROC glad_glVertexAttribL3dvEXT;
-PFNGLVERTEXATTRIBL4DVEXTPROC glad_glVertexAttribL4dvEXT;
-PFNGLVERTEXATTRIBLPOINTEREXTPROC glad_glVertexAttribLPointerEXT;
-PFNGLGETVERTEXATTRIBLDVEXTPROC glad_glGetVertexAttribLdvEXT;
-PFNGLBEGINVERTEXSHADEREXTPROC glad_glBeginVertexShaderEXT;
-PFNGLENDVERTEXSHADEREXTPROC glad_glEndVertexShaderEXT;
-PFNGLBINDVERTEXSHADEREXTPROC glad_glBindVertexShaderEXT;
-PFNGLGENVERTEXSHADERSEXTPROC glad_glGenVertexShadersEXT;
-PFNGLDELETEVERTEXSHADEREXTPROC glad_glDeleteVertexShaderEXT;
-PFNGLSHADEROP1EXTPROC glad_glShaderOp1EXT;
-PFNGLSHADEROP2EXTPROC glad_glShaderOp2EXT;
-PFNGLSHADEROP3EXTPROC glad_glShaderOp3EXT;
-PFNGLSWIZZLEEXTPROC glad_glSwizzleEXT;
-PFNGLWRITEMASKEXTPROC glad_glWriteMaskEXT;
-PFNGLINSERTCOMPONENTEXTPROC glad_glInsertComponentEXT;
-PFNGLEXTRACTCOMPONENTEXTPROC glad_glExtractComponentEXT;
-PFNGLGENSYMBOLSEXTPROC glad_glGenSymbolsEXT;
-PFNGLSETINVARIANTEXTPROC glad_glSetInvariantEXT;
-PFNGLSETLOCALCONSTANTEXTPROC glad_glSetLocalConstantEXT;
-PFNGLVARIANTBVEXTPROC glad_glVariantbvEXT;
-PFNGLVARIANTSVEXTPROC glad_glVariantsvEXT;
-PFNGLVARIANTIVEXTPROC glad_glVariantivEXT;
-PFNGLVARIANTFVEXTPROC glad_glVariantfvEXT;
-PFNGLVARIANTDVEXTPROC glad_glVariantdvEXT;
-PFNGLVARIANTUBVEXTPROC glad_glVariantubvEXT;
-PFNGLVARIANTUSVEXTPROC glad_glVariantusvEXT;
-PFNGLVARIANTUIVEXTPROC glad_glVariantuivEXT;
-PFNGLVARIANTPOINTEREXTPROC glad_glVariantPointerEXT;
-PFNGLENABLEVARIANTCLIENTSTATEEXTPROC glad_glEnableVariantClientStateEXT;
-PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC glad_glDisableVariantClientStateEXT;
-PFNGLBINDLIGHTPARAMETEREXTPROC glad_glBindLightParameterEXT;
-PFNGLBINDMATERIALPARAMETEREXTPROC glad_glBindMaterialParameterEXT;
-PFNGLBINDTEXGENPARAMETEREXTPROC glad_glBindTexGenParameterEXT;
-PFNGLBINDTEXTUREUNITPARAMETEREXTPROC glad_glBindTextureUnitParameterEXT;
-PFNGLBINDPARAMETEREXTPROC glad_glBindParameterEXT;
-PFNGLISVARIANTENABLEDEXTPROC glad_glIsVariantEnabledEXT;
-PFNGLGETVARIANTBOOLEANVEXTPROC glad_glGetVariantBooleanvEXT;
-PFNGLGETVARIANTINTEGERVEXTPROC glad_glGetVariantIntegervEXT;
-PFNGLGETVARIANTFLOATVEXTPROC glad_glGetVariantFloatvEXT;
-PFNGLGETVARIANTPOINTERVEXTPROC glad_glGetVariantPointervEXT;
-PFNGLGETINVARIANTBOOLEANVEXTPROC glad_glGetInvariantBooleanvEXT;
-PFNGLGETINVARIANTINTEGERVEXTPROC glad_glGetInvariantIntegervEXT;
-PFNGLGETINVARIANTFLOATVEXTPROC glad_glGetInvariantFloatvEXT;
-PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC glad_glGetLocalConstantBooleanvEXT;
-PFNGLGETLOCALCONSTANTINTEGERVEXTPROC glad_glGetLocalConstantIntegervEXT;
-PFNGLGETLOCALCONSTANTFLOATVEXTPROC glad_glGetLocalConstantFloatvEXT;
-PFNGLVERTEXWEIGHTFEXTPROC glad_glVertexWeightfEXT;
-PFNGLVERTEXWEIGHTFVEXTPROC glad_glVertexWeightfvEXT;
-PFNGLVERTEXWEIGHTPOINTEREXTPROC glad_glVertexWeightPointerEXT;
-PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC glad_glAcquireKeyedMutexWin32EXT;
-PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC glad_glReleaseKeyedMutexWin32EXT;
-PFNGLWINDOWRECTANGLESEXTPROC glad_glWindowRectanglesEXT;
-PFNGLIMPORTSYNCEXTPROC glad_glImportSyncEXT;
-PFNGLFRAMETERMINATORGREMEDYPROC glad_glFrameTerminatorGREMEDY;
-PFNGLSTRINGMARKERGREMEDYPROC glad_glStringMarkerGREMEDY;
-PFNGLIMAGETRANSFORMPARAMETERIHPPROC glad_glImageTransformParameteriHP;
-PFNGLIMAGETRANSFORMPARAMETERFHPPROC glad_glImageTransformParameterfHP;
-PFNGLIMAGETRANSFORMPARAMETERIVHPPROC glad_glImageTransformParameterivHP;
-PFNGLIMAGETRANSFORMPARAMETERFVHPPROC glad_glImageTransformParameterfvHP;
-PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC glad_glGetImageTransformParameterivHP;
-PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC glad_glGetImageTransformParameterfvHP;
-PFNGLMULTIMODEDRAWARRAYSIBMPROC glad_glMultiModeDrawArraysIBM;
-PFNGLMULTIMODEDRAWELEMENTSIBMPROC glad_glMultiModeDrawElementsIBM;
-PFNGLFLUSHSTATICDATAIBMPROC glad_glFlushStaticDataIBM;
-PFNGLCOLORPOINTERLISTIBMPROC glad_glColorPointerListIBM;
-PFNGLSECONDARYCOLORPOINTERLISTIBMPROC glad_glSecondaryColorPointerListIBM;
-PFNGLEDGEFLAGPOINTERLISTIBMPROC glad_glEdgeFlagPointerListIBM;
-PFNGLFOGCOORDPOINTERLISTIBMPROC glad_glFogCoordPointerListIBM;
-PFNGLINDEXPOINTERLISTIBMPROC glad_glIndexPointerListIBM;
-PFNGLNORMALPOINTERLISTIBMPROC glad_glNormalPointerListIBM;
-PFNGLTEXCOORDPOINTERLISTIBMPROC glad_glTexCoordPointerListIBM;
-PFNGLVERTEXPOINTERLISTIBMPROC glad_glVertexPointerListIBM;
-PFNGLBLENDFUNCSEPARATEINGRPROC glad_glBlendFuncSeparateINGR;
-PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC glad_glApplyFramebufferAttachmentCMAAINTEL;
-PFNGLSYNCTEXTUREINTELPROC glad_glSyncTextureINTEL;
-PFNGLUNMAPTEXTURE2DINTELPROC glad_glUnmapTexture2DINTEL;
-PFNGLMAPTEXTURE2DINTELPROC glad_glMapTexture2DINTEL;
-PFNGLVERTEXPOINTERVINTELPROC glad_glVertexPointervINTEL;
-PFNGLNORMALPOINTERVINTELPROC glad_glNormalPointervINTEL;
-PFNGLCOLORPOINTERVINTELPROC glad_glColorPointervINTEL;
-PFNGLTEXCOORDPOINTERVINTELPROC glad_glTexCoordPointervINTEL;
-PFNGLBEGINPERFQUERYINTELPROC glad_glBeginPerfQueryINTEL;
-PFNGLCREATEPERFQUERYINTELPROC glad_glCreatePerfQueryINTEL;
-PFNGLDELETEPERFQUERYINTELPROC glad_glDeletePerfQueryINTEL;
-PFNGLENDPERFQUERYINTELPROC glad_glEndPerfQueryINTEL;
-PFNGLGETFIRSTPERFQUERYIDINTELPROC glad_glGetFirstPerfQueryIdINTEL;
-PFNGLGETNEXTPERFQUERYIDINTELPROC glad_glGetNextPerfQueryIdINTEL;
-PFNGLGETPERFCOUNTERINFOINTELPROC glad_glGetPerfCounterInfoINTEL;
-PFNGLGETPERFQUERYDATAINTELPROC glad_glGetPerfQueryDataINTEL;
-PFNGLGETPERFQUERYIDBYNAMEINTELPROC glad_glGetPerfQueryIdByNameINTEL;
-PFNGLGETPERFQUERYINFOINTELPROC glad_glGetPerfQueryInfoINTEL;
-PFNGLBLENDBARRIERKHRPROC glad_glBlendBarrierKHR;
-PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
-PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
-PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
-PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
-PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
-PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
-PFNGLOBJECTLABELPROC glad_glObjectLabel;
-PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
-PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
-PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
-PFNGLGETPOINTERVPROC glad_glGetPointerv;
-PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
-PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
-PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
-PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
-PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
-PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
-PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
-PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
-PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
-PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
-PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
-PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glad_glMaxShaderCompilerThreadsKHR;
-PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus;
-PFNGLREADNPIXELSPROC glad_glReadnPixels;
-PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv;
-PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv;
-PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv;
-PFNGLGETGRAPHICSRESETSTATUSKHRPROC glad_glGetGraphicsResetStatusKHR;
-PFNGLREADNPIXELSKHRPROC glad_glReadnPixelsKHR;
-PFNGLGETNUNIFORMFVKHRPROC glad_glGetnUniformfvKHR;
-PFNGLGETNUNIFORMIVKHRPROC glad_glGetnUniformivKHR;
-PFNGLGETNUNIFORMUIVKHRPROC glad_glGetnUniformuivKHR;
-PFNGLRESIZEBUFFERSMESAPROC glad_glResizeBuffersMESA;
-PFNGLWINDOWPOS2DMESAPROC glad_glWindowPos2dMESA;
-PFNGLWINDOWPOS2DVMESAPROC glad_glWindowPos2dvMESA;
-PFNGLWINDOWPOS2FMESAPROC glad_glWindowPos2fMESA;
-PFNGLWINDOWPOS2FVMESAPROC glad_glWindowPos2fvMESA;
-PFNGLWINDOWPOS2IMESAPROC glad_glWindowPos2iMESA;
-PFNGLWINDOWPOS2IVMESAPROC glad_glWindowPos2ivMESA;
-PFNGLWINDOWPOS2SMESAPROC glad_glWindowPos2sMESA;
-PFNGLWINDOWPOS2SVMESAPROC glad_glWindowPos2svMESA;
-PFNGLWINDOWPOS3DMESAPROC glad_glWindowPos3dMESA;
-PFNGLWINDOWPOS3DVMESAPROC glad_glWindowPos3dvMESA;
-PFNGLWINDOWPOS3FMESAPROC glad_glWindowPos3fMESA;
-PFNGLWINDOWPOS3FVMESAPROC glad_glWindowPos3fvMESA;
-PFNGLWINDOWPOS3IMESAPROC glad_glWindowPos3iMESA;
-PFNGLWINDOWPOS3IVMESAPROC glad_glWindowPos3ivMESA;
-PFNGLWINDOWPOS3SMESAPROC glad_glWindowPos3sMESA;
-PFNGLWINDOWPOS3SVMESAPROC glad_glWindowPos3svMESA;
-PFNGLWINDOWPOS4DMESAPROC glad_glWindowPos4dMESA;
-PFNGLWINDOWPOS4DVMESAPROC glad_glWindowPos4dvMESA;
-PFNGLWINDOWPOS4FMESAPROC glad_glWindowPos4fMESA;
-PFNGLWINDOWPOS4FVMESAPROC glad_glWindowPos4fvMESA;
-PFNGLWINDOWPOS4IMESAPROC glad_glWindowPos4iMESA;
-PFNGLWINDOWPOS4IVMESAPROC glad_glWindowPos4ivMESA;
-PFNGLWINDOWPOS4SMESAPROC glad_glWindowPos4sMESA;
-PFNGLWINDOWPOS4SVMESAPROC glad_glWindowPos4svMESA;
-PFNGLBEGINCONDITIONALRENDERNVXPROC glad_glBeginConditionalRenderNVX;
-PFNGLENDCONDITIONALRENDERNVXPROC glad_glEndConditionalRenderNVX;
-PFNGLLGPUNAMEDBUFFERSUBDATANVXPROC glad_glLGPUNamedBufferSubDataNVX;
-PFNGLLGPUCOPYIMAGESUBDATANVXPROC glad_glLGPUCopyImageSubDataNVX;
-PFNGLLGPUINTERLOCKNVXPROC glad_glLGPUInterlockNVX;
-PFNGLALPHATOCOVERAGEDITHERCONTROLNVPROC glad_glAlphaToCoverageDitherControlNV;
-PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC glad_glMultiDrawArraysIndirectBindlessNV;
-PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC glad_glMultiDrawElementsIndirectBindlessNV;
-PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSCOUNTNVPROC glad_glMultiDrawArraysIndirectBindlessCountNV;
-PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSCOUNTNVPROC glad_glMultiDrawElementsIndirectBindlessCountNV;
-PFNGLGETTEXTUREHANDLENVPROC glad_glGetTextureHandleNV;
-PFNGLGETTEXTURESAMPLERHANDLENVPROC glad_glGetTextureSamplerHandleNV;
-PFNGLMAKETEXTUREHANDLERESIDENTNVPROC glad_glMakeTextureHandleResidentNV;
-PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC glad_glMakeTextureHandleNonResidentNV;
-PFNGLGETIMAGEHANDLENVPROC glad_glGetImageHandleNV;
-PFNGLMAKEIMAGEHANDLERESIDENTNVPROC glad_glMakeImageHandleResidentNV;
-PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC glad_glMakeImageHandleNonResidentNV;
-PFNGLUNIFORMHANDLEUI64NVPROC glad_glUniformHandleui64NV;
-PFNGLUNIFORMHANDLEUI64VNVPROC glad_glUniformHandleui64vNV;
-PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC glad_glProgramUniformHandleui64NV;
-PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC glad_glProgramUniformHandleui64vNV;
-PFNGLISTEXTUREHANDLERESIDENTNVPROC glad_glIsTextureHandleResidentNV;
-PFNGLISIMAGEHANDLERESIDENTNVPROC glad_glIsImageHandleResidentNV;
-PFNGLBLENDPARAMETERINVPROC glad_glBlendParameteriNV;
-PFNGLBLENDBARRIERNVPROC glad_glBlendBarrierNV;
-PFNGLVIEWPORTPOSITIONWSCALENVPROC glad_glViewportPositionWScaleNV;
-PFNGLCREATESTATESNVPROC glad_glCreateStatesNV;
-PFNGLDELETESTATESNVPROC glad_glDeleteStatesNV;
-PFNGLISSTATENVPROC glad_glIsStateNV;
-PFNGLSTATECAPTURENVPROC glad_glStateCaptureNV;
-PFNGLGETCOMMANDHEADERNVPROC glad_glGetCommandHeaderNV;
-PFNGLGETSTAGEINDEXNVPROC glad_glGetStageIndexNV;
-PFNGLDRAWCOMMANDSNVPROC glad_glDrawCommandsNV;
-PFNGLDRAWCOMMANDSADDRESSNVPROC glad_glDrawCommandsAddressNV;
-PFNGLDRAWCOMMANDSSTATESNVPROC glad_glDrawCommandsStatesNV;
-PFNGLDRAWCOMMANDSSTATESADDRESSNVPROC glad_glDrawCommandsStatesAddressNV;
-PFNGLCREATECOMMANDLISTSNVPROC glad_glCreateCommandListsNV;
-PFNGLDELETECOMMANDLISTSNVPROC glad_glDeleteCommandListsNV;
-PFNGLISCOMMANDLISTNVPROC glad_glIsCommandListNV;
-PFNGLLISTDRAWCOMMANDSSTATESCLIENTNVPROC glad_glListDrawCommandsStatesClientNV;
-PFNGLCOMMANDLISTSEGMENTSNVPROC glad_glCommandListSegmentsNV;
-PFNGLCOMPILECOMMANDLISTNVPROC glad_glCompileCommandListNV;
-PFNGLCALLCOMMANDLISTNVPROC glad_glCallCommandListNV;
-PFNGLBEGINCONDITIONALRENDERNVPROC glad_glBeginConditionalRenderNV;
-PFNGLENDCONDITIONALRENDERNVPROC glad_glEndConditionalRenderNV;
-PFNGLSUBPIXELPRECISIONBIASNVPROC glad_glSubpixelPrecisionBiasNV;
-PFNGLCONSERVATIVERASTERPARAMETERFNVPROC glad_glConservativeRasterParameterfNV;
-PFNGLCONSERVATIVERASTERPARAMETERINVPROC glad_glConservativeRasterParameteriNV;
-PFNGLCOPYIMAGESUBDATANVPROC glad_glCopyImageSubDataNV;
-PFNGLDEPTHRANGEDNVPROC glad_glDepthRangedNV;
-PFNGLCLEARDEPTHDNVPROC glad_glClearDepthdNV;
-PFNGLDEPTHBOUNDSDNVPROC glad_glDepthBoundsdNV;
-PFNGLDRAWTEXTURENVPROC glad_glDrawTextureNV;
-PFNGLDRAWVKIMAGENVPROC glad_glDrawVkImageNV;
-PFNGLGETVKPROCADDRNVPROC glad_glGetVkProcAddrNV;
-PFNGLWAITVKSEMAPHORENVPROC glad_glWaitVkSemaphoreNV;
-PFNGLSIGNALVKSEMAPHORENVPROC glad_glSignalVkSemaphoreNV;
-PFNGLSIGNALVKFENCENVPROC glad_glSignalVkFenceNV;
-PFNGLMAPCONTROLPOINTSNVPROC glad_glMapControlPointsNV;
-PFNGLMAPPARAMETERIVNVPROC glad_glMapParameterivNV;
-PFNGLMAPPARAMETERFVNVPROC glad_glMapParameterfvNV;
-PFNGLGETMAPCONTROLPOINTSNVPROC glad_glGetMapControlPointsNV;
-PFNGLGETMAPPARAMETERIVNVPROC glad_glGetMapParameterivNV;
-PFNGLGETMAPPARAMETERFVNVPROC glad_glGetMapParameterfvNV;
-PFNGLGETMAPATTRIBPARAMETERIVNVPROC glad_glGetMapAttribParameterivNV;
-PFNGLGETMAPATTRIBPARAMETERFVNVPROC glad_glGetMapAttribParameterfvNV;
-PFNGLEVALMAPSNVPROC glad_glEvalMapsNV;
-PFNGLGETMULTISAMPLEFVNVPROC glad_glGetMultisamplefvNV;
-PFNGLSAMPLEMASKINDEXEDNVPROC glad_glSampleMaskIndexedNV;
-PFNGLTEXRENDERBUFFERNVPROC glad_glTexRenderbufferNV;
-PFNGLDELETEFENCESNVPROC glad_glDeleteFencesNV;
-PFNGLGENFENCESNVPROC glad_glGenFencesNV;
-PFNGLISFENCENVPROC glad_glIsFenceNV;
-PFNGLTESTFENCENVPROC glad_glTestFenceNV;
-PFNGLGETFENCEIVNVPROC glad_glGetFenceivNV;
-PFNGLFINISHFENCENVPROC glad_glFinishFenceNV;
-PFNGLSETFENCENVPROC glad_glSetFenceNV;
-PFNGLFRAGMENTCOVERAGECOLORNVPROC glad_glFragmentCoverageColorNV;
-PFNGLPROGRAMNAMEDPARAMETER4FNVPROC glad_glProgramNamedParameter4fNV;
-PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC glad_glProgramNamedParameter4fvNV;
-PFNGLPROGRAMNAMEDPARAMETER4DNVPROC glad_glProgramNamedParameter4dNV;
-PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC glad_glProgramNamedParameter4dvNV;
-PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC glad_glGetProgramNamedParameterfvNV;
-PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC glad_glGetProgramNamedParameterdvNV;
-PFNGLCOVERAGEMODULATIONTABLENVPROC glad_glCoverageModulationTableNV;
-PFNGLGETCOVERAGEMODULATIONTABLENVPROC glad_glGetCoverageModulationTableNV;
-PFNGLCOVERAGEMODULATIONNVPROC glad_glCoverageModulationNV;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC glad_glRenderbufferStorageMultisampleCoverageNV;
-PFNGLPROGRAMVERTEXLIMITNVPROC glad_glProgramVertexLimitNV;
-PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT;
-PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC glad_glFramebufferTextureFaceEXT;
-PFNGLRENDERGPUMASKNVPROC glad_glRenderGpuMaskNV;
-PFNGLMULTICASTBUFFERSUBDATANVPROC glad_glMulticastBufferSubDataNV;
-PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC glad_glMulticastCopyBufferSubDataNV;
-PFNGLMULTICASTCOPYIMAGESUBDATANVPROC glad_glMulticastCopyImageSubDataNV;
-PFNGLMULTICASTBLITFRAMEBUFFERNVPROC glad_glMulticastBlitFramebufferNV;
-PFNGLMULTICASTFRAMEBUFFERSAMPLELOCATIONSFVNVPROC glad_glMulticastFramebufferSampleLocationsfvNV;
-PFNGLMULTICASTBARRIERNVPROC glad_glMulticastBarrierNV;
-PFNGLMULTICASTWAITSYNCNVPROC glad_glMulticastWaitSyncNV;
-PFNGLMULTICASTGETQUERYOBJECTIVNVPROC glad_glMulticastGetQueryObjectivNV;
-PFNGLMULTICASTGETQUERYOBJECTUIVNVPROC glad_glMulticastGetQueryObjectuivNV;
-PFNGLMULTICASTGETQUERYOBJECTI64VNVPROC glad_glMulticastGetQueryObjecti64vNV;
-PFNGLMULTICASTGETQUERYOBJECTUI64VNVPROC glad_glMulticastGetQueryObjectui64vNV;
-PFNGLPROGRAMLOCALPARAMETERI4INVPROC glad_glProgramLocalParameterI4iNV;
-PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC glad_glProgramLocalParameterI4ivNV;
-PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC glad_glProgramLocalParametersI4ivNV;
-PFNGLPROGRAMLOCALPARAMETERI4UINVPROC glad_glProgramLocalParameterI4uiNV;
-PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC glad_glProgramLocalParameterI4uivNV;
-PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC glad_glProgramLocalParametersI4uivNV;
-PFNGLPROGRAMENVPARAMETERI4INVPROC glad_glProgramEnvParameterI4iNV;
-PFNGLPROGRAMENVPARAMETERI4IVNVPROC glad_glProgramEnvParameterI4ivNV;
-PFNGLPROGRAMENVPARAMETERSI4IVNVPROC glad_glProgramEnvParametersI4ivNV;
-PFNGLPROGRAMENVPARAMETERI4UINVPROC glad_glProgramEnvParameterI4uiNV;
-PFNGLPROGRAMENVPARAMETERI4UIVNVPROC glad_glProgramEnvParameterI4uivNV;
-PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC glad_glProgramEnvParametersI4uivNV;
-PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC glad_glGetProgramLocalParameterIivNV;
-PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC glad_glGetProgramLocalParameterIuivNV;
-PFNGLGETPROGRAMENVPARAMETERIIVNVPROC glad_glGetProgramEnvParameterIivNV;
-PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC glad_glGetProgramEnvParameterIuivNV;
-PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC glad_glProgramSubroutineParametersuivNV;
-PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC glad_glGetProgramSubroutineParameteruivNV;
-PFNGLVERTEX2HNVPROC glad_glVertex2hNV;
-PFNGLVERTEX2HVNVPROC glad_glVertex2hvNV;
-PFNGLVERTEX3HNVPROC glad_glVertex3hNV;
-PFNGLVERTEX3HVNVPROC glad_glVertex3hvNV;
-PFNGLVERTEX4HNVPROC glad_glVertex4hNV;
-PFNGLVERTEX4HVNVPROC glad_glVertex4hvNV;
-PFNGLNORMAL3HNVPROC glad_glNormal3hNV;
-PFNGLNORMAL3HVNVPROC glad_glNormal3hvNV;
-PFNGLCOLOR3HNVPROC glad_glColor3hNV;
-PFNGLCOLOR3HVNVPROC glad_glColor3hvNV;
-PFNGLCOLOR4HNVPROC glad_glColor4hNV;
-PFNGLCOLOR4HVNVPROC glad_glColor4hvNV;
-PFNGLTEXCOORD1HNVPROC glad_glTexCoord1hNV;
-PFNGLTEXCOORD1HVNVPROC glad_glTexCoord1hvNV;
-PFNGLTEXCOORD2HNVPROC glad_glTexCoord2hNV;
-PFNGLTEXCOORD2HVNVPROC glad_glTexCoord2hvNV;
-PFNGLTEXCOORD3HNVPROC glad_glTexCoord3hNV;
-PFNGLTEXCOORD3HVNVPROC glad_glTexCoord3hvNV;
-PFNGLTEXCOORD4HNVPROC glad_glTexCoord4hNV;
-PFNGLTEXCOORD4HVNVPROC glad_glTexCoord4hvNV;
-PFNGLMULTITEXCOORD1HNVPROC glad_glMultiTexCoord1hNV;
-PFNGLMULTITEXCOORD1HVNVPROC glad_glMultiTexCoord1hvNV;
-PFNGLMULTITEXCOORD2HNVPROC glad_glMultiTexCoord2hNV;
-PFNGLMULTITEXCOORD2HVNVPROC glad_glMultiTexCoord2hvNV;
-PFNGLMULTITEXCOORD3HNVPROC glad_glMultiTexCoord3hNV;
-PFNGLMULTITEXCOORD3HVNVPROC glad_glMultiTexCoord3hvNV;
-PFNGLMULTITEXCOORD4HNVPROC glad_glMultiTexCoord4hNV;
-PFNGLMULTITEXCOORD4HVNVPROC glad_glMultiTexCoord4hvNV;
-PFNGLFOGCOORDHNVPROC glad_glFogCoordhNV;
-PFNGLFOGCOORDHVNVPROC glad_glFogCoordhvNV;
-PFNGLSECONDARYCOLOR3HNVPROC glad_glSecondaryColor3hNV;
-PFNGLSECONDARYCOLOR3HVNVPROC glad_glSecondaryColor3hvNV;
-PFNGLVERTEXWEIGHTHNVPROC glad_glVertexWeighthNV;
-PFNGLVERTEXWEIGHTHVNVPROC glad_glVertexWeighthvNV;
-PFNGLVERTEXATTRIB1HNVPROC glad_glVertexAttrib1hNV;
-PFNGLVERTEXATTRIB1HVNVPROC glad_glVertexAttrib1hvNV;
-PFNGLVERTEXATTRIB2HNVPROC glad_glVertexAttrib2hNV;
-PFNGLVERTEXATTRIB2HVNVPROC glad_glVertexAttrib2hvNV;
-PFNGLVERTEXATTRIB3HNVPROC glad_glVertexAttrib3hNV;
-PFNGLVERTEXATTRIB3HVNVPROC glad_glVertexAttrib3hvNV;
-PFNGLVERTEXATTRIB4HNVPROC glad_glVertexAttrib4hNV;
-PFNGLVERTEXATTRIB4HVNVPROC glad_glVertexAttrib4hvNV;
-PFNGLVERTEXATTRIBS1HVNVPROC glad_glVertexAttribs1hvNV;
-PFNGLVERTEXATTRIBS2HVNVPROC glad_glVertexAttribs2hvNV;
-PFNGLVERTEXATTRIBS3HVNVPROC glad_glVertexAttribs3hvNV;
-PFNGLVERTEXATTRIBS4HVNVPROC glad_glVertexAttribs4hvNV;
-PFNGLGETINTERNALFORMATSAMPLEIVNVPROC glad_glGetInternalformatSampleivNV;
-PFNGLGENOCCLUSIONQUERIESNVPROC glad_glGenOcclusionQueriesNV;
-PFNGLDELETEOCCLUSIONQUERIESNVPROC glad_glDeleteOcclusionQueriesNV;
-PFNGLISOCCLUSIONQUERYNVPROC glad_glIsOcclusionQueryNV;
-PFNGLBEGINOCCLUSIONQUERYNVPROC glad_glBeginOcclusionQueryNV;
-PFNGLENDOCCLUSIONQUERYNVPROC glad_glEndOcclusionQueryNV;
-PFNGLGETOCCLUSIONQUERYIVNVPROC glad_glGetOcclusionQueryivNV;
-PFNGLGETOCCLUSIONQUERYUIVNVPROC glad_glGetOcclusionQueryuivNV;
-PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC glad_glProgramBufferParametersfvNV;
-PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC glad_glProgramBufferParametersIivNV;
-PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC glad_glProgramBufferParametersIuivNV;
-PFNGLGENPATHSNVPROC glad_glGenPathsNV;
-PFNGLDELETEPATHSNVPROC glad_glDeletePathsNV;
-PFNGLISPATHNVPROC glad_glIsPathNV;
-PFNGLPATHCOMMANDSNVPROC glad_glPathCommandsNV;
-PFNGLPATHCOORDSNVPROC glad_glPathCoordsNV;
-PFNGLPATHSUBCOMMANDSNVPROC glad_glPathSubCommandsNV;
-PFNGLPATHSUBCOORDSNVPROC glad_glPathSubCoordsNV;
-PFNGLPATHSTRINGNVPROC glad_glPathStringNV;
-PFNGLPATHGLYPHSNVPROC glad_glPathGlyphsNV;
-PFNGLPATHGLYPHRANGENVPROC glad_glPathGlyphRangeNV;
-PFNGLWEIGHTPATHSNVPROC glad_glWeightPathsNV;
-PFNGLCOPYPATHNVPROC glad_glCopyPathNV;
-PFNGLINTERPOLATEPATHSNVPROC glad_glInterpolatePathsNV;
-PFNGLTRANSFORMPATHNVPROC glad_glTransformPathNV;
-PFNGLPATHPARAMETERIVNVPROC glad_glPathParameterivNV;
-PFNGLPATHPARAMETERINVPROC glad_glPathParameteriNV;
-PFNGLPATHPARAMETERFVNVPROC glad_glPathParameterfvNV;
-PFNGLPATHPARAMETERFNVPROC glad_glPathParameterfNV;
-PFNGLPATHDASHARRAYNVPROC glad_glPathDashArrayNV;
-PFNGLPATHSTENCILFUNCNVPROC glad_glPathStencilFuncNV;
-PFNGLPATHSTENCILDEPTHOFFSETNVPROC glad_glPathStencilDepthOffsetNV;
-PFNGLSTENCILFILLPATHNVPROC glad_glStencilFillPathNV;
-PFNGLSTENCILSTROKEPATHNVPROC glad_glStencilStrokePathNV;
-PFNGLSTENCILFILLPATHINSTANCEDNVPROC glad_glStencilFillPathInstancedNV;
-PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC glad_glStencilStrokePathInstancedNV;
-PFNGLPATHCOVERDEPTHFUNCNVPROC glad_glPathCoverDepthFuncNV;
-PFNGLCOVERFILLPATHNVPROC glad_glCoverFillPathNV;
-PFNGLCOVERSTROKEPATHNVPROC glad_glCoverStrokePathNV;
-PFNGLCOVERFILLPATHINSTANCEDNVPROC glad_glCoverFillPathInstancedNV;
-PFNGLCOVERSTROKEPATHINSTANCEDNVPROC glad_glCoverStrokePathInstancedNV;
-PFNGLGETPATHPARAMETERIVNVPROC glad_glGetPathParameterivNV;
-PFNGLGETPATHPARAMETERFVNVPROC glad_glGetPathParameterfvNV;
-PFNGLGETPATHCOMMANDSNVPROC glad_glGetPathCommandsNV;
-PFNGLGETPATHCOORDSNVPROC glad_glGetPathCoordsNV;
-PFNGLGETPATHDASHARRAYNVPROC glad_glGetPathDashArrayNV;
-PFNGLGETPATHMETRICSNVPROC glad_glGetPathMetricsNV;
-PFNGLGETPATHMETRICRANGENVPROC glad_glGetPathMetricRangeNV;
-PFNGLGETPATHSPACINGNVPROC glad_glGetPathSpacingNV;
-PFNGLISPOINTINFILLPATHNVPROC glad_glIsPointInFillPathNV;
-PFNGLISPOINTINSTROKEPATHNVPROC glad_glIsPointInStrokePathNV;
-PFNGLGETPATHLENGTHNVPROC glad_glGetPathLengthNV;
-PFNGLPOINTALONGPATHNVPROC glad_glPointAlongPathNV;
-PFNGLMATRIXLOAD3X2FNVPROC glad_glMatrixLoad3x2fNV;
-PFNGLMATRIXLOAD3X3FNVPROC glad_glMatrixLoad3x3fNV;
-PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC glad_glMatrixLoadTranspose3x3fNV;
-PFNGLMATRIXMULT3X2FNVPROC glad_glMatrixMult3x2fNV;
-PFNGLMATRIXMULT3X3FNVPROC glad_glMatrixMult3x3fNV;
-PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC glad_glMatrixMultTranspose3x3fNV;
-PFNGLSTENCILTHENCOVERFILLPATHNVPROC glad_glStencilThenCoverFillPathNV;
-PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC glad_glStencilThenCoverStrokePathNV;
-PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC glad_glStencilThenCoverFillPathInstancedNV;
-PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC glad_glStencilThenCoverStrokePathInstancedNV;
-PFNGLPATHGLYPHINDEXRANGENVPROC glad_glPathGlyphIndexRangeNV;
-PFNGLPATHGLYPHINDEXARRAYNVPROC glad_glPathGlyphIndexArrayNV;
-PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC glad_glPathMemoryGlyphIndexArrayNV;
-PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC glad_glProgramPathFragmentInputGenNV;
-PFNGLGETPROGRAMRESOURCEFVNVPROC glad_glGetProgramResourcefvNV;
-PFNGLPATHCOLORGENNVPROC glad_glPathColorGenNV;
-PFNGLPATHTEXGENNVPROC glad_glPathTexGenNV;
-PFNGLPATHFOGGENNVPROC glad_glPathFogGenNV;
-PFNGLGETPATHCOLORGENIVNVPROC glad_glGetPathColorGenivNV;
-PFNGLGETPATHCOLORGENFVNVPROC glad_glGetPathColorGenfvNV;
-PFNGLGETPATHTEXGENIVNVPROC glad_glGetPathTexGenivNV;
-PFNGLGETPATHTEXGENFVNVPROC glad_glGetPathTexGenfvNV;
-PFNGLPIXELDATARANGENVPROC glad_glPixelDataRangeNV;
-PFNGLFLUSHPIXELDATARANGENVPROC glad_glFlushPixelDataRangeNV;
-PFNGLPOINTPARAMETERINVPROC glad_glPointParameteriNV;
-PFNGLPOINTPARAMETERIVNVPROC glad_glPointParameterivNV;
-PFNGLPRESENTFRAMEKEYEDNVPROC glad_glPresentFrameKeyedNV;
-PFNGLPRESENTFRAMEDUALFILLNVPROC glad_glPresentFrameDualFillNV;
-PFNGLGETVIDEOIVNVPROC glad_glGetVideoivNV;
-PFNGLGETVIDEOUIVNVPROC glad_glGetVideouivNV;
-PFNGLGETVIDEOI64VNVPROC glad_glGetVideoi64vNV;
-PFNGLGETVIDEOUI64VNVPROC glad_glGetVideoui64vNV;
-PFNGLPRIMITIVERESTARTNVPROC glad_glPrimitiveRestartNV;
-PFNGLPRIMITIVERESTARTINDEXNVPROC glad_glPrimitiveRestartIndexNV;
-PFNGLQUERYRESOURCENVPROC glad_glQueryResourceNV;
-PFNGLGENQUERYRESOURCETAGNVPROC glad_glGenQueryResourceTagNV;
-PFNGLDELETEQUERYRESOURCETAGNVPROC glad_glDeleteQueryResourceTagNV;
-PFNGLQUERYRESOURCETAGNVPROC glad_glQueryResourceTagNV;
-PFNGLCOMBINERPARAMETERFVNVPROC glad_glCombinerParameterfvNV;
-PFNGLCOMBINERPARAMETERFNVPROC glad_glCombinerParameterfNV;
-PFNGLCOMBINERPARAMETERIVNVPROC glad_glCombinerParameterivNV;
-PFNGLCOMBINERPARAMETERINVPROC glad_glCombinerParameteriNV;
-PFNGLCOMBINERINPUTNVPROC glad_glCombinerInputNV;
-PFNGLCOMBINEROUTPUTNVPROC glad_glCombinerOutputNV;
-PFNGLFINALCOMBINERINPUTNVPROC glad_glFinalCombinerInputNV;
-PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC glad_glGetCombinerInputParameterfvNV;
-PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC glad_glGetCombinerInputParameterivNV;
-PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC glad_glGetCombinerOutputParameterfvNV;
-PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC glad_glGetCombinerOutputParameterivNV;
-PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC glad_glGetFinalCombinerInputParameterfvNV;
-PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC glad_glGetFinalCombinerInputParameterivNV;
-PFNGLCOMBINERSTAGEPARAMETERFVNVPROC glad_glCombinerStageParameterfvNV;
-PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC glad_glGetCombinerStageParameterfvNV;
-PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC glad_glFramebufferSampleLocationsfvNV;
-PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC glad_glNamedFramebufferSampleLocationsfvNV;
-PFNGLRESOLVEDEPTHVALUESNVPROC glad_glResolveDepthValuesNV;
-PFNGLMAKEBUFFERRESIDENTNVPROC glad_glMakeBufferResidentNV;
-PFNGLMAKEBUFFERNONRESIDENTNVPROC glad_glMakeBufferNonResidentNV;
-PFNGLISBUFFERRESIDENTNVPROC glad_glIsBufferResidentNV;
-PFNGLMAKENAMEDBUFFERRESIDENTNVPROC glad_glMakeNamedBufferResidentNV;
-PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC glad_glMakeNamedBufferNonResidentNV;
-PFNGLISNAMEDBUFFERRESIDENTNVPROC glad_glIsNamedBufferResidentNV;
-PFNGLGETBUFFERPARAMETERUI64VNVPROC glad_glGetBufferParameterui64vNV;
-PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC glad_glGetNamedBufferParameterui64vNV;
-PFNGLGETINTEGERUI64VNVPROC glad_glGetIntegerui64vNV;
-PFNGLUNIFORMUI64NVPROC glad_glUniformui64NV;
-PFNGLUNIFORMUI64VNVPROC glad_glUniformui64vNV;
-PFNGLPROGRAMUNIFORMUI64NVPROC glad_glProgramUniformui64NV;
-PFNGLPROGRAMUNIFORMUI64VNVPROC glad_glProgramUniformui64vNV;
-PFNGLTEXTUREBARRIERNVPROC glad_glTextureBarrierNV;
-PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC glad_glTexImage2DMultisampleCoverageNV;
-PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC glad_glTexImage3DMultisampleCoverageNV;
-PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC glad_glTextureImage2DMultisampleNV;
-PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC glad_glTextureImage3DMultisampleNV;
-PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC glad_glTextureImage2DMultisampleCoverageNV;
-PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC glad_glTextureImage3DMultisampleCoverageNV;
-PFNGLBEGINTRANSFORMFEEDBACKNVPROC glad_glBeginTransformFeedbackNV;
-PFNGLENDTRANSFORMFEEDBACKNVPROC glad_glEndTransformFeedbackNV;
-PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC glad_glTransformFeedbackAttribsNV;
-PFNGLBINDBUFFERRANGENVPROC glad_glBindBufferRangeNV;
-PFNGLBINDBUFFEROFFSETNVPROC glad_glBindBufferOffsetNV;
-PFNGLBINDBUFFERBASENVPROC glad_glBindBufferBaseNV;
-PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC glad_glTransformFeedbackVaryingsNV;
-PFNGLACTIVEVARYINGNVPROC glad_glActiveVaryingNV;
-PFNGLGETVARYINGLOCATIONNVPROC glad_glGetVaryingLocationNV;
-PFNGLGETACTIVEVARYINGNVPROC glad_glGetActiveVaryingNV;
-PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC glad_glGetTransformFeedbackVaryingNV;
-PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC glad_glTransformFeedbackStreamAttribsNV;
-PFNGLBINDTRANSFORMFEEDBACKNVPROC glad_glBindTransformFeedbackNV;
-PFNGLDELETETRANSFORMFEEDBACKSNVPROC glad_glDeleteTransformFeedbacksNV;
-PFNGLGENTRANSFORMFEEDBACKSNVPROC glad_glGenTransformFeedbacksNV;
-PFNGLISTRANSFORMFEEDBACKNVPROC glad_glIsTransformFeedbackNV;
-PFNGLPAUSETRANSFORMFEEDBACKNVPROC glad_glPauseTransformFeedbackNV;
-PFNGLRESUMETRANSFORMFEEDBACKNVPROC glad_glResumeTransformFeedbackNV;
-PFNGLDRAWTRANSFORMFEEDBACKNVPROC glad_glDrawTransformFeedbackNV;
-PFNGLVDPAUINITNVPROC glad_glVDPAUInitNV;
-PFNGLVDPAUFININVPROC glad_glVDPAUFiniNV;
-PFNGLVDPAUREGISTERVIDEOSURFACENVPROC glad_glVDPAURegisterVideoSurfaceNV;
-PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC glad_glVDPAURegisterOutputSurfaceNV;
-PFNGLVDPAUISSURFACENVPROC glad_glVDPAUIsSurfaceNV;
-PFNGLVDPAUUNREGISTERSURFACENVPROC glad_glVDPAUUnregisterSurfaceNV;
-PFNGLVDPAUGETSURFACEIVNVPROC glad_glVDPAUGetSurfaceivNV;
-PFNGLVDPAUSURFACEACCESSNVPROC glad_glVDPAUSurfaceAccessNV;
-PFNGLVDPAUMAPSURFACESNVPROC glad_glVDPAUMapSurfacesNV;
-PFNGLVDPAUUNMAPSURFACESNVPROC glad_glVDPAUUnmapSurfacesNV;
-PFNGLFLUSHVERTEXARRAYRANGENVPROC glad_glFlushVertexArrayRangeNV;
-PFNGLVERTEXARRAYRANGENVPROC glad_glVertexArrayRangeNV;
-PFNGLVERTEXATTRIBL1I64NVPROC glad_glVertexAttribL1i64NV;
-PFNGLVERTEXATTRIBL2I64NVPROC glad_glVertexAttribL2i64NV;
-PFNGLVERTEXATTRIBL3I64NVPROC glad_glVertexAttribL3i64NV;
-PFNGLVERTEXATTRIBL4I64NVPROC glad_glVertexAttribL4i64NV;
-PFNGLVERTEXATTRIBL1I64VNVPROC glad_glVertexAttribL1i64vNV;
-PFNGLVERTEXATTRIBL2I64VNVPROC glad_glVertexAttribL2i64vNV;
-PFNGLVERTEXATTRIBL3I64VNVPROC glad_glVertexAttribL3i64vNV;
-PFNGLVERTEXATTRIBL4I64VNVPROC glad_glVertexAttribL4i64vNV;
-PFNGLVERTEXATTRIBL1UI64NVPROC glad_glVertexAttribL1ui64NV;
-PFNGLVERTEXATTRIBL2UI64NVPROC glad_glVertexAttribL2ui64NV;
-PFNGLVERTEXATTRIBL3UI64NVPROC glad_glVertexAttribL3ui64NV;
-PFNGLVERTEXATTRIBL4UI64NVPROC glad_glVertexAttribL4ui64NV;
-PFNGLVERTEXATTRIBL1UI64VNVPROC glad_glVertexAttribL1ui64vNV;
-PFNGLVERTEXATTRIBL2UI64VNVPROC glad_glVertexAttribL2ui64vNV;
-PFNGLVERTEXATTRIBL3UI64VNVPROC glad_glVertexAttribL3ui64vNV;
-PFNGLVERTEXATTRIBL4UI64VNVPROC glad_glVertexAttribL4ui64vNV;
-PFNGLGETVERTEXATTRIBLI64VNVPROC glad_glGetVertexAttribLi64vNV;
-PFNGLGETVERTEXATTRIBLUI64VNVPROC glad_glGetVertexAttribLui64vNV;
-PFNGLVERTEXATTRIBLFORMATNVPROC glad_glVertexAttribLFormatNV;
-PFNGLBUFFERADDRESSRANGENVPROC glad_glBufferAddressRangeNV;
-PFNGLVERTEXFORMATNVPROC glad_glVertexFormatNV;
-PFNGLNORMALFORMATNVPROC glad_glNormalFormatNV;
-PFNGLCOLORFORMATNVPROC glad_glColorFormatNV;
-PFNGLINDEXFORMATNVPROC glad_glIndexFormatNV;
-PFNGLTEXCOORDFORMATNVPROC glad_glTexCoordFormatNV;
-PFNGLEDGEFLAGFORMATNVPROC glad_glEdgeFlagFormatNV;
-PFNGLSECONDARYCOLORFORMATNVPROC glad_glSecondaryColorFormatNV;
-PFNGLFOGCOORDFORMATNVPROC glad_glFogCoordFormatNV;
-PFNGLVERTEXATTRIBFORMATNVPROC glad_glVertexAttribFormatNV;
-PFNGLVERTEXATTRIBIFORMATNVPROC glad_glVertexAttribIFormatNV;
-PFNGLGETINTEGERUI64I_VNVPROC glad_glGetIntegerui64i_vNV;
-PFNGLAREPROGRAMSRESIDENTNVPROC glad_glAreProgramsResidentNV;
-PFNGLBINDPROGRAMNVPROC glad_glBindProgramNV;
-PFNGLDELETEPROGRAMSNVPROC glad_glDeleteProgramsNV;
-PFNGLEXECUTEPROGRAMNVPROC glad_glExecuteProgramNV;
-PFNGLGENPROGRAMSNVPROC glad_glGenProgramsNV;
-PFNGLGETPROGRAMPARAMETERDVNVPROC glad_glGetProgramParameterdvNV;
-PFNGLGETPROGRAMPARAMETERFVNVPROC glad_glGetProgramParameterfvNV;
-PFNGLGETPROGRAMIVNVPROC glad_glGetProgramivNV;
-PFNGLGETPROGRAMSTRINGNVPROC glad_glGetProgramStringNV;
-PFNGLGETTRACKMATRIXIVNVPROC glad_glGetTrackMatrixivNV;
-PFNGLGETVERTEXATTRIBDVNVPROC glad_glGetVertexAttribdvNV;
-PFNGLGETVERTEXATTRIBFVNVPROC glad_glGetVertexAttribfvNV;
-PFNGLGETVERTEXATTRIBIVNVPROC glad_glGetVertexAttribivNV;
-PFNGLGETVERTEXATTRIBPOINTERVNVPROC glad_glGetVertexAttribPointervNV;
-PFNGLISPROGRAMNVPROC glad_glIsProgramNV;
-PFNGLLOADPROGRAMNVPROC glad_glLoadProgramNV;
-PFNGLPROGRAMPARAMETER4DNVPROC glad_glProgramParameter4dNV;
-PFNGLPROGRAMPARAMETER4DVNVPROC glad_glProgramParameter4dvNV;
-PFNGLPROGRAMPARAMETER4FNVPROC glad_glProgramParameter4fNV;
-PFNGLPROGRAMPARAMETER4FVNVPROC glad_glProgramParameter4fvNV;
-PFNGLPROGRAMPARAMETERS4DVNVPROC glad_glProgramParameters4dvNV;
-PFNGLPROGRAMPARAMETERS4FVNVPROC glad_glProgramParameters4fvNV;
-PFNGLREQUESTRESIDENTPROGRAMSNVPROC glad_glRequestResidentProgramsNV;
-PFNGLTRACKMATRIXNVPROC glad_glTrackMatrixNV;
-PFNGLVERTEXATTRIBPOINTERNVPROC glad_glVertexAttribPointerNV;
-PFNGLVERTEXATTRIB1DNVPROC glad_glVertexAttrib1dNV;
-PFNGLVERTEXATTRIB1DVNVPROC glad_glVertexAttrib1dvNV;
-PFNGLVERTEXATTRIB1FNVPROC glad_glVertexAttrib1fNV;
-PFNGLVERTEXATTRIB1FVNVPROC glad_glVertexAttrib1fvNV;
-PFNGLVERTEXATTRIB1SNVPROC glad_glVertexAttrib1sNV;
-PFNGLVERTEXATTRIB1SVNVPROC glad_glVertexAttrib1svNV;
-PFNGLVERTEXATTRIB2DNVPROC glad_glVertexAttrib2dNV;
-PFNGLVERTEXATTRIB2DVNVPROC glad_glVertexAttrib2dvNV;
-PFNGLVERTEXATTRIB2FNVPROC glad_glVertexAttrib2fNV;
-PFNGLVERTEXATTRIB2FVNVPROC glad_glVertexAttrib2fvNV;
-PFNGLVERTEXATTRIB2SNVPROC glad_glVertexAttrib2sNV;
-PFNGLVERTEXATTRIB2SVNVPROC glad_glVertexAttrib2svNV;
-PFNGLVERTEXATTRIB3DNVPROC glad_glVertexAttrib3dNV;
-PFNGLVERTEXATTRIB3DVNVPROC glad_glVertexAttrib3dvNV;
-PFNGLVERTEXATTRIB3FNVPROC glad_glVertexAttrib3fNV;
-PFNGLVERTEXATTRIB3FVNVPROC glad_glVertexAttrib3fvNV;
-PFNGLVERTEXATTRIB3SNVPROC glad_glVertexAttrib3sNV;
-PFNGLVERTEXATTRIB3SVNVPROC glad_glVertexAttrib3svNV;
-PFNGLVERTEXATTRIB4DNVPROC glad_glVertexAttrib4dNV;
-PFNGLVERTEXATTRIB4DVNVPROC glad_glVertexAttrib4dvNV;
-PFNGLVERTEXATTRIB4FNVPROC glad_glVertexAttrib4fNV;
-PFNGLVERTEXATTRIB4FVNVPROC glad_glVertexAttrib4fvNV;
-PFNGLVERTEXATTRIB4SNVPROC glad_glVertexAttrib4sNV;
-PFNGLVERTEXATTRIB4SVNVPROC glad_glVertexAttrib4svNV;
-PFNGLVERTEXATTRIB4UBNVPROC glad_glVertexAttrib4ubNV;
-PFNGLVERTEXATTRIB4UBVNVPROC glad_glVertexAttrib4ubvNV;
-PFNGLVERTEXATTRIBS1DVNVPROC glad_glVertexAttribs1dvNV;
-PFNGLVERTEXATTRIBS1FVNVPROC glad_glVertexAttribs1fvNV;
-PFNGLVERTEXATTRIBS1SVNVPROC glad_glVertexAttribs1svNV;
-PFNGLVERTEXATTRIBS2DVNVPROC glad_glVertexAttribs2dvNV;
-PFNGLVERTEXATTRIBS2FVNVPROC glad_glVertexAttribs2fvNV;
-PFNGLVERTEXATTRIBS2SVNVPROC glad_glVertexAttribs2svNV;
-PFNGLVERTEXATTRIBS3DVNVPROC glad_glVertexAttribs3dvNV;
-PFNGLVERTEXATTRIBS3FVNVPROC glad_glVertexAttribs3fvNV;
-PFNGLVERTEXATTRIBS3SVNVPROC glad_glVertexAttribs3svNV;
-PFNGLVERTEXATTRIBS4DVNVPROC glad_glVertexAttribs4dvNV;
-PFNGLVERTEXATTRIBS4FVNVPROC glad_glVertexAttribs4fvNV;
-PFNGLVERTEXATTRIBS4SVNVPROC glad_glVertexAttribs4svNV;
-PFNGLVERTEXATTRIBS4UBVNVPROC glad_glVertexAttribs4ubvNV;
-PFNGLVERTEXATTRIBI1IEXTPROC glad_glVertexAttribI1iEXT;
-PFNGLVERTEXATTRIBI2IEXTPROC glad_glVertexAttribI2iEXT;
-PFNGLVERTEXATTRIBI3IEXTPROC glad_glVertexAttribI3iEXT;
-PFNGLVERTEXATTRIBI4IEXTPROC glad_glVertexAttribI4iEXT;
-PFNGLVERTEXATTRIBI1UIEXTPROC glad_glVertexAttribI1uiEXT;
-PFNGLVERTEXATTRIBI2UIEXTPROC glad_glVertexAttribI2uiEXT;
-PFNGLVERTEXATTRIBI3UIEXTPROC glad_glVertexAttribI3uiEXT;
-PFNGLVERTEXATTRIBI4UIEXTPROC glad_glVertexAttribI4uiEXT;
-PFNGLVERTEXATTRIBI1IVEXTPROC glad_glVertexAttribI1ivEXT;
-PFNGLVERTEXATTRIBI2IVEXTPROC glad_glVertexAttribI2ivEXT;
-PFNGLVERTEXATTRIBI3IVEXTPROC glad_glVertexAttribI3ivEXT;
-PFNGLVERTEXATTRIBI4IVEXTPROC glad_glVertexAttribI4ivEXT;
-PFNGLVERTEXATTRIBI1UIVEXTPROC glad_glVertexAttribI1uivEXT;
-PFNGLVERTEXATTRIBI2UIVEXTPROC glad_glVertexAttribI2uivEXT;
-PFNGLVERTEXATTRIBI3UIVEXTPROC glad_glVertexAttribI3uivEXT;
-PFNGLVERTEXATTRIBI4UIVEXTPROC glad_glVertexAttribI4uivEXT;
-PFNGLVERTEXATTRIBI4BVEXTPROC glad_glVertexAttribI4bvEXT;
-PFNGLVERTEXATTRIBI4SVEXTPROC glad_glVertexAttribI4svEXT;
-PFNGLVERTEXATTRIBI4UBVEXTPROC glad_glVertexAttribI4ubvEXT;
-PFNGLVERTEXATTRIBI4USVEXTPROC glad_glVertexAttribI4usvEXT;
-PFNGLVERTEXATTRIBIPOINTEREXTPROC glad_glVertexAttribIPointerEXT;
-PFNGLGETVERTEXATTRIBIIVEXTPROC glad_glGetVertexAttribIivEXT;
-PFNGLGETVERTEXATTRIBIUIVEXTPROC glad_glGetVertexAttribIuivEXT;
-PFNGLBEGINVIDEOCAPTURENVPROC glad_glBeginVideoCaptureNV;
-PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC glad_glBindVideoCaptureStreamBufferNV;
-PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC glad_glBindVideoCaptureStreamTextureNV;
-PFNGLENDVIDEOCAPTURENVPROC glad_glEndVideoCaptureNV;
-PFNGLGETVIDEOCAPTUREIVNVPROC glad_glGetVideoCaptureivNV;
-PFNGLGETVIDEOCAPTURESTREAMIVNVPROC glad_glGetVideoCaptureStreamivNV;
-PFNGLGETVIDEOCAPTURESTREAMFVNVPROC glad_glGetVideoCaptureStreamfvNV;
-PFNGLGETVIDEOCAPTURESTREAMDVNVPROC glad_glGetVideoCaptureStreamdvNV;
-PFNGLVIDEOCAPTURENVPROC glad_glVideoCaptureNV;
-PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC glad_glVideoCaptureStreamParameterivNV;
-PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC glad_glVideoCaptureStreamParameterfvNV;
-PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC glad_glVideoCaptureStreamParameterdvNV;
-PFNGLVIEWPORTSWIZZLENVPROC glad_glViewportSwizzleNV;
-PFNGLMULTITEXCOORD1BOESPROC glad_glMultiTexCoord1bOES;
-PFNGLMULTITEXCOORD1BVOESPROC glad_glMultiTexCoord1bvOES;
-PFNGLMULTITEXCOORD2BOESPROC glad_glMultiTexCoord2bOES;
-PFNGLMULTITEXCOORD2BVOESPROC glad_glMultiTexCoord2bvOES;
-PFNGLMULTITEXCOORD3BOESPROC glad_glMultiTexCoord3bOES;
-PFNGLMULTITEXCOORD3BVOESPROC glad_glMultiTexCoord3bvOES;
-PFNGLMULTITEXCOORD4BOESPROC glad_glMultiTexCoord4bOES;
-PFNGLMULTITEXCOORD4BVOESPROC glad_glMultiTexCoord4bvOES;
-PFNGLTEXCOORD1BOESPROC glad_glTexCoord1bOES;
-PFNGLTEXCOORD1BVOESPROC glad_glTexCoord1bvOES;
-PFNGLTEXCOORD2BOESPROC glad_glTexCoord2bOES;
-PFNGLTEXCOORD2BVOESPROC glad_glTexCoord2bvOES;
-PFNGLTEXCOORD3BOESPROC glad_glTexCoord3bOES;
-PFNGLTEXCOORD3BVOESPROC glad_glTexCoord3bvOES;
-PFNGLTEXCOORD4BOESPROC glad_glTexCoord4bOES;
-PFNGLTEXCOORD4BVOESPROC glad_glTexCoord4bvOES;
-PFNGLVERTEX2BOESPROC glad_glVertex2bOES;
-PFNGLVERTEX2BVOESPROC glad_glVertex2bvOES;
-PFNGLVERTEX3BOESPROC glad_glVertex3bOES;
-PFNGLVERTEX3BVOESPROC glad_glVertex3bvOES;
-PFNGLVERTEX4BOESPROC glad_glVertex4bOES;
-PFNGLVERTEX4BVOESPROC glad_glVertex4bvOES;
-PFNGLALPHAFUNCXOESPROC glad_glAlphaFuncxOES;
-PFNGLCLEARCOLORXOESPROC glad_glClearColorxOES;
-PFNGLCLEARDEPTHXOESPROC glad_glClearDepthxOES;
-PFNGLCLIPPLANEXOESPROC glad_glClipPlanexOES;
-PFNGLCOLOR4XOESPROC glad_glColor4xOES;
-PFNGLDEPTHRANGEXOESPROC glad_glDepthRangexOES;
-PFNGLFOGXOESPROC glad_glFogxOES;
-PFNGLFOGXVOESPROC glad_glFogxvOES;
-PFNGLFRUSTUMXOESPROC glad_glFrustumxOES;
-PFNGLGETCLIPPLANEXOESPROC glad_glGetClipPlanexOES;
-PFNGLGETFIXEDVOESPROC glad_glGetFixedvOES;
-PFNGLGETTEXENVXVOESPROC glad_glGetTexEnvxvOES;
-PFNGLGETTEXPARAMETERXVOESPROC glad_glGetTexParameterxvOES;
-PFNGLLIGHTMODELXOESPROC glad_glLightModelxOES;
-PFNGLLIGHTMODELXVOESPROC glad_glLightModelxvOES;
-PFNGLLIGHTXOESPROC glad_glLightxOES;
-PFNGLLIGHTXVOESPROC glad_glLightxvOES;
-PFNGLLINEWIDTHXOESPROC glad_glLineWidthxOES;
-PFNGLLOADMATRIXXOESPROC glad_glLoadMatrixxOES;
-PFNGLMATERIALXOESPROC glad_glMaterialxOES;
-PFNGLMATERIALXVOESPROC glad_glMaterialxvOES;
-PFNGLMULTMATRIXXOESPROC glad_glMultMatrixxOES;
-PFNGLMULTITEXCOORD4XOESPROC glad_glMultiTexCoord4xOES;
-PFNGLNORMAL3XOESPROC glad_glNormal3xOES;
-PFNGLORTHOXOESPROC glad_glOrthoxOES;
-PFNGLPOINTPARAMETERXVOESPROC glad_glPointParameterxvOES;
-PFNGLPOINTSIZEXOESPROC glad_glPointSizexOES;
-PFNGLPOLYGONOFFSETXOESPROC glad_glPolygonOffsetxOES;
-PFNGLROTATEXOESPROC glad_glRotatexOES;
-PFNGLSCALEXOESPROC glad_glScalexOES;
-PFNGLTEXENVXOESPROC glad_glTexEnvxOES;
-PFNGLTEXENVXVOESPROC glad_glTexEnvxvOES;
-PFNGLTEXPARAMETERXOESPROC glad_glTexParameterxOES;
-PFNGLTEXPARAMETERXVOESPROC glad_glTexParameterxvOES;
-PFNGLTRANSLATEXOESPROC glad_glTranslatexOES;
-PFNGLGETLIGHTXVOESPROC glad_glGetLightxvOES;
-PFNGLGETMATERIALXVOESPROC glad_glGetMaterialxvOES;
-PFNGLPOINTPARAMETERXOESPROC glad_glPointParameterxOES;
-PFNGLSAMPLECOVERAGEXOESPROC glad_glSampleCoveragexOES;
-PFNGLACCUMXOESPROC glad_glAccumxOES;
-PFNGLBITMAPXOESPROC glad_glBitmapxOES;
-PFNGLBLENDCOLORXOESPROC glad_glBlendColorxOES;
-PFNGLCLEARACCUMXOESPROC glad_glClearAccumxOES;
-PFNGLCOLOR3XOESPROC glad_glColor3xOES;
-PFNGLCOLOR3XVOESPROC glad_glColor3xvOES;
-PFNGLCOLOR4XVOESPROC glad_glColor4xvOES;
-PFNGLCONVOLUTIONPARAMETERXOESPROC glad_glConvolutionParameterxOES;
-PFNGLCONVOLUTIONPARAMETERXVOESPROC glad_glConvolutionParameterxvOES;
-PFNGLEVALCOORD1XOESPROC glad_glEvalCoord1xOES;
-PFNGLEVALCOORD1XVOESPROC glad_glEvalCoord1xvOES;
-PFNGLEVALCOORD2XOESPROC glad_glEvalCoord2xOES;
-PFNGLEVALCOORD2XVOESPROC glad_glEvalCoord2xvOES;
-PFNGLFEEDBACKBUFFERXOESPROC glad_glFeedbackBufferxOES;
-PFNGLGETCONVOLUTIONPARAMETERXVOESPROC glad_glGetConvolutionParameterxvOES;
-PFNGLGETHISTOGRAMPARAMETERXVOESPROC glad_glGetHistogramParameterxvOES;
-PFNGLGETLIGHTXOESPROC glad_glGetLightxOES;
-PFNGLGETMAPXVOESPROC glad_glGetMapxvOES;
-PFNGLGETMATERIALXOESPROC glad_glGetMaterialxOES;
-PFNGLGETPIXELMAPXVPROC glad_glGetPixelMapxv;
-PFNGLGETTEXGENXVOESPROC glad_glGetTexGenxvOES;
-PFNGLGETTEXLEVELPARAMETERXVOESPROC glad_glGetTexLevelParameterxvOES;
-PFNGLINDEXXOESPROC glad_glIndexxOES;
-PFNGLINDEXXVOESPROC glad_glIndexxvOES;
-PFNGLLOADTRANSPOSEMATRIXXOESPROC glad_glLoadTransposeMatrixxOES;
-PFNGLMAP1XOESPROC glad_glMap1xOES;
-PFNGLMAP2XOESPROC glad_glMap2xOES;
-PFNGLMAPGRID1XOESPROC glad_glMapGrid1xOES;
-PFNGLMAPGRID2XOESPROC glad_glMapGrid2xOES;
-PFNGLMULTTRANSPOSEMATRIXXOESPROC glad_glMultTransposeMatrixxOES;
-PFNGLMULTITEXCOORD1XOESPROC glad_glMultiTexCoord1xOES;
-PFNGLMULTITEXCOORD1XVOESPROC glad_glMultiTexCoord1xvOES;
-PFNGLMULTITEXCOORD2XOESPROC glad_glMultiTexCoord2xOES;
-PFNGLMULTITEXCOORD2XVOESPROC glad_glMultiTexCoord2xvOES;
-PFNGLMULTITEXCOORD3XOESPROC glad_glMultiTexCoord3xOES;
-PFNGLMULTITEXCOORD3XVOESPROC glad_glMultiTexCoord3xvOES;
-PFNGLMULTITEXCOORD4XVOESPROC glad_glMultiTexCoord4xvOES;
-PFNGLNORMAL3XVOESPROC glad_glNormal3xvOES;
-PFNGLPASSTHROUGHXOESPROC glad_glPassThroughxOES;
-PFNGLPIXELMAPXPROC glad_glPixelMapx;
-PFNGLPIXELSTOREXPROC glad_glPixelStorex;
-PFNGLPIXELTRANSFERXOESPROC glad_glPixelTransferxOES;
-PFNGLPIXELZOOMXOESPROC glad_glPixelZoomxOES;
-PFNGLPRIORITIZETEXTURESXOESPROC glad_glPrioritizeTexturesxOES;
-PFNGLRASTERPOS2XOESPROC glad_glRasterPos2xOES;
-PFNGLRASTERPOS2XVOESPROC glad_glRasterPos2xvOES;
-PFNGLRASTERPOS3XOESPROC glad_glRasterPos3xOES;
-PFNGLRASTERPOS3XVOESPROC glad_glRasterPos3xvOES;
-PFNGLRASTERPOS4XOESPROC glad_glRasterPos4xOES;
-PFNGLRASTERPOS4XVOESPROC glad_glRasterPos4xvOES;
-PFNGLRECTXOESPROC glad_glRectxOES;
-PFNGLRECTXVOESPROC glad_glRectxvOES;
-PFNGLTEXCOORD1XOESPROC glad_glTexCoord1xOES;
-PFNGLTEXCOORD1XVOESPROC glad_glTexCoord1xvOES;
-PFNGLTEXCOORD2XOESPROC glad_glTexCoord2xOES;
-PFNGLTEXCOORD2XVOESPROC glad_glTexCoord2xvOES;
-PFNGLTEXCOORD3XOESPROC glad_glTexCoord3xOES;
-PFNGLTEXCOORD3XVOESPROC glad_glTexCoord3xvOES;
-PFNGLTEXCOORD4XOESPROC glad_glTexCoord4xOES;
-PFNGLTEXCOORD4XVOESPROC glad_glTexCoord4xvOES;
-PFNGLTEXGENXOESPROC glad_glTexGenxOES;
-PFNGLTEXGENXVOESPROC glad_glTexGenxvOES;
-PFNGLVERTEX2XOESPROC glad_glVertex2xOES;
-PFNGLVERTEX2XVOESPROC glad_glVertex2xvOES;
-PFNGLVERTEX3XOESPROC glad_glVertex3xOES;
-PFNGLVERTEX3XVOESPROC glad_glVertex3xvOES;
-PFNGLVERTEX4XOESPROC glad_glVertex4xOES;
-PFNGLVERTEX4XVOESPROC glad_glVertex4xvOES;
-PFNGLQUERYMATRIXXOESPROC glad_glQueryMatrixxOES;
-PFNGLCLEARDEPTHFOESPROC glad_glClearDepthfOES;
-PFNGLCLIPPLANEFOESPROC glad_glClipPlanefOES;
-PFNGLDEPTHRANGEFOESPROC glad_glDepthRangefOES;
-PFNGLFRUSTUMFOESPROC glad_glFrustumfOES;
-PFNGLGETCLIPPLANEFOESPROC glad_glGetClipPlanefOES;
-PFNGLORTHOFOESPROC glad_glOrthofOES;
-PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR;
-PFNGLHINTPGIPROC glad_glHintPGI;
-PFNGLDETAILTEXFUNCSGISPROC glad_glDetailTexFuncSGIS;
-PFNGLGETDETAILTEXFUNCSGISPROC glad_glGetDetailTexFuncSGIS;
-PFNGLFOGFUNCSGISPROC glad_glFogFuncSGIS;
-PFNGLGETFOGFUNCSGISPROC glad_glGetFogFuncSGIS;
-PFNGLSAMPLEMASKSGISPROC glad_glSampleMaskSGIS;
-PFNGLSAMPLEPATTERNSGISPROC glad_glSamplePatternSGIS;
-PFNGLPIXELTEXGENPARAMETERISGISPROC glad_glPixelTexGenParameteriSGIS;
-PFNGLPIXELTEXGENPARAMETERIVSGISPROC glad_glPixelTexGenParameterivSGIS;
-PFNGLPIXELTEXGENPARAMETERFSGISPROC glad_glPixelTexGenParameterfSGIS;
-PFNGLPIXELTEXGENPARAMETERFVSGISPROC glad_glPixelTexGenParameterfvSGIS;
-PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC glad_glGetPixelTexGenParameterivSGIS;
-PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC glad_glGetPixelTexGenParameterfvSGIS;
-PFNGLPOINTPARAMETERFSGISPROC glad_glPointParameterfSGIS;
-PFNGLPOINTPARAMETERFVSGISPROC glad_glPointParameterfvSGIS;
-PFNGLSHARPENTEXFUNCSGISPROC glad_glSharpenTexFuncSGIS;
-PFNGLGETSHARPENTEXFUNCSGISPROC glad_glGetSharpenTexFuncSGIS;
-PFNGLTEXIMAGE4DSGISPROC glad_glTexImage4DSGIS;
-PFNGLTEXSUBIMAGE4DSGISPROC glad_glTexSubImage4DSGIS;
-PFNGLTEXTURECOLORMASKSGISPROC glad_glTextureColorMaskSGIS;
-PFNGLGETTEXFILTERFUNCSGISPROC glad_glGetTexFilterFuncSGIS;
-PFNGLTEXFILTERFUNCSGISPROC glad_glTexFilterFuncSGIS;
-PFNGLASYNCMARKERSGIXPROC glad_glAsyncMarkerSGIX;
-PFNGLFINISHASYNCSGIXPROC glad_glFinishAsyncSGIX;
-PFNGLPOLLASYNCSGIXPROC glad_glPollAsyncSGIX;
-PFNGLGENASYNCMARKERSSGIXPROC glad_glGenAsyncMarkersSGIX;
-PFNGLDELETEASYNCMARKERSSGIXPROC glad_glDeleteAsyncMarkersSGIX;
-PFNGLISASYNCMARKERSGIXPROC glad_glIsAsyncMarkerSGIX;
-PFNGLFLUSHRASTERSGIXPROC glad_glFlushRasterSGIX;
-PFNGLFRAGMENTCOLORMATERIALSGIXPROC glad_glFragmentColorMaterialSGIX;
-PFNGLFRAGMENTLIGHTFSGIXPROC glad_glFragmentLightfSGIX;
-PFNGLFRAGMENTLIGHTFVSGIXPROC glad_glFragmentLightfvSGIX;
-PFNGLFRAGMENTLIGHTISGIXPROC glad_glFragmentLightiSGIX;
-PFNGLFRAGMENTLIGHTIVSGIXPROC glad_glFragmentLightivSGIX;
-PFNGLFRAGMENTLIGHTMODELFSGIXPROC glad_glFragmentLightModelfSGIX;
-PFNGLFRAGMENTLIGHTMODELFVSGIXPROC glad_glFragmentLightModelfvSGIX;
-PFNGLFRAGMENTLIGHTMODELISGIXPROC glad_glFragmentLightModeliSGIX;
-PFNGLFRAGMENTLIGHTMODELIVSGIXPROC glad_glFragmentLightModelivSGIX;
-PFNGLFRAGMENTMATERIALFSGIXPROC glad_glFragmentMaterialfSGIX;
-PFNGLFRAGMENTMATERIALFVSGIXPROC glad_glFragmentMaterialfvSGIX;
-PFNGLFRAGMENTMATERIALISGIXPROC glad_glFragmentMaterialiSGIX;
-PFNGLFRAGMENTMATERIALIVSGIXPROC glad_glFragmentMaterialivSGIX;
-PFNGLGETFRAGMENTLIGHTFVSGIXPROC glad_glGetFragmentLightfvSGIX;
-PFNGLGETFRAGMENTLIGHTIVSGIXPROC glad_glGetFragmentLightivSGIX;
-PFNGLGETFRAGMENTMATERIALFVSGIXPROC glad_glGetFragmentMaterialfvSGIX;
-PFNGLGETFRAGMENTMATERIALIVSGIXPROC glad_glGetFragmentMaterialivSGIX;
-PFNGLLIGHTENVISGIXPROC glad_glLightEnviSGIX;
-PFNGLFRAMEZOOMSGIXPROC glad_glFrameZoomSGIX;
-PFNGLIGLOOINTERFACESGIXPROC glad_glIglooInterfaceSGIX;
-PFNGLGETINSTRUMENTSSGIXPROC glad_glGetInstrumentsSGIX;
-PFNGLINSTRUMENTSBUFFERSGIXPROC glad_glInstrumentsBufferSGIX;
-PFNGLPOLLINSTRUMENTSSGIXPROC glad_glPollInstrumentsSGIX;
-PFNGLREADINSTRUMENTSSGIXPROC glad_glReadInstrumentsSGIX;
-PFNGLSTARTINSTRUMENTSSGIXPROC glad_glStartInstrumentsSGIX;
-PFNGLSTOPINSTRUMENTSSGIXPROC glad_glStopInstrumentsSGIX;
-PFNGLGETLISTPARAMETERFVSGIXPROC glad_glGetListParameterfvSGIX;
-PFNGLGETLISTPARAMETERIVSGIXPROC glad_glGetListParameterivSGIX;
-PFNGLLISTPARAMETERFSGIXPROC glad_glListParameterfSGIX;
-PFNGLLISTPARAMETERFVSGIXPROC glad_glListParameterfvSGIX;
-PFNGLLISTPARAMETERISGIXPROC glad_glListParameteriSGIX;
-PFNGLLISTPARAMETERIVSGIXPROC glad_glListParameterivSGIX;
-PFNGLPIXELTEXGENSGIXPROC glad_glPixelTexGenSGIX;
-PFNGLDEFORMATIONMAP3DSGIXPROC glad_glDeformationMap3dSGIX;
-PFNGLDEFORMATIONMAP3FSGIXPROC glad_glDeformationMap3fSGIX;
-PFNGLDEFORMSGIXPROC glad_glDeformSGIX;
-PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC glad_glLoadIdentityDeformationMapSGIX;
-PFNGLREFERENCEPLANESGIXPROC glad_glReferencePlaneSGIX;
-PFNGLSPRITEPARAMETERFSGIXPROC glad_glSpriteParameterfSGIX;
-PFNGLSPRITEPARAMETERFVSGIXPROC glad_glSpriteParameterfvSGIX;
-PFNGLSPRITEPARAMETERISGIXPROC glad_glSpriteParameteriSGIX;
-PFNGLSPRITEPARAMETERIVSGIXPROC glad_glSpriteParameterivSGIX;
-PFNGLTAGSAMPLEBUFFERSGIXPROC glad_glTagSampleBufferSGIX;
-PFNGLCOLORTABLESGIPROC glad_glColorTableSGI;
-PFNGLCOLORTABLEPARAMETERFVSGIPROC glad_glColorTableParameterfvSGI;
-PFNGLCOLORTABLEPARAMETERIVSGIPROC glad_glColorTableParameterivSGI;
-PFNGLCOPYCOLORTABLESGIPROC glad_glCopyColorTableSGI;
-PFNGLGETCOLORTABLESGIPROC glad_glGetColorTableSGI;
-PFNGLGETCOLORTABLEPARAMETERFVSGIPROC glad_glGetColorTableParameterfvSGI;
-PFNGLGETCOLORTABLEPARAMETERIVSGIPROC glad_glGetColorTableParameterivSGI;
-PFNGLFINISHTEXTURESUNXPROC glad_glFinishTextureSUNX;
-PFNGLGLOBALALPHAFACTORBSUNPROC glad_glGlobalAlphaFactorbSUN;
-PFNGLGLOBALALPHAFACTORSSUNPROC glad_glGlobalAlphaFactorsSUN;
-PFNGLGLOBALALPHAFACTORISUNPROC glad_glGlobalAlphaFactoriSUN;
-PFNGLGLOBALALPHAFACTORFSUNPROC glad_glGlobalAlphaFactorfSUN;
-PFNGLGLOBALALPHAFACTORDSUNPROC glad_glGlobalAlphaFactordSUN;
-PFNGLGLOBALALPHAFACTORUBSUNPROC glad_glGlobalAlphaFactorubSUN;
-PFNGLGLOBALALPHAFACTORUSSUNPROC glad_glGlobalAlphaFactorusSUN;
-PFNGLGLOBALALPHAFACTORUISUNPROC glad_glGlobalAlphaFactoruiSUN;
-PFNGLDRAWMESHARRAYSSUNPROC glad_glDrawMeshArraysSUN;
-PFNGLREPLACEMENTCODEUISUNPROC glad_glReplacementCodeuiSUN;
-PFNGLREPLACEMENTCODEUSSUNPROC glad_glReplacementCodeusSUN;
-PFNGLREPLACEMENTCODEUBSUNPROC glad_glReplacementCodeubSUN;
-PFNGLREPLACEMENTCODEUIVSUNPROC glad_glReplacementCodeuivSUN;
-PFNGLREPLACEMENTCODEUSVSUNPROC glad_glReplacementCodeusvSUN;
-PFNGLREPLACEMENTCODEUBVSUNPROC glad_glReplacementCodeubvSUN;
-PFNGLREPLACEMENTCODEPOINTERSUNPROC glad_glReplacementCodePointerSUN;
-PFNGLCOLOR4UBVERTEX2FSUNPROC glad_glColor4ubVertex2fSUN;
-PFNGLCOLOR4UBVERTEX2FVSUNPROC glad_glColor4ubVertex2fvSUN;
-PFNGLCOLOR4UBVERTEX3FSUNPROC glad_glColor4ubVertex3fSUN;
-PFNGLCOLOR4UBVERTEX3FVSUNPROC glad_glColor4ubVertex3fvSUN;
-PFNGLCOLOR3FVERTEX3FSUNPROC glad_glColor3fVertex3fSUN;
-PFNGLCOLOR3FVERTEX3FVSUNPROC glad_glColor3fVertex3fvSUN;
-PFNGLNORMAL3FVERTEX3FSUNPROC glad_glNormal3fVertex3fSUN;
-PFNGLNORMAL3FVERTEX3FVSUNPROC glad_glNormal3fVertex3fvSUN;
-PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glColor4fNormal3fVertex3fSUN;
-PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glColor4fNormal3fVertex3fvSUN;
-PFNGLTEXCOORD2FVERTEX3FSUNPROC glad_glTexCoord2fVertex3fSUN;
-PFNGLTEXCOORD2FVERTEX3FVSUNPROC glad_glTexCoord2fVertex3fvSUN;
-PFNGLTEXCOORD4FVERTEX4FSUNPROC glad_glTexCoord4fVertex4fSUN;
-PFNGLTEXCOORD4FVERTEX4FVSUNPROC glad_glTexCoord4fVertex4fvSUN;
-PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC glad_glTexCoord2fColor4ubVertex3fSUN;
-PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC glad_glTexCoord2fColor4ubVertex3fvSUN;
-PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC glad_glTexCoord2fColor3fVertex3fSUN;
-PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC glad_glTexCoord2fColor3fVertex3fvSUN;
-PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC glad_glTexCoord2fNormal3fVertex3fSUN;
-PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC glad_glTexCoord2fNormal3fVertex3fvSUN;
-PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glTexCoord2fColor4fNormal3fVertex3fSUN;
-PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glTexCoord2fColor4fNormal3fVertex3fvSUN;
-PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC glad_glTexCoord4fColor4fNormal3fVertex4fSUN;
-PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC glad_glTexCoord4fColor4fNormal3fVertex4fvSUN;
-PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC glad_glReplacementCodeuiVertex3fSUN;
-PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC glad_glReplacementCodeuiVertex3fvSUN;
-PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC glad_glReplacementCodeuiColor4ubVertex3fSUN;
-PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC glad_glReplacementCodeuiColor4ubVertex3fvSUN;
-PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC glad_glReplacementCodeuiColor3fVertex3fSUN;
-PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC glad_glReplacementCodeuiColor3fVertex3fvSUN;
-PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiNormal3fVertex3fSUN;
-PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiNormal3fVertex3fvSUN;
-PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiColor4fNormal3fVertex3fSUN;
-PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiColor4fNormal3fVertex3fvSUN;
-PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC glad_glReplacementCodeuiTexCoord2fVertex3fSUN;
-PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC glad_glReplacementCodeuiTexCoord2fVertex3fvSUN;
-PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN;
-PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN;
-PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN;
-PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN;
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
+PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+int GLAD_GL_SGIX_pixel_tiles = 0;
+int GLAD_GL_EXT_post_depth_coverage = 0;
+int GLAD_GL_APPLE_element_array = 0;
+int GLAD_GL_AMD_multi_draw_indirect = 0;
+int GLAD_GL_EXT_blend_subtract = 0;
+int GLAD_GL_SGIX_tag_sample_buffer = 0;
+int GLAD_GL_NV_point_sprite = 0;
+int GLAD_GL_IBM_texture_mirrored_repeat = 0;
+int GLAD_GL_APPLE_transform_hint = 0;
+int GLAD_GL_ATI_separate_stencil = 0;
+int GLAD_GL_NV_shader_atomic_int64 = 0;
+int GLAD_GL_EXT_semaphore_win32 = 0;
+int GLAD_GL_NV_vertex_program2_option = 0;
+int GLAD_GL_EXT_texture_buffer_object = 0;
+int GLAD_GL_ARB_vertex_blend = 0;
+int GLAD_GL_OVR_multiview = 0;
+int GLAD_GL_AMD_shader_gpu_shader_half_float_fetch = 0;
+int GLAD_GL_NV_vertex_program2 = 0;
+int GLAD_GL_ARB_program_interface_query = 0;
+int GLAD_GL_EXT_misc_attribute = 0;
+int GLAD_GL_NV_multisample_coverage = 0;
+int GLAD_GL_ARB_shading_language_packing = 0;
+int GLAD_GL_EXT_texture_cube_map = 0;
+int GLAD_GL_NV_viewport_array2 = 0;
+int GLAD_GL_ARB_texture_stencil8 = 0;
+int GLAD_GL_EXT_index_func = 0;
+int GLAD_GL_EXT_memory_object_fd = 0;
+int GLAD_GL_OES_compressed_paletted_texture = 0;
+int GLAD_GL_MESA_shader_integer_functions = 0;
+int GLAD_GL_NV_shader_buffer_load = 0;
+int GLAD_GL_EXT_color_subtable = 0;
+int GLAD_GL_SUNX_constant_data = 0;
+int GLAD_GL_EXT_texture_compression_s3tc = 0;
+int GLAD_GL_EXT_multi_draw_arrays = 0;
+int GLAD_GL_ARB_shader_atomic_counters = 0;
+int GLAD_GL_ARB_arrays_of_arrays = 0;
+int GLAD_GL_NV_conditional_render = 0;
+int GLAD_GL_EXT_texture_env_combine = 0;
+int GLAD_GL_NV_fog_distance = 0;
+int GLAD_GL_SGIX_async_histogram = 0;
+int GLAD_GL_MESA_resize_buffers = 0;
+int GLAD_GL_NV_light_max_exponent = 0;
+int GLAD_GL_NV_texture_env_combine4 = 0;
+int GLAD_GL_ARB_spirv_extensions = 0;
+int GLAD_GL_ARB_texture_view = 0;
+int GLAD_GL_ARB_texture_env_combine = 0;
+int GLAD_GL_ARB_map_buffer_range = 0;
+int GLAD_GL_EXT_convolution = 0;
+int GLAD_GL_NV_compute_program5 = 0;
+int GLAD_GL_NV_vertex_attrib_integer_64bit = 0;
+int GLAD_GL_EXT_paletted_texture = 0;
+int GLAD_GL_ARB_texture_buffer_object = 0;
+int GLAD_GL_ATI_pn_triangles = 0;
+int GLAD_GL_SGIX_resample = 0;
+int GLAD_GL_SGIX_flush_raster = 0;
+int GLAD_GL_EXT_light_texture = 0;
+int GLAD_GL_ARB_point_sprite = 0;
+int GLAD_GL_SUN_convolution_border_modes = 0;
+int GLAD_GL_EXT_semaphore_fd = 0;
+int GLAD_GL_NV_parameter_buffer_object2 = 0;
+int GLAD_GL_ARB_half_float_pixel = 0;
+int GLAD_GL_NV_tessellation_program5 = 0;
+int GLAD_GL_REND_screen_coordinates = 0;
+int GLAD_GL_EXT_shared_texture_palette = 0;
+int GLAD_GL_EXT_packed_float = 0;
+int GLAD_GL_OML_subsample = 0;
+int GLAD_GL_SGIX_vertex_preclip = 0;
+int GLAD_GL_SGIX_texture_scale_bias = 0;
+int GLAD_GL_AMD_draw_buffers_blend = 0;
+int GLAD_GL_APPLE_texture_range = 0;
+int GLAD_GL_EXT_texture_array = 0;
+int GLAD_GL_NV_texture_barrier = 0;
+int GLAD_GL_ARB_texture_query_levels = 0;
+int GLAD_GL_NV_texgen_emboss = 0;
+int GLAD_GL_EXT_texture_swizzle = 0;
+int GLAD_GL_ARB_texture_rg = 0;
+int GLAD_GL_ARB_vertex_type_2_10_10_10_rev = 0;
+int GLAD_GL_ARB_fragment_shader = 0;
+int GLAD_GL_3DFX_tbuffer = 0;
+int GLAD_GL_GREMEDY_frame_terminator = 0;
+int GLAD_GL_IBM_cull_vertex = 0;
+int GLAD_GL_EXT_separate_shader_objects = 0;
+int GLAD_GL_NV_texture_multisample = 0;
+int GLAD_GL_ARB_shader_objects = 0;
+int GLAD_GL_ARB_framebuffer_object = 0;
+int GLAD_GL_EXT_external_buffer = 0;
+int GLAD_GL_ATI_envmap_bumpmap = 0;
+int GLAD_GL_AMD_shader_explicit_vertex_parameter = 0;
+int GLAD_GL_ARB_robust_buffer_access_behavior = 0;
+int GLAD_GL_ARB_shader_stencil_export = 0;
+int GLAD_GL_NV_texture_rectangle = 0;
+int GLAD_GL_ARB_enhanced_layouts = 0;
+int GLAD_GL_ARB_texture_rectangle = 0;
+int GLAD_GL_SGI_texture_color_table = 0;
+int GLAD_GL_NV_viewport_swizzle = 0;
+int GLAD_GL_ATI_map_object_buffer = 0;
+int GLAD_GL_ARB_robustness = 0;
+int GLAD_GL_NV_pixel_data_range = 0;
+int GLAD_GL_EXT_framebuffer_blit = 0;
+int GLAD_GL_ARB_gpu_shader_fp64 = 0;
+int GLAD_GL_NV_command_list = 0;
+int GLAD_GL_SGIX_depth_texture = 0;
+int GLAD_GL_AMD_framebuffer_sample_positions = 0;
+int GLAD_GL_GREMEDY_string_marker = 0;
+int GLAD_GL_ARB_texture_compression_bptc = 0;
+int GLAD_GL_EXT_subtexture = 0;
+int GLAD_GL_EXT_pixel_transform_color_table = 0;
+int GLAD_GL_EXT_texture_compression_rgtc = 0;
+int GLAD_GL_ARB_shader_atomic_counter_ops = 0;
+int GLAD_GL_SGIX_depth_pass_instrument = 0;
+int GLAD_GL_EXT_gpu_program_parameters = 0;
+int GLAD_GL_NV_evaluators = 0;
+int GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent = 0;
+int GLAD_GL_SGIS_texture_filter4 = 0;
+int GLAD_GL_AMD_performance_monitor = 0;
+int GLAD_GL_NV_geometry_shader4 = 0;
+int GLAD_GL_EXT_stencil_clear_tag = 0;
+int GLAD_GL_NV_vertex_program1_1 = 0;
+int GLAD_GL_NV_present_video = 0;
+int GLAD_GL_ARB_texture_compression_rgtc = 0;
+int GLAD_GL_HP_convolution_border_modes = 0;
+int GLAD_GL_EXT_shader_integer_mix = 0;
+int GLAD_GL_SGIX_framezoom = 0;
+int GLAD_GL_ARB_stencil_texturing = 0;
+int GLAD_GL_ARB_shader_clock = 0;
+int GLAD_GL_NV_shader_atomic_fp16_vector = 0;
+int GLAD_GL_SGIX_fog_offset = 0;
+int GLAD_GL_ARB_draw_elements_base_vertex = 0;
+int GLAD_GL_INGR_interlace_read = 0;
+int GLAD_GL_NV_transform_feedback = 0;
+int GLAD_GL_NV_fragment_program = 0;
+int GLAD_GL_AMD_stencil_operation_extended = 0;
+int GLAD_GL_ARB_seamless_cubemap_per_texture = 0;
+int GLAD_GL_ARB_instanced_arrays = 0;
+int GLAD_GL_ARB_get_texture_sub_image = 0;
+int GLAD_GL_NV_vertex_array_range2 = 0;
+int GLAD_GL_KHR_robustness = 0;
+int GLAD_GL_AMD_sparse_texture = 0;
+int GLAD_GL_ARB_clip_control = 0;
+int GLAD_GL_NV_fragment_coverage_to_color = 0;
+int GLAD_GL_NV_fence = 0;
+int GLAD_GL_ARB_texture_buffer_range = 0;
+int GLAD_GL_SUN_mesh_array = 0;
+int GLAD_GL_ARB_vertex_attrib_binding = 0;
+int GLAD_GL_ARB_framebuffer_no_attachments = 0;
+int GLAD_GL_ARB_cl_event = 0;
+int GLAD_GL_EXT_vertex_weighting = 0;
+int GLAD_GL_ARB_derivative_control = 0;
+int GLAD_GL_NV_packed_depth_stencil = 0;
+int GLAD_GL_OES_single_precision = 0;
+int GLAD_GL_NV_primitive_restart = 0;
+int GLAD_GL_SUN_global_alpha = 0;
+int GLAD_GL_ARB_fragment_shader_interlock = 0;
+int GLAD_GL_EXT_texture_object = 0;
+int GLAD_GL_AMD_name_gen_delete = 0;
+int GLAD_GL_NV_texture_compression_vtc = 0;
+int GLAD_GL_NV_sample_mask_override_coverage = 0;
+int GLAD_GL_NV_texture_shader3 = 0;
+int GLAD_GL_MESA_tile_raster_order = 0;
+int GLAD_GL_ARB_texture_filter_anisotropic = 0;
+int GLAD_GL_EXT_texture = 0;
+int GLAD_GL_ARB_buffer_storage = 0;
+int GLAD_GL_AMD_shader_atomic_counter_ops = 0;
+int GLAD_GL_APPLE_vertex_program_evaluators = 0;
+int GLAD_GL_AMD_texture_gather_bias_lod = 0;
+int GLAD_GL_NV_texgen_reflection = 0;
+int GLAD_GL_ARB_explicit_uniform_location = 0;
+int GLAD_GL_ARB_depth_buffer_float = 0;
+int GLAD_GL_NV_path_rendering_shared_edge = 0;
+int GLAD_GL_SGIX_shadow_ambient = 0;
+int GLAD_GL_ARB_texture_cube_map = 0;
+int GLAD_GL_AMD_vertex_shader_viewport_index = 0;
+int GLAD_GL_SGIX_list_priority = 0;
+int GLAD_GL_NV_vertex_buffer_unified_memory = 0;
+int GLAD_GL_NV_uniform_buffer_unified_memory = 0;
+int GLAD_GL_ARB_clear_texture = 0;
+int GLAD_GL_ATI_texture_env_combine3 = 0;
+int GLAD_GL_NV_depth_clamp = 0;
+int GLAD_GL_ARB_map_buffer_alignment = 0;
+int GLAD_GL_EXT_memory_object = 0;
+int GLAD_GL_NV_blend_equation_advanced = 0;
+int GLAD_GL_SGIS_sharpen_texture = 0;
+int GLAD_GL_KHR_robust_buffer_access_behavior = 0;
+int GLAD_GL_ARB_pipeline_statistics_query = 0;
+int GLAD_GL_ARB_vertex_program = 0;
+int GLAD_GL_ARB_texture_rgb10_a2ui = 0;
+int GLAD_GL_OML_interlace = 0;
+int GLAD_GL_ATI_pixel_format_float = 0;
+int GLAD_GL_NV_clip_space_w_scaling = 0;
+int GLAD_GL_ARB_vertex_buffer_object = 0;
+int GLAD_GL_EXT_shadow_funcs = 0;
+int GLAD_GL_ATI_text_fragment_shader = 0;
+int GLAD_GL_NV_vertex_array_range = 0;
+int GLAD_GL_SGIX_fragment_lighting = 0;
+int GLAD_GL_AMD_shader_ballot = 0;
+int GLAD_GL_NV_texture_expand_normal = 0;
+int GLAD_GL_NV_framebuffer_multisample_coverage = 0;
+int GLAD_GL_EXT_timer_query = 0;
+int GLAD_GL_EXT_vertex_array_bgra = 0;
+int GLAD_GL_NV_bindless_texture = 0;
+int GLAD_GL_KHR_debug = 0;
+int GLAD_GL_SGIS_texture_border_clamp = 0;
+int GLAD_GL_ATI_vertex_attrib_array_object = 0;
+int GLAD_GL_SGIX_clipmap = 0;
+int GLAD_GL_EXT_geometry_shader4 = 0;
+int GLAD_GL_ARB_shader_texture_image_samples = 0;
+int GLAD_GL_MESA_ycbcr_texture = 0;
+int GLAD_GL_MESAX_texture_stack = 0;
+int GLAD_GL_AMD_seamless_cubemap_per_texture = 0;
+int GLAD_GL_EXT_bindable_uniform = 0;
+int GLAD_GL_KHR_texture_compression_astc_hdr = 0;
+int GLAD_GL_ARB_shader_ballot = 0;
+int GLAD_GL_KHR_blend_equation_advanced = 0;
+int GLAD_GL_ARB_fragment_program_shadow = 0;
+int GLAD_GL_ATI_element_array = 0;
+int GLAD_GL_AMD_texture_texture4 = 0;
+int GLAD_GL_SGIX_reference_plane = 0;
+int GLAD_GL_EXT_stencil_two_side = 0;
+int GLAD_GL_ARB_transform_feedback_overflow_query = 0;
+int GLAD_GL_SGIX_texture_lod_bias = 0;
+int GLAD_GL_KHR_no_error = 0;
+int GLAD_GL_NV_explicit_multisample = 0;
+int GLAD_GL_NV_stereo_view_rendering = 0;
+int GLAD_GL_IBM_static_data = 0;
+int GLAD_GL_EXT_clip_volume_hint = 0;
+int GLAD_GL_EXT_texture_perturb_normal = 0;
+int GLAD_GL_NV_fragment_program2 = 0;
+int GLAD_GL_NV_fragment_program4 = 0;
+int GLAD_GL_EXT_point_parameters = 0;
+int GLAD_GL_PGI_misc_hints = 0;
+int GLAD_GL_EXT_EGL_image_storage = 0;
+int GLAD_GL_SGIX_subsample = 0;
+int GLAD_GL_AMD_shader_stencil_export = 0;
+int GLAD_GL_ARB_shader_texture_lod = 0;
+int GLAD_GL_ARB_vertex_shader = 0;
+int GLAD_GL_ARB_depth_clamp = 0;
+int GLAD_GL_SGIS_texture_select = 0;
+int GLAD_GL_NV_texture_shader = 0;
+int GLAD_GL_ARB_tessellation_shader = 0;
+int GLAD_GL_EXT_draw_buffers2 = 0;
+int GLAD_GL_ARB_vertex_attrib_64bit = 0;
+int GLAD_GL_EXT_texture_filter_minmax = 0;
+int GLAD_GL_NV_query_resource = 0;
+int GLAD_GL_AMD_interleaved_elements = 0;
+int GLAD_GL_ARB_fragment_program = 0;
+int GLAD_GL_OML_resample = 0;
+int GLAD_GL_APPLE_ycbcr_422 = 0;
+int GLAD_GL_SGIX_texture_add_env = 0;
+int GLAD_GL_ARB_shadow_ambient = 0;
+int GLAD_GL_ARB_texture_storage = 0;
+int GLAD_GL_EXT_pixel_buffer_object = 0;
+int GLAD_GL_ARB_copy_image = 0;
+int GLAD_GL_SGIS_pixel_texture = 0;
+int GLAD_GL_SGIS_generate_mipmap = 0;
+int GLAD_GL_SGIX_instruments = 0;
+int GLAD_GL_ARB_fragment_layer_viewport = 0;
+int GLAD_GL_ARB_shader_storage_buffer_object = 0;
+int GLAD_GL_EXT_sparse_texture2 = 0;
+int GLAD_GL_EXT_blend_minmax = 0;
+int GLAD_GL_MESA_pack_invert = 0;
+int GLAD_GL_ARB_base_instance = 0;
+int GLAD_GL_SGIX_convolution_accuracy = 0;
+int GLAD_GL_PGI_vertex_hints = 0;
+int GLAD_GL_AMD_transform_feedback4 = 0;
+int GLAD_GL_ARB_ES3_1_compatibility = 0;
+int GLAD_GL_EXT_memory_object_win32 = 0;
+int GLAD_GL_EXT_texture_integer = 0;
+int GLAD_GL_ARB_texture_multisample = 0;
+int GLAD_GL_ATI_vertex_streams = 0;
+int GLAD_GL_AMD_gpu_shader_int64 = 0;
+int GLAD_GL_S3_s3tc = 0;
+int GLAD_GL_ARB_query_buffer_object = 0;
+int GLAD_GL_AMD_vertex_shader_tessellator = 0;
+int GLAD_GL_ARB_invalidate_subdata = 0;
+int GLAD_GL_NV_draw_vulkan_image = 0;
+int GLAD_GL_EXT_index_material = 0;
+int GLAD_GL_NVX_linked_gpu_multicast = 0;
+int GLAD_GL_NV_blend_equation_advanced_coherent = 0;
+int GLAD_GL_KHR_texture_compression_astc_sliced_3d = 0;
+int GLAD_GL_INTEL_parallel_arrays = 0;
+int GLAD_GL_ATI_draw_buffers = 0;
+int GLAD_GL_WIN_specular_fog = 0;
+int GLAD_GL_EXT_cmyka = 0;
+int GLAD_GL_SGIX_pixel_texture = 0;
+int GLAD_GL_APPLE_specular_vector = 0;
+int GLAD_GL_ARB_compatibility = 0;
+int GLAD_GL_ARB_timer_query = 0;
+int GLAD_GL_SGIX_interlace = 0;
+int GLAD_GL_NV_parameter_buffer_object = 0;
+int GLAD_GL_AMD_shader_trinary_minmax = 0;
+int GLAD_GL_ARB_direct_state_access = 0;
+int GLAD_GL_EXT_rescale_normal = 0;
+int GLAD_GL_ARB_pixel_buffer_object = 0;
+int GLAD_GL_ARB_uniform_buffer_object = 0;
+int GLAD_GL_ARB_vertex_type_10f_11f_11f_rev = 0;
+int GLAD_GL_ARB_texture_swizzle = 0;
+int GLAD_GL_NV_transform_feedback2 = 0;
+int GLAD_GL_SGIX_async_pixel = 0;
+int GLAD_GL_NV_fragment_program_option = 0;
+int GLAD_GL_ARB_explicit_attrib_location = 0;
+int GLAD_GL_EXT_blend_color = 0;
+int GLAD_GL_NV_shader_thread_group = 0;
+int GLAD_GL_EXT_stencil_wrap = 0;
+int GLAD_GL_EXT_index_array_formats = 0;
+int GLAD_GL_OVR_multiview2 = 0;
+int GLAD_GL_EXT_histogram = 0;
+int GLAD_GL_EXT_polygon_offset = 0;
+int GLAD_GL_SGIS_point_parameters = 0;
+int GLAD_GL_SGIX_ycrcb = 0;
+int GLAD_GL_EXT_direct_state_access = 0;
+int GLAD_GL_ARB_cull_distance = 0;
+int GLAD_GL_AMD_sample_positions = 0;
+int GLAD_GL_NV_vertex_program = 0;
+int GLAD_GL_NV_shader_thread_shuffle = 0;
+int GLAD_GL_ARB_shader_precision = 0;
+int GLAD_GL_EXT_vertex_shader = 0;
+int GLAD_GL_EXT_blend_func_separate = 0;
+int GLAD_GL_APPLE_fence = 0;
+int GLAD_GL_NV_query_resource_tag = 0;
+int GLAD_GL_OES_byte_coordinates = 0;
+int GLAD_GL_ARB_transpose_matrix = 0;
+int GLAD_GL_ARB_provoking_vertex = 0;
+int GLAD_GL_EXT_fog_coord = 0;
+int GLAD_GL_EXT_vertex_array = 0;
+int GLAD_GL_ARB_half_float_vertex = 0;
+int GLAD_GL_EXT_blend_equation_separate = 0;
+int GLAD_GL_NV_framebuffer_mixed_samples = 0;
+int GLAD_GL_NVX_conditional_render = 0;
+int GLAD_GL_ARB_multi_draw_indirect = 0;
+int GLAD_GL_EXT_raster_multisample = 0;
+int GLAD_GL_NV_copy_image = 0;
+int GLAD_GL_HP_texture_lighting = 0;
+int GLAD_GL_INTEL_framebuffer_CMAA = 0;
+int GLAD_GL_ARB_transform_feedback2 = 0;
+int GLAD_GL_ARB_transform_feedback3 = 0;
+int GLAD_GL_SGIX_ycrcba = 0;
+int GLAD_GL_EXT_debug_marker = 0;
+int GLAD_GL_EXT_bgra = 0;
+int GLAD_GL_ARB_sparse_texture_clamp = 0;
+int GLAD_GL_EXT_pixel_transform = 0;
+int GLAD_GL_ARB_conservative_depth = 0;
+int GLAD_GL_ATI_fragment_shader = 0;
+int GLAD_GL_ARB_vertex_array_object = 0;
+int GLAD_GL_SUN_triangle_list = 0;
+int GLAD_GL_EXT_texture_env_add = 0;
+int GLAD_GL_EXT_packed_depth_stencil = 0;
+int GLAD_GL_EXT_texture_mirror_clamp = 0;
+int GLAD_GL_NV_multisample_filter_hint = 0;
+int GLAD_GL_APPLE_float_pixels = 0;
+int GLAD_GL_ARB_transform_feedback_instanced = 0;
+int GLAD_GL_SGIX_async = 0;
+int GLAD_GL_EXT_texture_compression_latc = 0;
+int GLAD_GL_NV_robustness_video_memory_purge = 0;
+int GLAD_GL_ARB_shading_language_100 = 0;
+int GLAD_GL_INTEL_performance_query = 0;
+int GLAD_GL_ARB_texture_mirror_clamp_to_edge = 0;
+int GLAD_GL_NV_gpu_shader5 = 0;
+int GLAD_GL_NV_bindless_multi_draw_indirect_count = 0;
+int GLAD_GL_ARB_ES2_compatibility = 0;
+int GLAD_GL_ARB_indirect_parameters = 0;
+int GLAD_GL_EXT_window_rectangles = 0;
+int GLAD_GL_NV_half_float = 0;
+int GLAD_GL_ARB_ES3_2_compatibility = 0;
+int GLAD_GL_ATI_texture_mirror_once = 0;
+int GLAD_GL_IBM_rasterpos_clip = 0;
+int GLAD_GL_EXT_semaphore = 0;
+int GLAD_GL_SGIX_shadow = 0;
+int GLAD_GL_EXT_polygon_offset_clamp = 0;
+int GLAD_GL_NV_deep_texture3D = 0;
+int GLAD_GL_ARB_shader_draw_parameters = 0;
+int GLAD_GL_SGIX_calligraphic_fragment = 0;
+int GLAD_GL_ARB_shader_bit_encoding = 0;
+int GLAD_GL_EXT_compiled_vertex_array = 0;
+int GLAD_GL_NV_depth_buffer_float = 0;
+int GLAD_GL_NV_occlusion_query = 0;
+int GLAD_GL_APPLE_flush_buffer_range = 0;
+int GLAD_GL_ARB_imaging = 0;
+int GLAD_GL_NV_shader_atomic_float = 0;
+int GLAD_GL_ARB_draw_buffers_blend = 0;
+int GLAD_GL_AMD_gcn_shader = 0;
+int GLAD_GL_AMD_blend_minmax_factor = 0;
+int GLAD_GL_EXT_texture_sRGB_decode = 0;
+int GLAD_GL_ARB_shading_language_420pack = 0;
+int GLAD_GL_ARB_shader_viewport_layer_array = 0;
+int GLAD_GL_ATI_meminfo = 0;
+int GLAD_GL_EXT_abgr = 0;
+int GLAD_GL_AMD_pinned_memory = 0;
+int GLAD_GL_EXT_texture_snorm = 0;
+int GLAD_GL_SGIX_texture_coordinate_clamp = 0;
+int GLAD_GL_ARB_clear_buffer_object = 0;
+int GLAD_GL_ARB_multisample = 0;
+int GLAD_GL_EXT_debug_label = 0;
+int GLAD_GL_ARB_sample_shading = 0;
+int GLAD_GL_NV_internalformat_sample_query = 0;
+int GLAD_GL_INTEL_map_texture = 0;
+int GLAD_GL_ARB_texture_env_crossbar = 0;
+int GLAD_GL_EXT_422_pixels = 0;
+int GLAD_GL_NV_blend_minmax_factor = 0;
+int GLAD_GL_NV_conservative_raster_pre_snap_triangles = 0;
+int GLAD_GL_ARB_compute_shader = 0;
+int GLAD_GL_EXT_blend_logic_op = 0;
+int GLAD_GL_ARB_blend_func_extended = 0;
+int GLAD_GL_IBM_vertex_array_lists = 0;
+int GLAD_GL_ARB_color_buffer_float = 0;
+int GLAD_GL_ARB_bindless_texture = 0;
+int GLAD_GL_ARB_window_pos = 0;
+int GLAD_GL_ARB_internalformat_query = 0;
+int GLAD_GL_ARB_shadow = 0;
+int GLAD_GL_ARB_texture_mirrored_repeat = 0;
+int GLAD_GL_EXT_shader_image_load_store = 0;
+int GLAD_GL_EXT_copy_texture = 0;
+int GLAD_GL_NV_register_combiners2 = 0;
+int GLAD_GL_SGIX_ycrcb_subsample = 0;
+int GLAD_GL_NV_alpha_to_coverage_dither_control = 0;
+int GLAD_GL_SGIX_ir_instrument1 = 0;
+int GLAD_GL_NV_draw_texture = 0;
+int GLAD_GL_EXT_texture_shared_exponent = 0;
+int GLAD_GL_NV_texture_shader2 = 0;
+int GLAD_GL_EXT_draw_instanced = 0;
+int GLAD_GL_NV_copy_depth_to_color = 0;
+int GLAD_GL_ARB_viewport_array = 0;
+int GLAD_GL_ARB_separate_shader_objects = 0;
+int GLAD_GL_NV_conservative_raster_pre_snap = 0;
+int GLAD_GL_EXT_depth_bounds_test = 0;
+int GLAD_GL_HP_image_transform = 0;
+int GLAD_GL_ARB_texture_env_add = 0;
+int GLAD_GL_NV_video_capture = 0;
+int GLAD_GL_ARB_sampler_objects = 0;
+int GLAD_GL_ARB_matrix_palette = 0;
+int GLAD_GL_SGIS_texture_color_mask = 0;
+int GLAD_GL_EXT_packed_pixels = 0;
+int GLAD_GL_EXT_coordinate_frame = 0;
+int GLAD_GL_ARB_texture_compression = 0;
+int GLAD_GL_ARB_multi_bind = 0;
+int GLAD_GL_APPLE_aux_depth_stencil = 0;
+int GLAD_GL_ARB_shader_subroutine = 0;
+int GLAD_GL_EXT_framebuffer_sRGB = 0;
+int GLAD_GL_ARB_texture_storage_multisample = 0;
+int GLAD_GL_KHR_blend_equation_advanced_coherent = 0;
+int GLAD_GL_EXT_vertex_attrib_64bit = 0;
+int GLAD_GL_NV_shader_atomic_float64 = 0;
+int GLAD_GL_ARB_depth_texture = 0;
+int GLAD_GL_NV_shader_buffer_store = 0;
+int GLAD_GL_OES_query_matrix = 0;
+int GLAD_GL_MESA_window_pos = 0;
+int GLAD_GL_NV_fill_rectangle = 0;
+int GLAD_GL_NV_shader_storage_buffer_object = 0;
+int GLAD_GL_ARB_texture_query_lod = 0;
+int GLAD_GL_ARB_copy_buffer = 0;
+int GLAD_GL_ARB_shader_image_size = 0;
+int GLAD_GL_NV_shader_atomic_counters = 0;
+int GLAD_GL_APPLE_object_purgeable = 0;
+int GLAD_GL_ARB_occlusion_query = 0;
+int GLAD_GL_INGR_color_clamp = 0;
+int GLAD_GL_SGI_color_table = 0;
+int GLAD_GL_NV_gpu_program5_mem_extended = 0;
+int GLAD_GL_ARB_texture_cube_map_array = 0;
+int GLAD_GL_SGIX_scalebias_hint = 0;
+int GLAD_GL_EXT_gpu_shader4 = 0;
+int GLAD_GL_NV_geometry_program4 = 0;
+int GLAD_GL_EXT_framebuffer_multisample_blit_scaled = 0;
+int GLAD_GL_AMD_debug_output = 0;
+int GLAD_GL_ARB_texture_border_clamp = 0;
+int GLAD_GL_EXT_win32_keyed_mutex = 0;
+int GLAD_GL_ARB_fragment_coord_conventions = 0;
+int GLAD_GL_ARB_multitexture = 0;
+int GLAD_GL_SGIX_polynomial_ffd = 0;
+int GLAD_GL_EXT_texture_env_dot3 = 0;
+int GLAD_GL_EXT_provoking_vertex = 0;
+int GLAD_GL_ARB_point_parameters = 0;
+int GLAD_GL_ARB_shader_image_load_store = 0;
+int GLAD_GL_ARB_conditional_render_inverted = 0;
+int GLAD_GL_HP_occlusion_test = 0;
+int GLAD_GL_ARB_ES3_compatibility = 0;
+int GLAD_GL_ARB_texture_barrier = 0;
+int GLAD_GL_ARB_texture_buffer_object_rgb32 = 0;
+int GLAD_GL_NV_bindless_multi_draw_indirect = 0;
+int GLAD_GL_SGIX_texture_multi_buffer = 0;
+int GLAD_GL_INTEL_blackhole_render = 0;
+int GLAD_GL_AMD_shader_image_load_store_lod = 0;
+int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
+int GLAD_GL_3DFX_multisample = 0;
+int GLAD_GL_INTEL_fragment_shader_ordering = 0;
+int GLAD_GL_ARB_texture_env_dot3 = 0;
+int GLAD_GL_NV_gpu_program4 = 0;
+int GLAD_GL_NV_gpu_program5 = 0;
+int GLAD_GL_NV_float_buffer = 0;
+int GLAD_GL_SGIS_texture_edge_clamp = 0;
+int GLAD_GL_ARB_framebuffer_sRGB = 0;
+int GLAD_GL_SUN_slice_accum = 0;
+int GLAD_GL_EXT_index_texture = 0;
+int GLAD_GL_EXT_shader_image_load_formatted = 0;
+int GLAD_GL_ARB_geometry_shader4 = 0;
+int GLAD_GL_EXT_separate_specular_color = 0;
+int GLAD_GL_AMD_depth_clamp_separate = 0;
+int GLAD_GL_NV_conservative_raster = 0;
+int GLAD_GL_ARB_sparse_texture2 = 0;
+int GLAD_GL_SGIX_sprite = 0;
+int GLAD_GL_ARB_get_program_binary = 0;
+int GLAD_GL_AMD_occlusion_query_event = 0;
+int GLAD_GL_SGIS_multisample = 0;
+int GLAD_GL_EXT_framebuffer_object = 0;
+int GLAD_GL_ARB_robustness_isolation = 0;
+int GLAD_GL_ARB_vertex_array_bgra = 0;
+int GLAD_GL_APPLE_vertex_array_range = 0;
+int GLAD_GL_AMD_query_buffer_object = 0;
+int GLAD_GL_NV_register_combiners = 0;
+int GLAD_GL_ARB_draw_buffers = 0;
+int GLAD_GL_NVX_blend_equation_advanced_multi_draw_buffers = 0;
+int GLAD_GL_AMD_gpu_shader_int16 = 0;
+int GLAD_GL_ARB_debug_output = 0;
+int GLAD_GL_EXT_shader_framebuffer_fetch = 0;
+int GLAD_GL_SGI_color_matrix = 0;
+int GLAD_GL_EXT_cull_vertex = 0;
+int GLAD_GL_AMD_framebuffer_multisample_advanced = 0;
+int GLAD_GL_EXT_texture_sRGB = 0;
+int GLAD_GL_APPLE_row_bytes = 0;
+int GLAD_GL_NV_conservative_raster_underestimation = 0;
+int GLAD_GL_IBM_multimode_draw_arrays = 0;
+int GLAD_GL_KHR_parallel_shader_compile = 0;
+int GLAD_GL_APPLE_vertex_array_object = 0;
+int GLAD_GL_3DFX_texture_compression_FXT1 = 0;
+int GLAD_GL_NV_fragment_shader_interlock = 0;
+int GLAD_GL_AMD_conservative_depth = 0;
+int GLAD_GL_ARB_texture_float = 0;
+int GLAD_GL_ARB_compressed_texture_pixel_storage = 0;
+int GLAD_GL_SGIS_detail_texture = 0;
+int GLAD_GL_NV_geometry_shader_passthrough = 0;
+int GLAD_GL_ARB_draw_instanced = 0;
+int GLAD_GL_OES_read_format = 0;
+int GLAD_GL_ATI_texture_float = 0;
+int GLAD_GL_ARB_texture_gather = 0;
+int GLAD_GL_AMD_vertex_shader_layer = 0;
+int GLAD_GL_ARB_shading_language_include = 0;
+int GLAD_GL_APPLE_client_storage = 0;
+int GLAD_GL_WIN_phong_shading = 0;
+int GLAD_GL_INGR_blend_func_separate = 0;
+int GLAD_GL_NV_path_rendering = 0;
+int GLAD_GL_NV_conservative_raster_dilate = 0;
+int GLAD_GL_AMD_gpu_shader_half_float = 0;
+int GLAD_GL_ARB_post_depth_coverage = 0;
+int GLAD_GL_ARB_texture_non_power_of_two = 0;
+int GLAD_GL_APPLE_rgb_422 = 0;
+int GLAD_GL_EXT_texture_lod_bias = 0;
+int GLAD_GL_ARB_gpu_shader_int64 = 0;
+int GLAD_GL_ARB_seamless_cube_map = 0;
+int GLAD_GL_ARB_shader_group_vote = 0;
+int GLAD_GL_NV_vdpau_interop = 0;
+int GLAD_GL_ARB_occlusion_query2 = 0;
+int GLAD_GL_ARB_internalformat_query2 = 0;
+int GLAD_GL_EXT_texture_filter_anisotropic = 0;
+int GLAD_GL_SUN_vertex = 0;
+int GLAD_GL_EXT_transform_feedback = 0;
+int GLAD_GL_SGIX_igloo_interface = 0;
+int GLAD_GL_SGIS_texture_lod = 0;
+int GLAD_GL_NV_vertex_program3 = 0;
+int GLAD_GL_ARB_draw_indirect = 0;
+int GLAD_GL_NV_vertex_program4 = 0;
+int GLAD_GL_AMD_transform_feedback3_lines_triangles = 0;
+int GLAD_GL_SGIS_fog_function = 0;
+int GLAD_GL_EXT_x11_sync_object = 0;
+int GLAD_GL_ARB_sync = 0;
+int GLAD_GL_NV_texture_rectangle_compressed = 0;
+int GLAD_GL_NV_sample_locations = 0;
+int GLAD_GL_NV_gpu_multicast = 0;
+int GLAD_GL_ARB_gl_spirv = 0;
+int GLAD_GL_ARB_compute_variable_group_size = 0;
+int GLAD_GL_OES_fixed_point = 0;
+int GLAD_GL_MESA_program_binary_formats = 0;
+int GLAD_GL_NV_blend_square = 0;
+int GLAD_GL_EXT_framebuffer_multisample = 0;
+int GLAD_GL_ARB_gpu_shader5 = 0;
+int GLAD_GL_SGIS_texture4D = 0;
+int GLAD_GL_EXT_texture3D = 0;
+int GLAD_GL_EXT_multisample = 0;
+int GLAD_GL_EXT_secondary_color = 0;
+int GLAD_GL_INTEL_conservative_rasterization = 0;
+int GLAD_GL_ARB_texture_filter_minmax = 0;
+int GLAD_GL_ATI_vertex_array_object = 0;
+int GLAD_GL_ARB_parallel_shader_compile = 0;
+int GLAD_GL_NVX_gpu_memory_info = 0;
+int GLAD_GL_ARB_sparse_texture = 0;
+int GLAD_GL_SGIS_point_line_texgen = 0;
+int GLAD_GL_ARB_sample_locations = 0;
+int GLAD_GL_ARB_sparse_buffer = 0;
+int GLAD_GL_ARB_polygon_offset_clamp = 0;
+int GLAD_GL_EXT_draw_range_elements = 0;
+int GLAD_GL_SGIX_blend_alpha_minmax = 0;
+int GLAD_GL_KHR_context_flush_control = 0;
+PFNGLTBUFFERMASK3DFXPROC glad_glTbufferMask3DFX = NULL;
+PFNGLDEBUGMESSAGEENABLEAMDPROC glad_glDebugMessageEnableAMD = NULL;
+PFNGLDEBUGMESSAGEINSERTAMDPROC glad_glDebugMessageInsertAMD = NULL;
+PFNGLDEBUGMESSAGECALLBACKAMDPROC glad_glDebugMessageCallbackAMD = NULL;
+PFNGLGETDEBUGMESSAGELOGAMDPROC glad_glGetDebugMessageLogAMD = NULL;
+PFNGLBLENDFUNCINDEXEDAMDPROC glad_glBlendFuncIndexedAMD = NULL;
+PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC glad_glBlendFuncSeparateIndexedAMD = NULL;
+PFNGLBLENDEQUATIONINDEXEDAMDPROC glad_glBlendEquationIndexedAMD = NULL;
+PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC glad_glBlendEquationSeparateIndexedAMD = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC glad_glRenderbufferStorageMultisampleAdvancedAMD = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC glad_glNamedRenderbufferStorageMultisampleAdvancedAMD = NULL;
+PFNGLFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC glad_glFramebufferSamplePositionsfvAMD = NULL;
+PFNGLNAMEDFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC glad_glNamedFramebufferSamplePositionsfvAMD = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERFVAMDPROC glad_glGetFramebufferParameterfvAMD = NULL;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERFVAMDPROC glad_glGetNamedFramebufferParameterfvAMD = NULL;
+PFNGLUNIFORM1I64NVPROC glad_glUniform1i64NV = NULL;
+PFNGLUNIFORM2I64NVPROC glad_glUniform2i64NV = NULL;
+PFNGLUNIFORM3I64NVPROC glad_glUniform3i64NV = NULL;
+PFNGLUNIFORM4I64NVPROC glad_glUniform4i64NV = NULL;
+PFNGLUNIFORM1I64VNVPROC glad_glUniform1i64vNV = NULL;
+PFNGLUNIFORM2I64VNVPROC glad_glUniform2i64vNV = NULL;
+PFNGLUNIFORM3I64VNVPROC glad_glUniform3i64vNV = NULL;
+PFNGLUNIFORM4I64VNVPROC glad_glUniform4i64vNV = NULL;
+PFNGLUNIFORM1UI64NVPROC glad_glUniform1ui64NV = NULL;
+PFNGLUNIFORM2UI64NVPROC glad_glUniform2ui64NV = NULL;
+PFNGLUNIFORM3UI64NVPROC glad_glUniform3ui64NV = NULL;
+PFNGLUNIFORM4UI64NVPROC glad_glUniform4ui64NV = NULL;
+PFNGLUNIFORM1UI64VNVPROC glad_glUniform1ui64vNV = NULL;
+PFNGLUNIFORM2UI64VNVPROC glad_glUniform2ui64vNV = NULL;
+PFNGLUNIFORM3UI64VNVPROC glad_glUniform3ui64vNV = NULL;
+PFNGLUNIFORM4UI64VNVPROC glad_glUniform4ui64vNV = NULL;
+PFNGLGETUNIFORMI64VNVPROC glad_glGetUniformi64vNV = NULL;
+PFNGLGETUNIFORMUI64VNVPROC glad_glGetUniformui64vNV = NULL;
+PFNGLPROGRAMUNIFORM1I64NVPROC glad_glProgramUniform1i64NV = NULL;
+PFNGLPROGRAMUNIFORM2I64NVPROC glad_glProgramUniform2i64NV = NULL;
+PFNGLPROGRAMUNIFORM3I64NVPROC glad_glProgramUniform3i64NV = NULL;
+PFNGLPROGRAMUNIFORM4I64NVPROC glad_glProgramUniform4i64NV = NULL;
+PFNGLPROGRAMUNIFORM1I64VNVPROC glad_glProgramUniform1i64vNV = NULL;
+PFNGLPROGRAMUNIFORM2I64VNVPROC glad_glProgramUniform2i64vNV = NULL;
+PFNGLPROGRAMUNIFORM3I64VNVPROC glad_glProgramUniform3i64vNV = NULL;
+PFNGLPROGRAMUNIFORM4I64VNVPROC glad_glProgramUniform4i64vNV = NULL;
+PFNGLPROGRAMUNIFORM1UI64NVPROC glad_glProgramUniform1ui64NV = NULL;
+PFNGLPROGRAMUNIFORM2UI64NVPROC glad_glProgramUniform2ui64NV = NULL;
+PFNGLPROGRAMUNIFORM3UI64NVPROC glad_glProgramUniform3ui64NV = NULL;
+PFNGLPROGRAMUNIFORM4UI64NVPROC glad_glProgramUniform4ui64NV = NULL;
+PFNGLPROGRAMUNIFORM1UI64VNVPROC glad_glProgramUniform1ui64vNV = NULL;
+PFNGLPROGRAMUNIFORM2UI64VNVPROC glad_glProgramUniform2ui64vNV = NULL;
+PFNGLPROGRAMUNIFORM3UI64VNVPROC glad_glProgramUniform3ui64vNV = NULL;
+PFNGLPROGRAMUNIFORM4UI64VNVPROC glad_glProgramUniform4ui64vNV = NULL;
+PFNGLVERTEXATTRIBPARAMETERIAMDPROC glad_glVertexAttribParameteriAMD = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC glad_glMultiDrawArraysIndirectAMD = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC glad_glMultiDrawElementsIndirectAMD = NULL;
+PFNGLGENNAMESAMDPROC glad_glGenNamesAMD = NULL;
+PFNGLDELETENAMESAMDPROC glad_glDeleteNamesAMD = NULL;
+PFNGLISNAMEAMDPROC glad_glIsNameAMD = NULL;
+PFNGLQUERYOBJECTPARAMETERUIAMDPROC glad_glQueryObjectParameteruiAMD = NULL;
+PFNGLGETPERFMONITORGROUPSAMDPROC glad_glGetPerfMonitorGroupsAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERSAMDPROC glad_glGetPerfMonitorCountersAMD = NULL;
+PFNGLGETPERFMONITORGROUPSTRINGAMDPROC glad_glGetPerfMonitorGroupStringAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC glad_glGetPerfMonitorCounterStringAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERINFOAMDPROC glad_glGetPerfMonitorCounterInfoAMD = NULL;
+PFNGLGENPERFMONITORSAMDPROC glad_glGenPerfMonitorsAMD = NULL;
+PFNGLDELETEPERFMONITORSAMDPROC glad_glDeletePerfMonitorsAMD = NULL;
+PFNGLSELECTPERFMONITORCOUNTERSAMDPROC glad_glSelectPerfMonitorCountersAMD = NULL;
+PFNGLBEGINPERFMONITORAMDPROC glad_glBeginPerfMonitorAMD = NULL;
+PFNGLENDPERFMONITORAMDPROC glad_glEndPerfMonitorAMD = NULL;
+PFNGLGETPERFMONITORCOUNTERDATAAMDPROC glad_glGetPerfMonitorCounterDataAMD = NULL;
+PFNGLSETMULTISAMPLEFVAMDPROC glad_glSetMultisamplefvAMD = NULL;
+PFNGLTEXSTORAGESPARSEAMDPROC glad_glTexStorageSparseAMD = NULL;
+PFNGLTEXTURESTORAGESPARSEAMDPROC glad_glTextureStorageSparseAMD = NULL;
+PFNGLSTENCILOPVALUEAMDPROC glad_glStencilOpValueAMD = NULL;
+PFNGLTESSELLATIONFACTORAMDPROC glad_glTessellationFactorAMD = NULL;
+PFNGLTESSELLATIONMODEAMDPROC glad_glTessellationModeAMD = NULL;
+PFNGLELEMENTPOINTERAPPLEPROC glad_glElementPointerAPPLE = NULL;
+PFNGLDRAWELEMENTARRAYAPPLEPROC glad_glDrawElementArrayAPPLE = NULL;
+PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC glad_glDrawRangeElementArrayAPPLE = NULL;
+PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC glad_glMultiDrawElementArrayAPPLE = NULL;
+PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC glad_glMultiDrawRangeElementArrayAPPLE = NULL;
+PFNGLGENFENCESAPPLEPROC glad_glGenFencesAPPLE = NULL;
+PFNGLDELETEFENCESAPPLEPROC glad_glDeleteFencesAPPLE = NULL;
+PFNGLSETFENCEAPPLEPROC glad_glSetFenceAPPLE = NULL;
+PFNGLISFENCEAPPLEPROC glad_glIsFenceAPPLE = NULL;
+PFNGLTESTFENCEAPPLEPROC glad_glTestFenceAPPLE = NULL;
+PFNGLFINISHFENCEAPPLEPROC glad_glFinishFenceAPPLE = NULL;
+PFNGLTESTOBJECTAPPLEPROC glad_glTestObjectAPPLE = NULL;
+PFNGLFINISHOBJECTAPPLEPROC glad_glFinishObjectAPPLE = NULL;
+PFNGLBUFFERPARAMETERIAPPLEPROC glad_glBufferParameteriAPPLE = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glad_glFlushMappedBufferRangeAPPLE = NULL;
+PFNGLOBJECTPURGEABLEAPPLEPROC glad_glObjectPurgeableAPPLE = NULL;
+PFNGLOBJECTUNPURGEABLEAPPLEPROC glad_glObjectUnpurgeableAPPLE = NULL;
+PFNGLGETOBJECTPARAMETERIVAPPLEPROC glad_glGetObjectParameterivAPPLE = NULL;
+PFNGLTEXTURERANGEAPPLEPROC glad_glTextureRangeAPPLE = NULL;
+PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC glad_glGetTexParameterPointervAPPLE = NULL;
+PFNGLBINDVERTEXARRAYAPPLEPROC glad_glBindVertexArrayAPPLE = NULL;
+PFNGLDELETEVERTEXARRAYSAPPLEPROC glad_glDeleteVertexArraysAPPLE = NULL;
+PFNGLGENVERTEXARRAYSAPPLEPROC glad_glGenVertexArraysAPPLE = NULL;
+PFNGLISVERTEXARRAYAPPLEPROC glad_glIsVertexArrayAPPLE = NULL;
+PFNGLVERTEXARRAYRANGEAPPLEPROC glad_glVertexArrayRangeAPPLE = NULL;
+PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC glad_glFlushVertexArrayRangeAPPLE = NULL;
+PFNGLVERTEXARRAYPARAMETERIAPPLEPROC glad_glVertexArrayParameteriAPPLE = NULL;
+PFNGLENABLEVERTEXATTRIBAPPLEPROC glad_glEnableVertexAttribAPPLE = NULL;
+PFNGLDISABLEVERTEXATTRIBAPPLEPROC glad_glDisableVertexAttribAPPLE = NULL;
+PFNGLISVERTEXATTRIBENABLEDAPPLEPROC glad_glIsVertexAttribEnabledAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB1DAPPLEPROC glad_glMapVertexAttrib1dAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB1FAPPLEPROC glad_glMapVertexAttrib1fAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB2DAPPLEPROC glad_glMapVertexAttrib2dAPPLE = NULL;
+PFNGLMAPVERTEXATTRIB2FAPPLEPROC glad_glMapVertexAttrib2fAPPLE = NULL;
+PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL;
+PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
+PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL;
+PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
+PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
+PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion = NULL;
+PFNGLPRIMITIVEBOUNDINGBOXARBPROC glad_glPrimitiveBoundingBoxARB = NULL;
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance = NULL;
+PFNGLGETTEXTUREHANDLEARBPROC glad_glGetTextureHandleARB = NULL;
+PFNGLGETTEXTURESAMPLERHANDLEARBPROC glad_glGetTextureSamplerHandleARB = NULL;
+PFNGLMAKETEXTUREHANDLERESIDENTARBPROC glad_glMakeTextureHandleResidentARB = NULL;
+PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC glad_glMakeTextureHandleNonResidentARB = NULL;
+PFNGLGETIMAGEHANDLEARBPROC glad_glGetImageHandleARB = NULL;
+PFNGLMAKEIMAGEHANDLERESIDENTARBPROC glad_glMakeImageHandleResidentARB = NULL;
+PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC glad_glMakeImageHandleNonResidentARB = NULL;
+PFNGLUNIFORMHANDLEUI64ARBPROC glad_glUniformHandleui64ARB = NULL;
+PFNGLUNIFORMHANDLEUI64VARBPROC glad_glUniformHandleui64vARB = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC glad_glProgramUniformHandleui64ARB = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC glad_glProgramUniformHandleui64vARB = NULL;
+PFNGLISTEXTUREHANDLERESIDENTARBPROC glad_glIsTextureHandleResidentARB = NULL;
+PFNGLISIMAGEHANDLERESIDENTARBPROC glad_glIsImageHandleResidentARB = NULL;
+PFNGLVERTEXATTRIBL1UI64ARBPROC glad_glVertexAttribL1ui64ARB = NULL;
+PFNGLVERTEXATTRIBL1UI64VARBPROC glad_glVertexAttribL1ui64vARB = NULL;
+PFNGLGETVERTEXATTRIBLUI64VARBPROC glad_glGetVertexAttribLui64vARB = NULL;
+PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL;
+PFNGLCREATESYNCFROMCLEVENTARBPROC glad_glCreateSyncFromCLeventARB = NULL;
+PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData = NULL;
+PFNGLCLEARBUFFERSUBDATAPROC glad_glClearBufferSubData = NULL;
+PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage = NULL;
+PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage = NULL;
+PFNGLCLIPCONTROLPROC glad_glClipControl = NULL;
+PFNGLCLAMPCOLORARBPROC glad_glClampColorARB = NULL;
+PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute = NULL;
+PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect = NULL;
+PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC glad_glDispatchComputeGroupSizeARB = NULL;
+PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData = NULL;
+PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
+PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
+PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
+PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
+PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL;
+PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL;
+PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL;
+PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL;
+PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL;
+PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL;
+PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL;
+PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL;
+PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL;
+PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL;
+PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL;
+PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL;
+PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL;
+PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL;
+PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL;
+PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL;
+PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL;
+PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL;
+PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL;
+PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL;
+PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL;
+PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL;
+PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL;
+PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL;
+PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL;
+PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL;
+PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL;
+PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL;
+PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL;
+PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL;
+PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL;
+PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL;
+PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL;
+PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL;
+PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL;
+PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL;
+PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL;
+PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL;
+PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL;
+PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL;
+PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL;
+PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL;
+PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL;
+PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL;
+PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL;
+PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL;
+PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL;
+PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL;
+PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL;
+PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL;
+PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL;
+PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL;
+PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL;
+PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL;
+PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL;
+PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL;
+PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL;
+PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL;
+PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL;
+PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL;
+PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL;
+PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL;
+PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL;
+PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL;
+PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL;
+PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL;
+PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL;
+PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL;
+PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL;
+PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL;
+PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL;
+PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL;
+PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL;
+PFNGLDRAWBUFFERSARBPROC glad_glDrawBuffersARB = NULL;
+PFNGLBLENDEQUATIONIARBPROC glad_glBlendEquationiARB = NULL;
+PFNGLBLENDEQUATIONSEPARATEIARBPROC glad_glBlendEquationSeparateiARB = NULL;
+PFNGLBLENDFUNCIARBPROC glad_glBlendFunciARB = NULL;
+PFNGLBLENDFUNCSEPARATEIARBPROC glad_glBlendFuncSeparateiARB = NULL;
+PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect = NULL;
+PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect = NULL;
+PFNGLDRAWARRAYSINSTANCEDARBPROC glad_glDrawArraysInstancedARB = NULL;
+PFNGLDRAWELEMENTSINSTANCEDARBPROC glad_glDrawElementsInstancedARB = NULL;
+PFNGLPROGRAMSTRINGARBPROC glad_glProgramStringARB = NULL;
+PFNGLBINDPROGRAMARBPROC glad_glBindProgramARB = NULL;
+PFNGLDELETEPROGRAMSARBPROC glad_glDeleteProgramsARB = NULL;
+PFNGLGENPROGRAMSARBPROC glad_glGenProgramsARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DARBPROC glad_glProgramEnvParameter4dARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DVARBPROC glad_glProgramEnvParameter4dvARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FARBPROC glad_glProgramEnvParameter4fARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FVARBPROC glad_glProgramEnvParameter4fvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DARBPROC glad_glProgramLocalParameter4dARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glad_glProgramLocalParameter4dvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FARBPROC glad_glProgramLocalParameter4fARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glad_glProgramLocalParameter4fvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERDVARBPROC glad_glGetProgramEnvParameterdvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERFVARBPROC glad_glGetProgramEnvParameterfvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glad_glGetProgramLocalParameterdvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glad_glGetProgramLocalParameterfvARB = NULL;
+PFNGLGETPROGRAMIVARBPROC glad_glGetProgramivARB = NULL;
+PFNGLGETPROGRAMSTRINGARBPROC glad_glGetProgramStringARB = NULL;
+PFNGLISPROGRAMARBPROC glad_glIsProgramARB = NULL;
+PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv = NULL;
+PFNGLPROGRAMPARAMETERIARBPROC glad_glProgramParameteriARB = NULL;
+PFNGLFRAMEBUFFERTEXTUREARBPROC glad_glFramebufferTextureARB = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERARBPROC glad_glFramebufferTextureLayerARB = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEARBPROC glad_glFramebufferTextureFaceARB = NULL;
+PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary = NULL;
+PFNGLPROGRAMBINARYPROC glad_glProgramBinary = NULL;
+PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri = NULL;
+PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage = NULL;
+PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage = NULL;
+PFNGLSPECIALIZESHADERARBPROC glad_glSpecializeShaderARB = NULL;
+PFNGLUNIFORM1DPROC glad_glUniform1d = NULL;
+PFNGLUNIFORM2DPROC glad_glUniform2d = NULL;
+PFNGLUNIFORM3DPROC glad_glUniform3d = NULL;
+PFNGLUNIFORM4DPROC glad_glUniform4d = NULL;
+PFNGLUNIFORM1DVPROC glad_glUniform1dv = NULL;
+PFNGLUNIFORM2DVPROC glad_glUniform2dv = NULL;
+PFNGLUNIFORM3DVPROC glad_glUniform3dv = NULL;
+PFNGLUNIFORM4DVPROC glad_glUniform4dv = NULL;
+PFNGLUNIFORMMATRIX2DVPROC glad_glUniformMatrix2dv = NULL;
+PFNGLUNIFORMMATRIX3DVPROC glad_glUniformMatrix3dv = NULL;
+PFNGLUNIFORMMATRIX4DVPROC glad_glUniformMatrix4dv = NULL;
+PFNGLUNIFORMMATRIX2X3DVPROC glad_glUniformMatrix2x3dv = NULL;
+PFNGLUNIFORMMATRIX2X4DVPROC glad_glUniformMatrix2x4dv = NULL;
+PFNGLUNIFORMMATRIX3X2DVPROC glad_glUniformMatrix3x2dv = NULL;
+PFNGLUNIFORMMATRIX3X4DVPROC glad_glUniformMatrix3x4dv = NULL;
+PFNGLUNIFORMMATRIX4X2DVPROC glad_glUniformMatrix4x2dv = NULL;
+PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv = NULL;
+PFNGLGETUNIFORMDVPROC glad_glGetUniformdv = NULL;
+PFNGLUNIFORM1I64ARBPROC glad_glUniform1i64ARB = NULL;
+PFNGLUNIFORM2I64ARBPROC glad_glUniform2i64ARB = NULL;
+PFNGLUNIFORM3I64ARBPROC glad_glUniform3i64ARB = NULL;
+PFNGLUNIFORM4I64ARBPROC glad_glUniform4i64ARB = NULL;
+PFNGLUNIFORM1I64VARBPROC glad_glUniform1i64vARB = NULL;
+PFNGLUNIFORM2I64VARBPROC glad_glUniform2i64vARB = NULL;
+PFNGLUNIFORM3I64VARBPROC glad_glUniform3i64vARB = NULL;
+PFNGLUNIFORM4I64VARBPROC glad_glUniform4i64vARB = NULL;
+PFNGLUNIFORM1UI64ARBPROC glad_glUniform1ui64ARB = NULL;
+PFNGLUNIFORM2UI64ARBPROC glad_glUniform2ui64ARB = NULL;
+PFNGLUNIFORM3UI64ARBPROC glad_glUniform3ui64ARB = NULL;
+PFNGLUNIFORM4UI64ARBPROC glad_glUniform4ui64ARB = NULL;
+PFNGLUNIFORM1UI64VARBPROC glad_glUniform1ui64vARB = NULL;
+PFNGLUNIFORM2UI64VARBPROC glad_glUniform2ui64vARB = NULL;
+PFNGLUNIFORM3UI64VARBPROC glad_glUniform3ui64vARB = NULL;
+PFNGLUNIFORM4UI64VARBPROC glad_glUniform4ui64vARB = NULL;
+PFNGLGETUNIFORMI64VARBPROC glad_glGetUniformi64vARB = NULL;
+PFNGLGETUNIFORMUI64VARBPROC glad_glGetUniformui64vARB = NULL;
+PFNGLGETNUNIFORMI64VARBPROC glad_glGetnUniformi64vARB = NULL;
+PFNGLGETNUNIFORMUI64VARBPROC glad_glGetnUniformui64vARB = NULL;
+PFNGLPROGRAMUNIFORM1I64ARBPROC glad_glProgramUniform1i64ARB = NULL;
+PFNGLPROGRAMUNIFORM2I64ARBPROC glad_glProgramUniform2i64ARB = NULL;
+PFNGLPROGRAMUNIFORM3I64ARBPROC glad_glProgramUniform3i64ARB = NULL;
+PFNGLPROGRAMUNIFORM4I64ARBPROC glad_glProgramUniform4i64ARB = NULL;
+PFNGLPROGRAMUNIFORM1I64VARBPROC glad_glProgramUniform1i64vARB = NULL;
+PFNGLPROGRAMUNIFORM2I64VARBPROC glad_glProgramUniform2i64vARB = NULL;
+PFNGLPROGRAMUNIFORM3I64VARBPROC glad_glProgramUniform3i64vARB = NULL;
+PFNGLPROGRAMUNIFORM4I64VARBPROC glad_glProgramUniform4i64vARB = NULL;
+PFNGLPROGRAMUNIFORM1UI64ARBPROC glad_glProgramUniform1ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM2UI64ARBPROC glad_glProgramUniform2ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM3UI64ARBPROC glad_glProgramUniform3ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM4UI64ARBPROC glad_glProgramUniform4ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM1UI64VARBPROC glad_glProgramUniform1ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM2UI64VARBPROC glad_glProgramUniform2ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM3UI64VARBPROC glad_glProgramUniform3ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM4UI64VARBPROC glad_glProgramUniform4ui64vARB = NULL;
+PFNGLCOLORTABLEPROC glad_glColorTable = NULL;
+PFNGLCOLORTABLEPARAMETERFVPROC glad_glColorTableParameterfv = NULL;
+PFNGLCOLORTABLEPARAMETERIVPROC glad_glColorTableParameteriv = NULL;
+PFNGLCOPYCOLORTABLEPROC glad_glCopyColorTable = NULL;
+PFNGLGETCOLORTABLEPROC glad_glGetColorTable = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVPROC glad_glGetColorTableParameterfv = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVPROC glad_glGetColorTableParameteriv = NULL;
+PFNGLCOLORSUBTABLEPROC glad_glColorSubTable = NULL;
+PFNGLCOPYCOLORSUBTABLEPROC glad_glCopyColorSubTable = NULL;
+PFNGLCONVOLUTIONFILTER1DPROC glad_glConvolutionFilter1D = NULL;
+PFNGLCONVOLUTIONFILTER2DPROC glad_glConvolutionFilter2D = NULL;
+PFNGLCONVOLUTIONPARAMETERFPROC glad_glConvolutionParameterf = NULL;
+PFNGLCONVOLUTIONPARAMETERFVPROC glad_glConvolutionParameterfv = NULL;
+PFNGLCONVOLUTIONPARAMETERIPROC glad_glConvolutionParameteri = NULL;
+PFNGLCONVOLUTIONPARAMETERIVPROC glad_glConvolutionParameteriv = NULL;
+PFNGLCOPYCONVOLUTIONFILTER1DPROC glad_glCopyConvolutionFilter1D = NULL;
+PFNGLCOPYCONVOLUTIONFILTER2DPROC glad_glCopyConvolutionFilter2D = NULL;
+PFNGLGETCONVOLUTIONFILTERPROC glad_glGetConvolutionFilter = NULL;
+PFNGLGETCONVOLUTIONPARAMETERFVPROC glad_glGetConvolutionParameterfv = NULL;
+PFNGLGETCONVOLUTIONPARAMETERIVPROC glad_glGetConvolutionParameteriv = NULL;
+PFNGLGETSEPARABLEFILTERPROC glad_glGetSeparableFilter = NULL;
+PFNGLSEPARABLEFILTER2DPROC glad_glSeparableFilter2D = NULL;
+PFNGLGETHISTOGRAMPROC glad_glGetHistogram = NULL;
+PFNGLGETHISTOGRAMPARAMETERFVPROC glad_glGetHistogramParameterfv = NULL;
+PFNGLGETHISTOGRAMPARAMETERIVPROC glad_glGetHistogramParameteriv = NULL;
+PFNGLGETMINMAXPROC glad_glGetMinmax = NULL;
+PFNGLGETMINMAXPARAMETERFVPROC glad_glGetMinmaxParameterfv = NULL;
+PFNGLGETMINMAXPARAMETERIVPROC glad_glGetMinmaxParameteriv = NULL;
+PFNGLHISTOGRAMPROC glad_glHistogram = NULL;
+PFNGLMINMAXPROC glad_glMinmax = NULL;
+PFNGLRESETHISTOGRAMPROC glad_glResetHistogram = NULL;
+PFNGLRESETMINMAXPROC glad_glResetMinmax = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC glad_glMultiDrawArraysIndirectCountARB = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC glad_glMultiDrawElementsIndirectCountARB = NULL;
+PFNGLVERTEXATTRIBDIVISORARBPROC glad_glVertexAttribDivisorARB = NULL;
+PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL;
+PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v = NULL;
+PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage = NULL;
+PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage = NULL;
+PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData = NULL;
+PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData = NULL;
+PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL;
+PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL;
+PFNGLCURRENTPALETTEMATRIXARBPROC glad_glCurrentPaletteMatrixARB = NULL;
+PFNGLMATRIXINDEXUBVARBPROC glad_glMatrixIndexubvARB = NULL;
+PFNGLMATRIXINDEXUSVARBPROC glad_glMatrixIndexusvARB = NULL;
+PFNGLMATRIXINDEXUIVARBPROC glad_glMatrixIndexuivARB = NULL;
+PFNGLMATRIXINDEXPOINTERARBPROC glad_glMatrixIndexPointerARB = NULL;
+PFNGLBINDBUFFERSBASEPROC glad_glBindBuffersBase = NULL;
+PFNGLBINDBUFFERSRANGEPROC glad_glBindBuffersRange = NULL;
+PFNGLBINDTEXTURESPROC glad_glBindTextures = NULL;
+PFNGLBINDSAMPLERSPROC glad_glBindSamplers = NULL;
+PFNGLBINDIMAGETEXTURESPROC glad_glBindImageTextures = NULL;
+PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect = NULL;
+PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB = NULL;
+PFNGLACTIVETEXTUREARBPROC glad_glActiveTextureARB = NULL;
+PFNGLCLIENTACTIVETEXTUREARBPROC glad_glClientActiveTextureARB = NULL;
+PFNGLMULTITEXCOORD1DARBPROC glad_glMultiTexCoord1dARB = NULL;
+PFNGLMULTITEXCOORD1DVARBPROC glad_glMultiTexCoord1dvARB = NULL;
+PFNGLMULTITEXCOORD1FARBPROC glad_glMultiTexCoord1fARB = NULL;
+PFNGLMULTITEXCOORD1FVARBPROC glad_glMultiTexCoord1fvARB = NULL;
+PFNGLMULTITEXCOORD1IARBPROC glad_glMultiTexCoord1iARB = NULL;
+PFNGLMULTITEXCOORD1IVARBPROC glad_glMultiTexCoord1ivARB = NULL;
+PFNGLMULTITEXCOORD1SARBPROC glad_glMultiTexCoord1sARB = NULL;
+PFNGLMULTITEXCOORD1SVARBPROC glad_glMultiTexCoord1svARB = NULL;
+PFNGLMULTITEXCOORD2DARBPROC glad_glMultiTexCoord2dARB = NULL;
+PFNGLMULTITEXCOORD2DVARBPROC glad_glMultiTexCoord2dvARB = NULL;
+PFNGLMULTITEXCOORD2FARBPROC glad_glMultiTexCoord2fARB = NULL;
+PFNGLMULTITEXCOORD2FVARBPROC glad_glMultiTexCoord2fvARB = NULL;
+PFNGLMULTITEXCOORD2IARBPROC glad_glMultiTexCoord2iARB = NULL;
+PFNGLMULTITEXCOORD2IVARBPROC glad_glMultiTexCoord2ivARB = NULL;
+PFNGLMULTITEXCOORD2SARBPROC glad_glMultiTexCoord2sARB = NULL;
+PFNGLMULTITEXCOORD2SVARBPROC glad_glMultiTexCoord2svARB = NULL;
+PFNGLMULTITEXCOORD3DARBPROC glad_glMultiTexCoord3dARB = NULL;
+PFNGLMULTITEXCOORD3DVARBPROC glad_glMultiTexCoord3dvARB = NULL;
+PFNGLMULTITEXCOORD3FARBPROC glad_glMultiTexCoord3fARB = NULL;
+PFNGLMULTITEXCOORD3FVARBPROC glad_glMultiTexCoord3fvARB = NULL;
+PFNGLMULTITEXCOORD3IARBPROC glad_glMultiTexCoord3iARB = NULL;
+PFNGLMULTITEXCOORD3IVARBPROC glad_glMultiTexCoord3ivARB = NULL;
+PFNGLMULTITEXCOORD3SARBPROC glad_glMultiTexCoord3sARB = NULL;
+PFNGLMULTITEXCOORD3SVARBPROC glad_glMultiTexCoord3svARB = NULL;
+PFNGLMULTITEXCOORD4DARBPROC glad_glMultiTexCoord4dARB = NULL;
+PFNGLMULTITEXCOORD4DVARBPROC glad_glMultiTexCoord4dvARB = NULL;
+PFNGLMULTITEXCOORD4FARBPROC glad_glMultiTexCoord4fARB = NULL;
+PFNGLMULTITEXCOORD4FVARBPROC glad_glMultiTexCoord4fvARB = NULL;
+PFNGLMULTITEXCOORD4IARBPROC glad_glMultiTexCoord4iARB = NULL;
+PFNGLMULTITEXCOORD4IVARBPROC glad_glMultiTexCoord4ivARB = NULL;
+PFNGLMULTITEXCOORD4SARBPROC glad_glMultiTexCoord4sARB = NULL;
+PFNGLMULTITEXCOORD4SVARBPROC glad_glMultiTexCoord4svARB = NULL;
+PFNGLGENQUERIESARBPROC glad_glGenQueriesARB = NULL;
+PFNGLDELETEQUERIESARBPROC glad_glDeleteQueriesARB = NULL;
+PFNGLISQUERYARBPROC glad_glIsQueryARB = NULL;
+PFNGLBEGINQUERYARBPROC glad_glBeginQueryARB = NULL;
+PFNGLENDQUERYARBPROC glad_glEndQueryARB = NULL;
+PFNGLGETQUERYIVARBPROC glad_glGetQueryivARB = NULL;
+PFNGLGETQUERYOBJECTIVARBPROC glad_glGetQueryObjectivARB = NULL;
+PFNGLGETQUERYOBJECTUIVARBPROC glad_glGetQueryObjectuivARB = NULL;
+PFNGLMAXSHADERCOMPILERTHREADSARBPROC glad_glMaxShaderCompilerThreadsARB = NULL;
+PFNGLPOINTPARAMETERFARBPROC glad_glPointParameterfARB = NULL;
+PFNGLPOINTPARAMETERFVARBPROC glad_glPointParameterfvARB = NULL;
+PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp = NULL;
+PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv = NULL;
+PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex = NULL;
+PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName = NULL;
+PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glad_glGetProgramResourceLocationIndex = NULL;
+PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB = NULL;
+PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB = NULL;
+PFNGLREADNPIXELSARBPROC glad_glReadnPixelsARB = NULL;
+PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC glad_glGetnCompressedTexImageARB = NULL;
+PFNGLGETNUNIFORMFVARBPROC glad_glGetnUniformfvARB = NULL;
+PFNGLGETNUNIFORMIVARBPROC glad_glGetnUniformivARB = NULL;
+PFNGLGETNUNIFORMUIVARBPROC glad_glGetnUniformuivARB = NULL;
+PFNGLGETNUNIFORMDVARBPROC glad_glGetnUniformdvARB = NULL;
+PFNGLGETNMAPDVARBPROC glad_glGetnMapdvARB = NULL;
+PFNGLGETNMAPFVARBPROC glad_glGetnMapfvARB = NULL;
+PFNGLGETNMAPIVARBPROC glad_glGetnMapivARB = NULL;
+PFNGLGETNPIXELMAPFVARBPROC glad_glGetnPixelMapfvARB = NULL;
+PFNGLGETNPIXELMAPUIVARBPROC glad_glGetnPixelMapuivARB = NULL;
+PFNGLGETNPIXELMAPUSVARBPROC glad_glGetnPixelMapusvARB = NULL;
+PFNGLGETNPOLYGONSTIPPLEARBPROC glad_glGetnPolygonStippleARB = NULL;
+PFNGLGETNCOLORTABLEARBPROC glad_glGetnColorTableARB = NULL;
+PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB = NULL;
+PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB = NULL;
+PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB = NULL;
+PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB = NULL;
+PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glFramebufferSampleLocationsfvARB = NULL;
+PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glNamedFramebufferSampleLocationsfvARB = NULL;
+PFNGLEVALUATEDEPTHVALUESARBPROC glad_glEvaluateDepthValuesARB = NULL;
+PFNGLMINSAMPLESHADINGARBPROC glad_glMinSampleShadingARB = NULL;
+PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages = NULL;
+PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram = NULL;
+PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv = NULL;
+PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline = NULL;
+PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines = NULL;
+PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines = NULL;
+PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline = NULL;
+PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv = NULL;
+PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i = NULL;
+PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv = NULL;
+PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f = NULL;
+PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv = NULL;
+PFNGLPROGRAMUNIFORM1DPROC glad_glProgramUniform1d = NULL;
+PFNGLPROGRAMUNIFORM1DVPROC glad_glProgramUniform1dv = NULL;
+PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui = NULL;
+PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv = NULL;
+PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i = NULL;
+PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv = NULL;
+PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f = NULL;
+PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv = NULL;
+PFNGLPROGRAMUNIFORM2DPROC glad_glProgramUniform2d = NULL;
+PFNGLPROGRAMUNIFORM2DVPROC glad_glProgramUniform2dv = NULL;
+PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui = NULL;
+PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv = NULL;
+PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i = NULL;
+PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv = NULL;
+PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f = NULL;
+PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv = NULL;
+PFNGLPROGRAMUNIFORM3DPROC glad_glProgramUniform3d = NULL;
+PFNGLPROGRAMUNIFORM3DVPROC glad_glProgramUniform3dv = NULL;
+PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui = NULL;
+PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv = NULL;
+PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i = NULL;
+PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv = NULL;
+PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f = NULL;
+PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv = NULL;
+PFNGLPROGRAMUNIFORM4DPROC glad_glProgramUniform4d = NULL;
+PFNGLPROGRAMUNIFORM4DVPROC glad_glProgramUniform4dv = NULL;
+PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui = NULL;
+PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2DVPROC glad_glProgramUniformMatrix2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3DVPROC glad_glProgramUniformMatrix3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4DVPROC glad_glProgramUniformMatrix4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glad_glProgramUniformMatrix2x3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glad_glProgramUniformMatrix3x2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glad_glProgramUniformMatrix2x4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glad_glProgramUniformMatrix4x2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glad_glProgramUniformMatrix3x4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glad_glProgramUniformMatrix4x3dv = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog = NULL;
+PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv = NULL;
+PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture = NULL;
+PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier = NULL;
+PFNGLDELETEOBJECTARBPROC glad_glDeleteObjectARB = NULL;
+PFNGLGETHANDLEARBPROC glad_glGetHandleARB = NULL;
+PFNGLDETACHOBJECTARBPROC glad_glDetachObjectARB = NULL;
+PFNGLCREATESHADEROBJECTARBPROC glad_glCreateShaderObjectARB = NULL;
+PFNGLSHADERSOURCEARBPROC glad_glShaderSourceARB = NULL;
+PFNGLCOMPILESHADERARBPROC glad_glCompileShaderARB = NULL;
+PFNGLCREATEPROGRAMOBJECTARBPROC glad_glCreateProgramObjectARB = NULL;
+PFNGLATTACHOBJECTARBPROC glad_glAttachObjectARB = NULL;
+PFNGLLINKPROGRAMARBPROC glad_glLinkProgramARB = NULL;
+PFNGLUSEPROGRAMOBJECTARBPROC glad_glUseProgramObjectARB = NULL;
+PFNGLVALIDATEPROGRAMARBPROC glad_glValidateProgramARB = NULL;
+PFNGLUNIFORM1FARBPROC glad_glUniform1fARB = NULL;
+PFNGLUNIFORM2FARBPROC glad_glUniform2fARB = NULL;
+PFNGLUNIFORM3FARBPROC glad_glUniform3fARB = NULL;
+PFNGLUNIFORM4FARBPROC glad_glUniform4fARB = NULL;
+PFNGLUNIFORM1IARBPROC glad_glUniform1iARB = NULL;
+PFNGLUNIFORM2IARBPROC glad_glUniform2iARB = NULL;
+PFNGLUNIFORM3IARBPROC glad_glUniform3iARB = NULL;
+PFNGLUNIFORM4IARBPROC glad_glUniform4iARB = NULL;
+PFNGLUNIFORM1FVARBPROC glad_glUniform1fvARB = NULL;
+PFNGLUNIFORM2FVARBPROC glad_glUniform2fvARB = NULL;
+PFNGLUNIFORM3FVARBPROC glad_glUniform3fvARB = NULL;
+PFNGLUNIFORM4FVARBPROC glad_glUniform4fvARB = NULL;
+PFNGLUNIFORM1IVARBPROC glad_glUniform1ivARB = NULL;
+PFNGLUNIFORM2IVARBPROC glad_glUniform2ivARB = NULL;
+PFNGLUNIFORM3IVARBPROC glad_glUniform3ivARB = NULL;
+PFNGLUNIFORM4IVARBPROC glad_glUniform4ivARB = NULL;
+PFNGLUNIFORMMATRIX2FVARBPROC glad_glUniformMatrix2fvARB = NULL;
+PFNGLUNIFORMMATRIX3FVARBPROC glad_glUniformMatrix3fvARB = NULL;
+PFNGLUNIFORMMATRIX4FVARBPROC glad_glUniformMatrix4fvARB = NULL;
+PFNGLGETOBJECTPARAMETERFVARBPROC glad_glGetObjectParameterfvARB = NULL;
+PFNGLGETOBJECTPARAMETERIVARBPROC glad_glGetObjectParameterivARB = NULL;
+PFNGLGETINFOLOGARBPROC glad_glGetInfoLogARB = NULL;
+PFNGLGETATTACHEDOBJECTSARBPROC glad_glGetAttachedObjectsARB = NULL;
+PFNGLGETUNIFORMLOCATIONARBPROC glad_glGetUniformLocationARB = NULL;
+PFNGLGETACTIVEUNIFORMARBPROC glad_glGetActiveUniformARB = NULL;
+PFNGLGETUNIFORMFVARBPROC glad_glGetUniformfvARB = NULL;
+PFNGLGETUNIFORMIVARBPROC glad_glGetUniformivARB = NULL;
+PFNGLGETSHADERSOURCEARBPROC glad_glGetShaderSourceARB = NULL;
+PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding = NULL;
+PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glad_glGetSubroutineUniformLocation = NULL;
+PFNGLGETSUBROUTINEINDEXPROC glad_glGetSubroutineIndex = NULL;
+PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glad_glGetActiveSubroutineUniformiv = NULL;
+PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glad_glGetActiveSubroutineUniformName = NULL;
+PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName = NULL;
+PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv = NULL;
+PFNGLGETUNIFORMSUBROUTINEUIVPROC glad_glGetUniformSubroutineuiv = NULL;
+PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv = NULL;
+PFNGLNAMEDSTRINGARBPROC glad_glNamedStringARB = NULL;
+PFNGLDELETENAMEDSTRINGARBPROC glad_glDeleteNamedStringARB = NULL;
+PFNGLCOMPILESHADERINCLUDEARBPROC glad_glCompileShaderIncludeARB = NULL;
+PFNGLISNAMEDSTRINGARBPROC glad_glIsNamedStringARB = NULL;
+PFNGLGETNAMEDSTRINGARBPROC glad_glGetNamedStringARB = NULL;
+PFNGLGETNAMEDSTRINGIVARBPROC glad_glGetNamedStringivARB = NULL;
+PFNGLBUFFERPAGECOMMITMENTARBPROC glad_glBufferPageCommitmentARB = NULL;
+PFNGLNAMEDBUFFERPAGECOMMITMENTEXTPROC glad_glNamedBufferPageCommitmentEXT = NULL;
+PFNGLNAMEDBUFFERPAGECOMMITMENTARBPROC glad_glNamedBufferPageCommitmentARB = NULL;
+PFNGLTEXPAGECOMMITMENTARBPROC glad_glTexPageCommitmentARB = NULL;
+PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri = NULL;
+PFNGLPATCHPARAMETERFVPROC glad_glPatchParameterfv = NULL;
+PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier = NULL;
+PFNGLTEXBUFFERARBPROC glad_glTexBufferARB = NULL;
+PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glad_glCompressedTexImage3DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glad_glCompressedTexImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glad_glCompressedTexImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glad_glCompressedTexSubImage3DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glad_glCompressedTexSubImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glad_glCompressedTexSubImage1DARB = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glad_glGetCompressedTexImageARB = NULL;
+PFNGLTEXSTORAGE1DPROC glad_glTexStorage1D = NULL;
+PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D = NULL;
+PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D = NULL;
+PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample = NULL;
+PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample = NULL;
+PFNGLTEXTUREVIEWPROC glad_glTextureView = NULL;
+PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL;
+PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks = NULL;
+PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL;
+PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback = NULL;
+PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback = NULL;
+PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream = NULL;
+PFNGLBEGINQUERYINDEXEDPROC glad_glBeginQueryIndexed = NULL;
+PFNGLENDQUERYINDEXEDPROC glad_glEndQueryIndexed = NULL;
+PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced = NULL;
+PFNGLLOADTRANSPOSEMATRIXFARBPROC glad_glLoadTransposeMatrixfARB = NULL;
+PFNGLLOADTRANSPOSEMATRIXDARBPROC glad_glLoadTransposeMatrixdARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXFARBPROC glad_glMultTransposeMatrixfARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXDARBPROC glad_glMultTransposeMatrixdARB = NULL;
+PFNGLVERTEXATTRIBL1DPROC glad_glVertexAttribL1d = NULL;
+PFNGLVERTEXATTRIBL2DPROC glad_glVertexAttribL2d = NULL;
+PFNGLVERTEXATTRIBL3DPROC glad_glVertexAttribL3d = NULL;
+PFNGLVERTEXATTRIBL4DPROC glad_glVertexAttribL4d = NULL;
+PFNGLVERTEXATTRIBL1DVPROC glad_glVertexAttribL1dv = NULL;
+PFNGLVERTEXATTRIBL2DVPROC glad_glVertexAttribL2dv = NULL;
+PFNGLVERTEXATTRIBL3DVPROC glad_glVertexAttribL3dv = NULL;
+PFNGLVERTEXATTRIBL4DVPROC glad_glVertexAttribL4dv = NULL;
+PFNGLVERTEXATTRIBLPOINTERPROC glad_glVertexAttribLPointer = NULL;
+PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv = NULL;
+PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer = NULL;
+PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat = NULL;
+PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat = NULL;
+PFNGLVERTEXATTRIBLFORMATPROC glad_glVertexAttribLFormat = NULL;
+PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding = NULL;
+PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor = NULL;
+PFNGLWEIGHTBVARBPROC glad_glWeightbvARB = NULL;
+PFNGLWEIGHTSVARBPROC glad_glWeightsvARB = NULL;
+PFNGLWEIGHTIVARBPROC glad_glWeightivARB = NULL;
+PFNGLWEIGHTFVARBPROC glad_glWeightfvARB = NULL;
+PFNGLWEIGHTDVARBPROC glad_glWeightdvARB = NULL;
+PFNGLWEIGHTUBVARBPROC glad_glWeightubvARB = NULL;
+PFNGLWEIGHTUSVARBPROC glad_glWeightusvARB = NULL;
+PFNGLWEIGHTUIVARBPROC glad_glWeightuivARB = NULL;
+PFNGLWEIGHTPOINTERARBPROC glad_glWeightPointerARB = NULL;
+PFNGLVERTEXBLENDARBPROC glad_glVertexBlendARB = NULL;
+PFNGLBINDBUFFERARBPROC glad_glBindBufferARB = NULL;
+PFNGLDELETEBUFFERSARBPROC glad_glDeleteBuffersARB = NULL;
+PFNGLGENBUFFERSARBPROC glad_glGenBuffersARB = NULL;
+PFNGLISBUFFERARBPROC glad_glIsBufferARB = NULL;
+PFNGLBUFFERDATAARBPROC glad_glBufferDataARB = NULL;
+PFNGLBUFFERSUBDATAARBPROC glad_glBufferSubDataARB = NULL;
+PFNGLGETBUFFERSUBDATAARBPROC glad_glGetBufferSubDataARB = NULL;
+PFNGLMAPBUFFERARBPROC glad_glMapBufferARB = NULL;
+PFNGLUNMAPBUFFERARBPROC glad_glUnmapBufferARB = NULL;
+PFNGLGETBUFFERPARAMETERIVARBPROC glad_glGetBufferParameterivARB = NULL;
+PFNGLGETBUFFERPOINTERVARBPROC glad_glGetBufferPointervARB = NULL;
+PFNGLVERTEXATTRIB1DARBPROC glad_glVertexAttrib1dARB = NULL;
+PFNGLVERTEXATTRIB1DVARBPROC glad_glVertexAttrib1dvARB = NULL;
+PFNGLVERTEXATTRIB1FARBPROC glad_glVertexAttrib1fARB = NULL;
+PFNGLVERTEXATTRIB1FVARBPROC glad_glVertexAttrib1fvARB = NULL;
+PFNGLVERTEXATTRIB1SARBPROC glad_glVertexAttrib1sARB = NULL;
+PFNGLVERTEXATTRIB1SVARBPROC glad_glVertexAttrib1svARB = NULL;
+PFNGLVERTEXATTRIB2DARBPROC glad_glVertexAttrib2dARB = NULL;
+PFNGLVERTEXATTRIB2DVARBPROC glad_glVertexAttrib2dvARB = NULL;
+PFNGLVERTEXATTRIB2FARBPROC glad_glVertexAttrib2fARB = NULL;
+PFNGLVERTEXATTRIB2FVARBPROC glad_glVertexAttrib2fvARB = NULL;
+PFNGLVERTEXATTRIB2SARBPROC glad_glVertexAttrib2sARB = NULL;
+PFNGLVERTEXATTRIB2SVARBPROC glad_glVertexAttrib2svARB = NULL;
+PFNGLVERTEXATTRIB3DARBPROC glad_glVertexAttrib3dARB = NULL;
+PFNGLVERTEXATTRIB3DVARBPROC glad_glVertexAttrib3dvARB = NULL;
+PFNGLVERTEXATTRIB3FARBPROC glad_glVertexAttrib3fARB = NULL;
+PFNGLVERTEXATTRIB3FVARBPROC glad_glVertexAttrib3fvARB = NULL;
+PFNGLVERTEXATTRIB3SARBPROC glad_glVertexAttrib3sARB = NULL;
+PFNGLVERTEXATTRIB3SVARBPROC glad_glVertexAttrib3svARB = NULL;
+PFNGLVERTEXATTRIB4NBVARBPROC glad_glVertexAttrib4NbvARB = NULL;
+PFNGLVERTEXATTRIB4NIVARBPROC glad_glVertexAttrib4NivARB = NULL;
+PFNGLVERTEXATTRIB4NSVARBPROC glad_glVertexAttrib4NsvARB = NULL;
+PFNGLVERTEXATTRIB4NUBARBPROC glad_glVertexAttrib4NubARB = NULL;
+PFNGLVERTEXATTRIB4NUBVARBPROC glad_glVertexAttrib4NubvARB = NULL;
+PFNGLVERTEXATTRIB4NUIVARBPROC glad_glVertexAttrib4NuivARB = NULL;
+PFNGLVERTEXATTRIB4NUSVARBPROC glad_glVertexAttrib4NusvARB = NULL;
+PFNGLVERTEXATTRIB4BVARBPROC glad_glVertexAttrib4bvARB = NULL;
+PFNGLVERTEXATTRIB4DARBPROC glad_glVertexAttrib4dARB = NULL;
+PFNGLVERTEXATTRIB4DVARBPROC glad_glVertexAttrib4dvARB = NULL;
+PFNGLVERTEXATTRIB4FARBPROC glad_glVertexAttrib4fARB = NULL;
+PFNGLVERTEXATTRIB4FVARBPROC glad_glVertexAttrib4fvARB = NULL;
+PFNGLVERTEXATTRIB4IVARBPROC glad_glVertexAttrib4ivARB = NULL;
+PFNGLVERTEXATTRIB4SARBPROC glad_glVertexAttrib4sARB = NULL;
+PFNGLVERTEXATTRIB4SVARBPROC glad_glVertexAttrib4svARB = NULL;
+PFNGLVERTEXATTRIB4UBVARBPROC glad_glVertexAttrib4ubvARB = NULL;
+PFNGLVERTEXATTRIB4UIVARBPROC glad_glVertexAttrib4uivARB = NULL;
+PFNGLVERTEXATTRIB4USVARBPROC glad_glVertexAttrib4usvARB = NULL;
+PFNGLVERTEXATTRIBPOINTERARBPROC glad_glVertexAttribPointerARB = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYARBPROC glad_glEnableVertexAttribArrayARB = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glad_glDisableVertexAttribArrayARB = NULL;
+PFNGLGETVERTEXATTRIBDVARBPROC glad_glGetVertexAttribdvARB = NULL;
+PFNGLGETVERTEXATTRIBFVARBPROC glad_glGetVertexAttribfvARB = NULL;
+PFNGLGETVERTEXATTRIBIVARBPROC glad_glGetVertexAttribivARB = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVARBPROC glad_glGetVertexAttribPointervARB = NULL;
+PFNGLBINDATTRIBLOCATIONARBPROC glad_glBindAttribLocationARB = NULL;
+PFNGLGETACTIVEATTRIBARBPROC glad_glGetActiveAttribARB = NULL;
+PFNGLGETATTRIBLOCATIONARBPROC glad_glGetAttribLocationARB = NULL;
+PFNGLVIEWPORTARRAYVPROC glad_glViewportArrayv = NULL;
+PFNGLVIEWPORTINDEXEDFPROC glad_glViewportIndexedf = NULL;
+PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv = NULL;
+PFNGLSCISSORARRAYVPROC glad_glScissorArrayv = NULL;
+PFNGLSCISSORINDEXEDPROC glad_glScissorIndexed = NULL;
+PFNGLSCISSORINDEXEDVPROC glad_glScissorIndexedv = NULL;
+PFNGLDEPTHRANGEARRAYVPROC glad_glDepthRangeArrayv = NULL;
+PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed = NULL;
+PFNGLGETFLOATI_VPROC glad_glGetFloati_v = NULL;
+PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v = NULL;
+PFNGLWINDOWPOS2DARBPROC glad_glWindowPos2dARB = NULL;
+PFNGLWINDOWPOS2DVARBPROC glad_glWindowPos2dvARB = NULL;
+PFNGLWINDOWPOS2FARBPROC glad_glWindowPos2fARB = NULL;
+PFNGLWINDOWPOS2FVARBPROC glad_glWindowPos2fvARB = NULL;
+PFNGLWINDOWPOS2IARBPROC glad_glWindowPos2iARB = NULL;
+PFNGLWINDOWPOS2IVARBPROC glad_glWindowPos2ivARB = NULL;
+PFNGLWINDOWPOS2SARBPROC glad_glWindowPos2sARB = NULL;
+PFNGLWINDOWPOS2SVARBPROC glad_glWindowPos2svARB = NULL;
+PFNGLWINDOWPOS3DARBPROC glad_glWindowPos3dARB = NULL;
+PFNGLWINDOWPOS3DVARBPROC glad_glWindowPos3dvARB = NULL;
+PFNGLWINDOWPOS3FARBPROC glad_glWindowPos3fARB = NULL;
+PFNGLWINDOWPOS3FVARBPROC glad_glWindowPos3fvARB = NULL;
+PFNGLWINDOWPOS3IARBPROC glad_glWindowPos3iARB = NULL;
+PFNGLWINDOWPOS3IVARBPROC glad_glWindowPos3ivARB = NULL;
+PFNGLWINDOWPOS3SARBPROC glad_glWindowPos3sARB = NULL;
+PFNGLWINDOWPOS3SVARBPROC glad_glWindowPos3svARB = NULL;
+PFNGLDRAWBUFFERSATIPROC glad_glDrawBuffersATI = NULL;
+PFNGLELEMENTPOINTERATIPROC glad_glElementPointerATI = NULL;
+PFNGLDRAWELEMENTARRAYATIPROC glad_glDrawElementArrayATI = NULL;
+PFNGLDRAWRANGEELEMENTARRAYATIPROC glad_glDrawRangeElementArrayATI = NULL;
+PFNGLTEXBUMPPARAMETERIVATIPROC glad_glTexBumpParameterivATI = NULL;
+PFNGLTEXBUMPPARAMETERFVATIPROC glad_glTexBumpParameterfvATI = NULL;
+PFNGLGETTEXBUMPPARAMETERIVATIPROC glad_glGetTexBumpParameterivATI = NULL;
+PFNGLGETTEXBUMPPARAMETERFVATIPROC glad_glGetTexBumpParameterfvATI = NULL;
+PFNGLGENFRAGMENTSHADERSATIPROC glad_glGenFragmentShadersATI = NULL;
+PFNGLBINDFRAGMENTSHADERATIPROC glad_glBindFragmentShaderATI = NULL;
+PFNGLDELETEFRAGMENTSHADERATIPROC glad_glDeleteFragmentShaderATI = NULL;
+PFNGLBEGINFRAGMENTSHADERATIPROC glad_glBeginFragmentShaderATI = NULL;
+PFNGLENDFRAGMENTSHADERATIPROC glad_glEndFragmentShaderATI = NULL;
+PFNGLPASSTEXCOORDATIPROC glad_glPassTexCoordATI = NULL;
+PFNGLSAMPLEMAPATIPROC glad_glSampleMapATI = NULL;
+PFNGLCOLORFRAGMENTOP1ATIPROC glad_glColorFragmentOp1ATI = NULL;
+PFNGLCOLORFRAGMENTOP2ATIPROC glad_glColorFragmentOp2ATI = NULL;
+PFNGLCOLORFRAGMENTOP3ATIPROC glad_glColorFragmentOp3ATI = NULL;
+PFNGLALPHAFRAGMENTOP1ATIPROC glad_glAlphaFragmentOp1ATI = NULL;
+PFNGLALPHAFRAGMENTOP2ATIPROC glad_glAlphaFragmentOp2ATI = NULL;
+PFNGLALPHAFRAGMENTOP3ATIPROC glad_glAlphaFragmentOp3ATI = NULL;
+PFNGLSETFRAGMENTSHADERCONSTANTATIPROC glad_glSetFragmentShaderConstantATI = NULL;
+PFNGLMAPOBJECTBUFFERATIPROC glad_glMapObjectBufferATI = NULL;
+PFNGLUNMAPOBJECTBUFFERATIPROC glad_glUnmapObjectBufferATI = NULL;
+PFNGLPNTRIANGLESIATIPROC glad_glPNTrianglesiATI = NULL;
+PFNGLPNTRIANGLESFATIPROC glad_glPNTrianglesfATI = NULL;
+PFNGLSTENCILOPSEPARATEATIPROC glad_glStencilOpSeparateATI = NULL;
+PFNGLSTENCILFUNCSEPARATEATIPROC glad_glStencilFuncSeparateATI = NULL;
+PFNGLNEWOBJECTBUFFERATIPROC glad_glNewObjectBufferATI = NULL;
+PFNGLISOBJECTBUFFERATIPROC glad_glIsObjectBufferATI = NULL;
+PFNGLUPDATEOBJECTBUFFERATIPROC glad_glUpdateObjectBufferATI = NULL;
+PFNGLGETOBJECTBUFFERFVATIPROC glad_glGetObjectBufferfvATI = NULL;
+PFNGLGETOBJECTBUFFERIVATIPROC glad_glGetObjectBufferivATI = NULL;
+PFNGLFREEOBJECTBUFFERATIPROC glad_glFreeObjectBufferATI = NULL;
+PFNGLARRAYOBJECTATIPROC glad_glArrayObjectATI = NULL;
+PFNGLGETARRAYOBJECTFVATIPROC glad_glGetArrayObjectfvATI = NULL;
+PFNGLGETARRAYOBJECTIVATIPROC glad_glGetArrayObjectivATI = NULL;
+PFNGLVARIANTARRAYOBJECTATIPROC glad_glVariantArrayObjectATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTFVATIPROC glad_glGetVariantArrayObjectfvATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTIVATIPROC glad_glGetVariantArrayObjectivATI = NULL;
+PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glad_glVertexAttribArrayObjectATI = NULL;
+PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC glad_glGetVertexAttribArrayObjectfvATI = NULL;
+PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC glad_glGetVertexAttribArrayObjectivATI = NULL;
+PFNGLVERTEXSTREAM1SATIPROC glad_glVertexStream1sATI = NULL;
+PFNGLVERTEXSTREAM1SVATIPROC glad_glVertexStream1svATI = NULL;
+PFNGLVERTEXSTREAM1IATIPROC glad_glVertexStream1iATI = NULL;
+PFNGLVERTEXSTREAM1IVATIPROC glad_glVertexStream1ivATI = NULL;
+PFNGLVERTEXSTREAM1FATIPROC glad_glVertexStream1fATI = NULL;
+PFNGLVERTEXSTREAM1FVATIPROC glad_glVertexStream1fvATI = NULL;
+PFNGLVERTEXSTREAM1DATIPROC glad_glVertexStream1dATI = NULL;
+PFNGLVERTEXSTREAM1DVATIPROC glad_glVertexStream1dvATI = NULL;
+PFNGLVERTEXSTREAM2SATIPROC glad_glVertexStream2sATI = NULL;
+PFNGLVERTEXSTREAM2SVATIPROC glad_glVertexStream2svATI = NULL;
+PFNGLVERTEXSTREAM2IATIPROC glad_glVertexStream2iATI = NULL;
+PFNGLVERTEXSTREAM2IVATIPROC glad_glVertexStream2ivATI = NULL;
+PFNGLVERTEXSTREAM2FATIPROC glad_glVertexStream2fATI = NULL;
+PFNGLVERTEXSTREAM2FVATIPROC glad_glVertexStream2fvATI = NULL;
+PFNGLVERTEXSTREAM2DATIPROC glad_glVertexStream2dATI = NULL;
+PFNGLVERTEXSTREAM2DVATIPROC glad_glVertexStream2dvATI = NULL;
+PFNGLVERTEXSTREAM3SATIPROC glad_glVertexStream3sATI = NULL;
+PFNGLVERTEXSTREAM3SVATIPROC glad_glVertexStream3svATI = NULL;
+PFNGLVERTEXSTREAM3IATIPROC glad_glVertexStream3iATI = NULL;
+PFNGLVERTEXSTREAM3IVATIPROC glad_glVertexStream3ivATI = NULL;
+PFNGLVERTEXSTREAM3FATIPROC glad_glVertexStream3fATI = NULL;
+PFNGLVERTEXSTREAM3FVATIPROC glad_glVertexStream3fvATI = NULL;
+PFNGLVERTEXSTREAM3DATIPROC glad_glVertexStream3dATI = NULL;
+PFNGLVERTEXSTREAM3DVATIPROC glad_glVertexStream3dvATI = NULL;
+PFNGLVERTEXSTREAM4SATIPROC glad_glVertexStream4sATI = NULL;
+PFNGLVERTEXSTREAM4SVATIPROC glad_glVertexStream4svATI = NULL;
+PFNGLVERTEXSTREAM4IATIPROC glad_glVertexStream4iATI = NULL;
+PFNGLVERTEXSTREAM4IVATIPROC glad_glVertexStream4ivATI = NULL;
+PFNGLVERTEXSTREAM4FATIPROC glad_glVertexStream4fATI = NULL;
+PFNGLVERTEXSTREAM4FVATIPROC glad_glVertexStream4fvATI = NULL;
+PFNGLVERTEXSTREAM4DATIPROC glad_glVertexStream4dATI = NULL;
+PFNGLVERTEXSTREAM4DVATIPROC glad_glVertexStream4dvATI = NULL;
+PFNGLNORMALSTREAM3BATIPROC glad_glNormalStream3bATI = NULL;
+PFNGLNORMALSTREAM3BVATIPROC glad_glNormalStream3bvATI = NULL;
+PFNGLNORMALSTREAM3SATIPROC glad_glNormalStream3sATI = NULL;
+PFNGLNORMALSTREAM3SVATIPROC glad_glNormalStream3svATI = NULL;
+PFNGLNORMALSTREAM3IATIPROC glad_glNormalStream3iATI = NULL;
+PFNGLNORMALSTREAM3IVATIPROC glad_glNormalStream3ivATI = NULL;
+PFNGLNORMALSTREAM3FATIPROC glad_glNormalStream3fATI = NULL;
+PFNGLNORMALSTREAM3FVATIPROC glad_glNormalStream3fvATI = NULL;
+PFNGLNORMALSTREAM3DATIPROC glad_glNormalStream3dATI = NULL;
+PFNGLNORMALSTREAM3DVATIPROC glad_glNormalStream3dvATI = NULL;
+PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC glad_glClientActiveVertexStreamATI = NULL;
+PFNGLVERTEXBLENDENVIATIPROC glad_glVertexBlendEnviATI = NULL;
+PFNGLVERTEXBLENDENVFATIPROC glad_glVertexBlendEnvfATI = NULL;
+PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glad_glEGLImageTargetTexStorageEXT = NULL;
+PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC glad_glEGLImageTargetTextureStorageEXT = NULL;
+PFNGLUNIFORMBUFFEREXTPROC glad_glUniformBufferEXT = NULL;
+PFNGLGETUNIFORMBUFFERSIZEEXTPROC glad_glGetUniformBufferSizeEXT = NULL;
+PFNGLGETUNIFORMOFFSETEXTPROC glad_glGetUniformOffsetEXT = NULL;
+PFNGLBLENDCOLOREXTPROC glad_glBlendColorEXT = NULL;
+PFNGLBLENDEQUATIONSEPARATEEXTPROC glad_glBlendEquationSeparateEXT = NULL;
+PFNGLBLENDFUNCSEPARATEEXTPROC glad_glBlendFuncSeparateEXT = NULL;
+PFNGLBLENDEQUATIONEXTPROC glad_glBlendEquationEXT = NULL;
+PFNGLCOLORSUBTABLEEXTPROC glad_glColorSubTableEXT = NULL;
+PFNGLCOPYCOLORSUBTABLEEXTPROC glad_glCopyColorSubTableEXT = NULL;
+PFNGLLOCKARRAYSEXTPROC glad_glLockArraysEXT = NULL;
+PFNGLUNLOCKARRAYSEXTPROC glad_glUnlockArraysEXT = NULL;
+PFNGLCONVOLUTIONFILTER1DEXTPROC glad_glConvolutionFilter1DEXT = NULL;
+PFNGLCONVOLUTIONFILTER2DEXTPROC glad_glConvolutionFilter2DEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERFEXTPROC glad_glConvolutionParameterfEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERFVEXTPROC glad_glConvolutionParameterfvEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERIEXTPROC glad_glConvolutionParameteriEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERIVEXTPROC glad_glConvolutionParameterivEXT = NULL;
+PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC glad_glCopyConvolutionFilter1DEXT = NULL;
+PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC glad_glCopyConvolutionFilter2DEXT = NULL;
+PFNGLGETCONVOLUTIONFILTEREXTPROC glad_glGetConvolutionFilterEXT = NULL;
+PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC glad_glGetConvolutionParameterfvEXT = NULL;
+PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC glad_glGetConvolutionParameterivEXT = NULL;
+PFNGLGETSEPARABLEFILTEREXTPROC glad_glGetSeparableFilterEXT = NULL;
+PFNGLSEPARABLEFILTER2DEXTPROC glad_glSeparableFilter2DEXT = NULL;
+PFNGLTANGENT3BEXTPROC glad_glTangent3bEXT = NULL;
+PFNGLTANGENT3BVEXTPROC glad_glTangent3bvEXT = NULL;
+PFNGLTANGENT3DEXTPROC glad_glTangent3dEXT = NULL;
+PFNGLTANGENT3DVEXTPROC glad_glTangent3dvEXT = NULL;
+PFNGLTANGENT3FEXTPROC glad_glTangent3fEXT = NULL;
+PFNGLTANGENT3FVEXTPROC glad_glTangent3fvEXT = NULL;
+PFNGLTANGENT3IEXTPROC glad_glTangent3iEXT = NULL;
+PFNGLTANGENT3IVEXTPROC glad_glTangent3ivEXT = NULL;
+PFNGLTANGENT3SEXTPROC glad_glTangent3sEXT = NULL;
+PFNGLTANGENT3SVEXTPROC glad_glTangent3svEXT = NULL;
+PFNGLBINORMAL3BEXTPROC glad_glBinormal3bEXT = NULL;
+PFNGLBINORMAL3BVEXTPROC glad_glBinormal3bvEXT = NULL;
+PFNGLBINORMAL3DEXTPROC glad_glBinormal3dEXT = NULL;
+PFNGLBINORMAL3DVEXTPROC glad_glBinormal3dvEXT = NULL;
+PFNGLBINORMAL3FEXTPROC glad_glBinormal3fEXT = NULL;
+PFNGLBINORMAL3FVEXTPROC glad_glBinormal3fvEXT = NULL;
+PFNGLBINORMAL3IEXTPROC glad_glBinormal3iEXT = NULL;
+PFNGLBINORMAL3IVEXTPROC glad_glBinormal3ivEXT = NULL;
+PFNGLBINORMAL3SEXTPROC glad_glBinormal3sEXT = NULL;
+PFNGLBINORMAL3SVEXTPROC glad_glBinormal3svEXT = NULL;
+PFNGLTANGENTPOINTEREXTPROC glad_glTangentPointerEXT = NULL;
+PFNGLBINORMALPOINTEREXTPROC glad_glBinormalPointerEXT = NULL;
+PFNGLCOPYTEXIMAGE1DEXTPROC glad_glCopyTexImage1DEXT = NULL;
+PFNGLCOPYTEXIMAGE2DEXTPROC glad_glCopyTexImage2DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE1DEXTPROC glad_glCopyTexSubImage1DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE2DEXTPROC glad_glCopyTexSubImage2DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE3DEXTPROC glad_glCopyTexSubImage3DEXT = NULL;
+PFNGLCULLPARAMETERDVEXTPROC glad_glCullParameterdvEXT = NULL;
+PFNGLCULLPARAMETERFVEXTPROC glad_glCullParameterfvEXT = NULL;
+PFNGLLABELOBJECTEXTPROC glad_glLabelObjectEXT = NULL;
+PFNGLGETOBJECTLABELEXTPROC glad_glGetObjectLabelEXT = NULL;
+PFNGLINSERTEVENTMARKEREXTPROC glad_glInsertEventMarkerEXT = NULL;
+PFNGLPUSHGROUPMARKEREXTPROC glad_glPushGroupMarkerEXT = NULL;
+PFNGLPOPGROUPMARKEREXTPROC glad_glPopGroupMarkerEXT = NULL;
+PFNGLDEPTHBOUNDSEXTPROC glad_glDepthBoundsEXT = NULL;
+PFNGLMATRIXLOADFEXTPROC glad_glMatrixLoadfEXT = NULL;
+PFNGLMATRIXLOADDEXTPROC glad_glMatrixLoaddEXT = NULL;
+PFNGLMATRIXMULTFEXTPROC glad_glMatrixMultfEXT = NULL;
+PFNGLMATRIXMULTDEXTPROC glad_glMatrixMultdEXT = NULL;
+PFNGLMATRIXLOADIDENTITYEXTPROC glad_glMatrixLoadIdentityEXT = NULL;
+PFNGLMATRIXROTATEFEXTPROC glad_glMatrixRotatefEXT = NULL;
+PFNGLMATRIXROTATEDEXTPROC glad_glMatrixRotatedEXT = NULL;
+PFNGLMATRIXSCALEFEXTPROC glad_glMatrixScalefEXT = NULL;
+PFNGLMATRIXSCALEDEXTPROC glad_glMatrixScaledEXT = NULL;
+PFNGLMATRIXTRANSLATEFEXTPROC glad_glMatrixTranslatefEXT = NULL;
+PFNGLMATRIXTRANSLATEDEXTPROC glad_glMatrixTranslatedEXT = NULL;
+PFNGLMATRIXFRUSTUMEXTPROC glad_glMatrixFrustumEXT = NULL;
+PFNGLMATRIXORTHOEXTPROC glad_glMatrixOrthoEXT = NULL;
+PFNGLMATRIXPOPEXTPROC glad_glMatrixPopEXT = NULL;
+PFNGLMATRIXPUSHEXTPROC glad_glMatrixPushEXT = NULL;
+PFNGLCLIENTATTRIBDEFAULTEXTPROC glad_glClientAttribDefaultEXT = NULL;
+PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC glad_glPushClientAttribDefaultEXT = NULL;
+PFNGLTEXTUREPARAMETERFEXTPROC glad_glTextureParameterfEXT = NULL;
+PFNGLTEXTUREPARAMETERFVEXTPROC glad_glTextureParameterfvEXT = NULL;
+PFNGLTEXTUREPARAMETERIEXTPROC glad_glTextureParameteriEXT = NULL;
+PFNGLTEXTUREPARAMETERIVEXTPROC glad_glTextureParameterivEXT = NULL;
+PFNGLTEXTUREIMAGE1DEXTPROC glad_glTextureImage1DEXT = NULL;
+PFNGLTEXTUREIMAGE2DEXTPROC glad_glTextureImage2DEXT = NULL;
+PFNGLTEXTURESUBIMAGE1DEXTPROC glad_glTextureSubImage1DEXT = NULL;
+PFNGLTEXTURESUBIMAGE2DEXTPROC glad_glTextureSubImage2DEXT = NULL;
+PFNGLCOPYTEXTUREIMAGE1DEXTPROC glad_glCopyTextureImage1DEXT = NULL;
+PFNGLCOPYTEXTUREIMAGE2DEXTPROC glad_glCopyTextureImage2DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC glad_glCopyTextureSubImage1DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC glad_glCopyTextureSubImage2DEXT = NULL;
+PFNGLGETTEXTUREIMAGEEXTPROC glad_glGetTextureImageEXT = NULL;
+PFNGLGETTEXTUREPARAMETERFVEXTPROC glad_glGetTextureParameterfvEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIVEXTPROC glad_glGetTextureParameterivEXT = NULL;
+PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC glad_glGetTextureLevelParameterfvEXT = NULL;
+PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC glad_glGetTextureLevelParameterivEXT = NULL;
+PFNGLTEXTUREIMAGE3DEXTPROC glad_glTextureImage3DEXT = NULL;
+PFNGLTEXTURESUBIMAGE3DEXTPROC glad_glTextureSubImage3DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC glad_glCopyTextureSubImage3DEXT = NULL;
+PFNGLBINDMULTITEXTUREEXTPROC glad_glBindMultiTextureEXT = NULL;
+PFNGLMULTITEXCOORDPOINTEREXTPROC glad_glMultiTexCoordPointerEXT = NULL;
+PFNGLMULTITEXENVFEXTPROC glad_glMultiTexEnvfEXT = NULL;
+PFNGLMULTITEXENVFVEXTPROC glad_glMultiTexEnvfvEXT = NULL;
+PFNGLMULTITEXENVIEXTPROC glad_glMultiTexEnviEXT = NULL;
+PFNGLMULTITEXENVIVEXTPROC glad_glMultiTexEnvivEXT = NULL;
+PFNGLMULTITEXGENDEXTPROC glad_glMultiTexGendEXT = NULL;
+PFNGLMULTITEXGENDVEXTPROC glad_glMultiTexGendvEXT = NULL;
+PFNGLMULTITEXGENFEXTPROC glad_glMultiTexGenfEXT = NULL;
+PFNGLMULTITEXGENFVEXTPROC glad_glMultiTexGenfvEXT = NULL;
+PFNGLMULTITEXGENIEXTPROC glad_glMultiTexGeniEXT = NULL;
+PFNGLMULTITEXGENIVEXTPROC glad_glMultiTexGenivEXT = NULL;
+PFNGLGETMULTITEXENVFVEXTPROC glad_glGetMultiTexEnvfvEXT = NULL;
+PFNGLGETMULTITEXENVIVEXTPROC glad_glGetMultiTexEnvivEXT = NULL;
+PFNGLGETMULTITEXGENDVEXTPROC glad_glGetMultiTexGendvEXT = NULL;
+PFNGLGETMULTITEXGENFVEXTPROC glad_glGetMultiTexGenfvEXT = NULL;
+PFNGLGETMULTITEXGENIVEXTPROC glad_glGetMultiTexGenivEXT = NULL;
+PFNGLMULTITEXPARAMETERIEXTPROC glad_glMultiTexParameteriEXT = NULL;
+PFNGLMULTITEXPARAMETERIVEXTPROC glad_glMultiTexParameterivEXT = NULL;
+PFNGLMULTITEXPARAMETERFEXTPROC glad_glMultiTexParameterfEXT = NULL;
+PFNGLMULTITEXPARAMETERFVEXTPROC glad_glMultiTexParameterfvEXT = NULL;
+PFNGLMULTITEXIMAGE1DEXTPROC glad_glMultiTexImage1DEXT = NULL;
+PFNGLMULTITEXIMAGE2DEXTPROC glad_glMultiTexImage2DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE1DEXTPROC glad_glMultiTexSubImage1DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE2DEXTPROC glad_glMultiTexSubImage2DEXT = NULL;
+PFNGLCOPYMULTITEXIMAGE1DEXTPROC glad_glCopyMultiTexImage1DEXT = NULL;
+PFNGLCOPYMULTITEXIMAGE2DEXTPROC glad_glCopyMultiTexImage2DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC glad_glCopyMultiTexSubImage1DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC glad_glCopyMultiTexSubImage2DEXT = NULL;
+PFNGLGETMULTITEXIMAGEEXTPROC glad_glGetMultiTexImageEXT = NULL;
+PFNGLGETMULTITEXPARAMETERFVEXTPROC glad_glGetMultiTexParameterfvEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIVEXTPROC glad_glGetMultiTexParameterivEXT = NULL;
+PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC glad_glGetMultiTexLevelParameterfvEXT = NULL;
+PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC glad_glGetMultiTexLevelParameterivEXT = NULL;
+PFNGLMULTITEXIMAGE3DEXTPROC glad_glMultiTexImage3DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE3DEXTPROC glad_glMultiTexSubImage3DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC glad_glCopyMultiTexSubImage3DEXT = NULL;
+PFNGLENABLECLIENTSTATEINDEXEDEXTPROC glad_glEnableClientStateIndexedEXT = NULL;
+PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC glad_glDisableClientStateIndexedEXT = NULL;
+PFNGLGETFLOATINDEXEDVEXTPROC glad_glGetFloatIndexedvEXT = NULL;
+PFNGLGETDOUBLEINDEXEDVEXTPROC glad_glGetDoubleIndexedvEXT = NULL;
+PFNGLGETPOINTERINDEXEDVEXTPROC glad_glGetPointerIndexedvEXT = NULL;
+PFNGLENABLEINDEXEDEXTPROC glad_glEnableIndexedEXT = NULL;
+PFNGLDISABLEINDEXEDEXTPROC glad_glDisableIndexedEXT = NULL;
+PFNGLISENABLEDINDEXEDEXTPROC glad_glIsEnabledIndexedEXT = NULL;
+PFNGLGETINTEGERINDEXEDVEXTPROC glad_glGetIntegerIndexedvEXT = NULL;
+PFNGLGETBOOLEANINDEXEDVEXTPROC glad_glGetBooleanIndexedvEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC glad_glCompressedTextureImage3DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC glad_glCompressedTextureImage2DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC glad_glCompressedTextureImage1DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC glad_glCompressedTextureSubImage3DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC glad_glCompressedTextureSubImage2DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC glad_glCompressedTextureSubImage1DEXT = NULL;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC glad_glGetCompressedTextureImageEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC glad_glCompressedMultiTexImage3DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC glad_glCompressedMultiTexImage2DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC glad_glCompressedMultiTexImage1DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC glad_glCompressedMultiTexSubImage3DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC glad_glCompressedMultiTexSubImage2DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC glad_glCompressedMultiTexSubImage1DEXT = NULL;
+PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC glad_glGetCompressedMultiTexImageEXT = NULL;
+PFNGLMATRIXLOADTRANSPOSEFEXTPROC glad_glMatrixLoadTransposefEXT = NULL;
+PFNGLMATRIXLOADTRANSPOSEDEXTPROC glad_glMatrixLoadTransposedEXT = NULL;
+PFNGLMATRIXMULTTRANSPOSEFEXTPROC glad_glMatrixMultTransposefEXT = NULL;
+PFNGLMATRIXMULTTRANSPOSEDEXTPROC glad_glMatrixMultTransposedEXT = NULL;
+PFNGLNAMEDBUFFERDATAEXTPROC glad_glNamedBufferDataEXT = NULL;
+PFNGLNAMEDBUFFERSUBDATAEXTPROC glad_glNamedBufferSubDataEXT = NULL;
+PFNGLMAPNAMEDBUFFEREXTPROC glad_glMapNamedBufferEXT = NULL;
+PFNGLUNMAPNAMEDBUFFEREXTPROC glad_glUnmapNamedBufferEXT = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC glad_glGetNamedBufferParameterivEXT = NULL;
+PFNGLGETNAMEDBUFFERPOINTERVEXTPROC glad_glGetNamedBufferPointervEXT = NULL;
+PFNGLGETNAMEDBUFFERSUBDATAEXTPROC glad_glGetNamedBufferSubDataEXT = NULL;
+PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT = NULL;
+PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT = NULL;
+PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT = NULL;
+PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT = NULL;
+PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT = NULL;
+PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT = NULL;
+PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT = NULL;
+PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT = NULL;
+PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT = NULL;
+PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT = NULL;
+PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT = NULL;
+PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT = NULL;
+PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT = NULL;
+PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT = NULL;
+PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT = NULL;
+PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT = NULL;
+PFNGLTEXTUREBUFFEREXTPROC glad_glTextureBufferEXT = NULL;
+PFNGLMULTITEXBUFFEREXTPROC glad_glMultiTexBufferEXT = NULL;
+PFNGLTEXTUREPARAMETERIIVEXTPROC glad_glTextureParameterIivEXT = NULL;
+PFNGLTEXTUREPARAMETERIUIVEXTPROC glad_glTextureParameterIuivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIIVEXTPROC glad_glGetTextureParameterIivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIUIVEXTPROC glad_glGetTextureParameterIuivEXT = NULL;
+PFNGLMULTITEXPARAMETERIIVEXTPROC glad_glMultiTexParameterIivEXT = NULL;
+PFNGLMULTITEXPARAMETERIUIVEXTPROC glad_glMultiTexParameterIuivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIIVEXTPROC glad_glGetMultiTexParameterIivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIUIVEXTPROC glad_glGetMultiTexParameterIuivEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC glad_glNamedProgramLocalParameters4fvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC glad_glNamedProgramLocalParameterI4iEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC glad_glNamedProgramLocalParameterI4ivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC glad_glNamedProgramLocalParametersI4ivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC glad_glNamedProgramLocalParameterI4uiEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC glad_glNamedProgramLocalParameterI4uivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC glad_glNamedProgramLocalParametersI4uivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC glad_glGetNamedProgramLocalParameterIivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC glad_glGetNamedProgramLocalParameterIuivEXT = NULL;
+PFNGLENABLECLIENTSTATEIEXTPROC glad_glEnableClientStateiEXT = NULL;
+PFNGLDISABLECLIENTSTATEIEXTPROC glad_glDisableClientStateiEXT = NULL;
+PFNGLGETFLOATI_VEXTPROC glad_glGetFloati_vEXT = NULL;
+PFNGLGETDOUBLEI_VEXTPROC glad_glGetDoublei_vEXT = NULL;
+PFNGLGETPOINTERI_VEXTPROC glad_glGetPointeri_vEXT = NULL;
+PFNGLNAMEDPROGRAMSTRINGEXTPROC glad_glNamedProgramStringEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC glad_glNamedProgramLocalParameter4dEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC glad_glNamedProgramLocalParameter4dvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC glad_glNamedProgramLocalParameter4fEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC glad_glNamedProgramLocalParameter4fvEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC glad_glGetNamedProgramLocalParameterdvEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC glad_glGetNamedProgramLocalParameterfvEXT = NULL;
+PFNGLGETNAMEDPROGRAMIVEXTPROC glad_glGetNamedProgramivEXT = NULL;
+PFNGLGETNAMEDPROGRAMSTRINGEXTPROC glad_glGetNamedProgramStringEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC glad_glNamedRenderbufferStorageEXT = NULL;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC glad_glGetNamedRenderbufferParameterivEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glNamedRenderbufferStorageMultisampleEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC glad_glNamedRenderbufferStorageMultisampleCoverageEXT = NULL;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC glad_glCheckNamedFramebufferStatusEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC glad_glNamedFramebufferTexture1DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC glad_glNamedFramebufferTexture2DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC glad_glNamedFramebufferTexture3DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC glad_glNamedFramebufferRenderbufferEXT = NULL;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetNamedFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGENERATETEXTUREMIPMAPEXTPROC glad_glGenerateTextureMipmapEXT = NULL;
+PFNGLGENERATEMULTITEXMIPMAPEXTPROC glad_glGenerateMultiTexMipmapEXT = NULL;
+PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC glad_glFramebufferDrawBufferEXT = NULL;
+PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC glad_glFramebufferDrawBuffersEXT = NULL;
+PFNGLFRAMEBUFFERREADBUFFEREXTPROC glad_glFramebufferReadBufferEXT = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetFramebufferParameterivEXT = NULL;
+PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC glad_glNamedCopyBufferSubDataEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC glad_glNamedFramebufferTextureEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC glad_glNamedFramebufferTextureLayerEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC glad_glNamedFramebufferTextureFaceEXT = NULL;
+PFNGLTEXTURERENDERBUFFEREXTPROC glad_glTextureRenderbufferEXT = NULL;
+PFNGLMULTITEXRENDERBUFFEREXTPROC glad_glMultiTexRenderbufferEXT = NULL;
+PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC glad_glVertexArrayVertexOffsetEXT = NULL;
+PFNGLVERTEXARRAYCOLOROFFSETEXTPROC glad_glVertexArrayColorOffsetEXT = NULL;
+PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC glad_glVertexArrayEdgeFlagOffsetEXT = NULL;
+PFNGLVERTEXARRAYINDEXOFFSETEXTPROC glad_glVertexArrayIndexOffsetEXT = NULL;
+PFNGLVERTEXARRAYNORMALOFFSETEXTPROC glad_glVertexArrayNormalOffsetEXT = NULL;
+PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC glad_glVertexArrayTexCoordOffsetEXT = NULL;
+PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC glad_glVertexArrayMultiTexCoordOffsetEXT = NULL;
+PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC glad_glVertexArrayFogCoordOffsetEXT = NULL;
+PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC glad_glVertexArraySecondaryColorOffsetEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC glad_glVertexArrayVertexAttribOffsetEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC glad_glVertexArrayVertexAttribIOffsetEXT = NULL;
+PFNGLENABLEVERTEXARRAYEXTPROC glad_glEnableVertexArrayEXT = NULL;
+PFNGLDISABLEVERTEXARRAYEXTPROC glad_glDisableVertexArrayEXT = NULL;
+PFNGLENABLEVERTEXARRAYATTRIBEXTPROC glad_glEnableVertexArrayAttribEXT = NULL;
+PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC glad_glDisableVertexArrayAttribEXT = NULL;
+PFNGLGETVERTEXARRAYINTEGERVEXTPROC glad_glGetVertexArrayIntegervEXT = NULL;
+PFNGLGETVERTEXARRAYPOINTERVEXTPROC glad_glGetVertexArrayPointervEXT = NULL;
+PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC glad_glGetVertexArrayIntegeri_vEXT = NULL;
+PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC glad_glGetVertexArrayPointeri_vEXT = NULL;
+PFNGLMAPNAMEDBUFFERRANGEEXTPROC glad_glMapNamedBufferRangeEXT = NULL;
+PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC glad_glFlushMappedNamedBufferRangeEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEEXTPROC glad_glNamedBufferStorageEXT = NULL;
+PFNGLCLEARNAMEDBUFFERDATAEXTPROC glad_glClearNamedBufferDataEXT = NULL;
+PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC glad_glClearNamedBufferSubDataEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC glad_glNamedFramebufferParameteriEXT = NULL;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetNamedFramebufferParameterivEXT = NULL;
+PFNGLPROGRAMUNIFORM1DEXTPROC glad_glProgramUniform1dEXT = NULL;
+PFNGLPROGRAMUNIFORM2DEXTPROC glad_glProgramUniform2dEXT = NULL;
+PFNGLPROGRAMUNIFORM3DEXTPROC glad_glProgramUniform3dEXT = NULL;
+PFNGLPROGRAMUNIFORM4DEXTPROC glad_glProgramUniform4dEXT = NULL;
+PFNGLPROGRAMUNIFORM1DVEXTPROC glad_glProgramUniform1dvEXT = NULL;
+PFNGLPROGRAMUNIFORM2DVEXTPROC glad_glProgramUniform2dvEXT = NULL;
+PFNGLPROGRAMUNIFORM3DVEXTPROC glad_glProgramUniform3dvEXT = NULL;
+PFNGLPROGRAMUNIFORM4DVEXTPROC glad_glProgramUniform4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC glad_glProgramUniformMatrix2dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC glad_glProgramUniformMatrix3dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC glad_glProgramUniformMatrix4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC glad_glProgramUniformMatrix2x3dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC glad_glProgramUniformMatrix2x4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC glad_glProgramUniformMatrix3x2dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC glad_glProgramUniformMatrix3x4dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC glad_glProgramUniformMatrix4x2dvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC glad_glProgramUniformMatrix4x3dvEXT = NULL;
+PFNGLTEXTUREBUFFERRANGEEXTPROC glad_glTextureBufferRangeEXT = NULL;
+PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT = NULL;
+PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT = NULL;
+PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT = NULL;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC glad_glTextureStorage2DMultisampleEXT = NULL;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC glad_glTextureStorage3DMultisampleEXT = NULL;
+PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC glad_glVertexArrayBindVertexBufferEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC glad_glVertexArrayVertexAttribFormatEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC glad_glVertexArrayVertexAttribIFormatEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC glad_glVertexArrayVertexAttribLFormatEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC glad_glVertexArrayVertexAttribBindingEXT = NULL;
+PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC glad_glVertexArrayVertexBindingDivisorEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC glad_glVertexArrayVertexAttribLOffsetEXT = NULL;
+PFNGLTEXTUREPAGECOMMITMENTEXTPROC glad_glTexturePageCommitmentEXT = NULL;
+PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC glad_glVertexArrayVertexAttribDivisorEXT = NULL;
+PFNGLCOLORMASKINDEXEDEXTPROC glad_glColorMaskIndexedEXT = NULL;
+PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT = NULL;
+PFNGLDRAWRANGEELEMENTSEXTPROC glad_glDrawRangeElementsEXT = NULL;
+PFNGLBUFFERSTORAGEEXTERNALEXTPROC glad_glBufferStorageExternalEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC glad_glNamedBufferStorageExternalEXT = NULL;
+PFNGLFOGCOORDFEXTPROC glad_glFogCoordfEXT = NULL;
+PFNGLFOGCOORDFVEXTPROC glad_glFogCoordfvEXT = NULL;
+PFNGLFOGCOORDDEXTPROC glad_glFogCoorddEXT = NULL;
+PFNGLFOGCOORDDVEXTPROC glad_glFogCoorddvEXT = NULL;
+PFNGLFOGCOORDPOINTEREXTPROC glad_glFogCoordPointerEXT = NULL;
+PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
+PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
+PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
+PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT = NULL;
+PFNGLPROGRAMENVPARAMETERS4FVEXTPROC glad_glProgramEnvParameters4fvEXT = NULL;
+PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC glad_glProgramLocalParameters4fvEXT = NULL;
+PFNGLGETUNIFORMUIVEXTPROC glad_glGetUniformuivEXT = NULL;
+PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT = NULL;
+PFNGLGETFRAGDATALOCATIONEXTPROC glad_glGetFragDataLocationEXT = NULL;
+PFNGLUNIFORM1UIEXTPROC glad_glUniform1uiEXT = NULL;
+PFNGLUNIFORM2UIEXTPROC glad_glUniform2uiEXT = NULL;
+PFNGLUNIFORM3UIEXTPROC glad_glUniform3uiEXT = NULL;
+PFNGLUNIFORM4UIEXTPROC glad_glUniform4uiEXT = NULL;
+PFNGLUNIFORM1UIVEXTPROC glad_glUniform1uivEXT = NULL;
+PFNGLUNIFORM2UIVEXTPROC glad_glUniform2uivEXT = NULL;
+PFNGLUNIFORM3UIVEXTPROC glad_glUniform3uivEXT = NULL;
+PFNGLUNIFORM4UIVEXTPROC glad_glUniform4uivEXT = NULL;
+PFNGLGETHISTOGRAMEXTPROC glad_glGetHistogramEXT = NULL;
+PFNGLGETHISTOGRAMPARAMETERFVEXTPROC glad_glGetHistogramParameterfvEXT = NULL;
+PFNGLGETHISTOGRAMPARAMETERIVEXTPROC glad_glGetHistogramParameterivEXT = NULL;
+PFNGLGETMINMAXEXTPROC glad_glGetMinmaxEXT = NULL;
+PFNGLGETMINMAXPARAMETERFVEXTPROC glad_glGetMinmaxParameterfvEXT = NULL;
+PFNGLGETMINMAXPARAMETERIVEXTPROC glad_glGetMinmaxParameterivEXT = NULL;
+PFNGLHISTOGRAMEXTPROC glad_glHistogramEXT = NULL;
+PFNGLMINMAXEXTPROC glad_glMinmaxEXT = NULL;
+PFNGLRESETHISTOGRAMEXTPROC glad_glResetHistogramEXT = NULL;
+PFNGLRESETMINMAXEXTPROC glad_glResetMinmaxEXT = NULL;
+PFNGLINDEXFUNCEXTPROC glad_glIndexFuncEXT = NULL;
+PFNGLINDEXMATERIALEXTPROC glad_glIndexMaterialEXT = NULL;
+PFNGLAPPLYTEXTUREEXTPROC glad_glApplyTextureEXT = NULL;
+PFNGLTEXTURELIGHTEXTPROC glad_glTextureLightEXT = NULL;
+PFNGLTEXTUREMATERIALEXTPROC glad_glTextureMaterialEXT = NULL;
+PFNGLGETUNSIGNEDBYTEVEXTPROC glad_glGetUnsignedBytevEXT = NULL;
+PFNGLGETUNSIGNEDBYTEI_VEXTPROC glad_glGetUnsignedBytei_vEXT = NULL;
+PFNGLDELETEMEMORYOBJECTSEXTPROC glad_glDeleteMemoryObjectsEXT = NULL;
+PFNGLISMEMORYOBJECTEXTPROC glad_glIsMemoryObjectEXT = NULL;
+PFNGLCREATEMEMORYOBJECTSEXTPROC glad_glCreateMemoryObjectsEXT = NULL;
+PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glad_glMemoryObjectParameterivEXT = NULL;
+PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC glad_glGetMemoryObjectParameterivEXT = NULL;
+PFNGLTEXSTORAGEMEM2DEXTPROC glad_glTexStorageMem2DEXT = NULL;
+PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTexStorageMem2DMultisampleEXT = NULL;
+PFNGLTEXSTORAGEMEM3DEXTPROC glad_glTexStorageMem3DEXT = NULL;
+PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTexStorageMem3DMultisampleEXT = NULL;
+PFNGLBUFFERSTORAGEMEMEXTPROC glad_glBufferStorageMemEXT = NULL;
+PFNGLTEXTURESTORAGEMEM2DEXTPROC glad_glTextureStorageMem2DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTextureStorageMem2DMultisampleEXT = NULL;
+PFNGLTEXTURESTORAGEMEM3DEXTPROC glad_glTextureStorageMem3DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTextureStorageMem3DMultisampleEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC glad_glNamedBufferStorageMemEXT = NULL;
+PFNGLTEXSTORAGEMEM1DEXTPROC glad_glTexStorageMem1DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM1DEXTPROC glad_glTextureStorageMem1DEXT = NULL;
+PFNGLIMPORTMEMORYFDEXTPROC glad_glImportMemoryFdEXT = NULL;
+PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC glad_glImportMemoryWin32HandleEXT = NULL;
+PFNGLIMPORTMEMORYWIN32NAMEEXTPROC glad_glImportMemoryWin32NameEXT = NULL;
+PFNGLMULTIDRAWARRAYSEXTPROC glad_glMultiDrawArraysEXT = NULL;
+PFNGLMULTIDRAWELEMENTSEXTPROC glad_glMultiDrawElementsEXT = NULL;
+PFNGLSAMPLEMASKEXTPROC glad_glSampleMaskEXT = NULL;
+PFNGLSAMPLEPATTERNEXTPROC glad_glSamplePatternEXT = NULL;
+PFNGLCOLORTABLEEXTPROC glad_glColorTableEXT = NULL;
+PFNGLGETCOLORTABLEEXTPROC glad_glGetColorTableEXT = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVEXTPROC glad_glGetColorTableParameterivEXT = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVEXTPROC glad_glGetColorTableParameterfvEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERIEXTPROC glad_glPixelTransformParameteriEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERFEXTPROC glad_glPixelTransformParameterfEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC glad_glPixelTransformParameterivEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC glad_glPixelTransformParameterfvEXT = NULL;
+PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC glad_glGetPixelTransformParameterivEXT = NULL;
+PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC glad_glGetPixelTransformParameterfvEXT = NULL;
+PFNGLPOINTPARAMETERFEXTPROC glad_glPointParameterfEXT = NULL;
+PFNGLPOINTPARAMETERFVEXTPROC glad_glPointParameterfvEXT = NULL;
+PFNGLPOLYGONOFFSETEXTPROC glad_glPolygonOffsetEXT = NULL;
+PFNGLPOLYGONOFFSETCLAMPEXTPROC glad_glPolygonOffsetClampEXT = NULL;
+PFNGLPROVOKINGVERTEXEXTPROC glad_glProvokingVertexEXT = NULL;
+PFNGLRASTERSAMPLESEXTPROC glad_glRasterSamplesEXT = NULL;
+PFNGLSECONDARYCOLOR3BEXTPROC glad_glSecondaryColor3bEXT = NULL;
+PFNGLSECONDARYCOLOR3BVEXTPROC glad_glSecondaryColor3bvEXT = NULL;
+PFNGLSECONDARYCOLOR3DEXTPROC glad_glSecondaryColor3dEXT = NULL;
+PFNGLSECONDARYCOLOR3DVEXTPROC glad_glSecondaryColor3dvEXT = NULL;
+PFNGLSECONDARYCOLOR3FEXTPROC glad_glSecondaryColor3fEXT = NULL;
+PFNGLSECONDARYCOLOR3FVEXTPROC glad_glSecondaryColor3fvEXT = NULL;
+PFNGLSECONDARYCOLOR3IEXTPROC glad_glSecondaryColor3iEXT = NULL;
+PFNGLSECONDARYCOLOR3IVEXTPROC glad_glSecondaryColor3ivEXT = NULL;
+PFNGLSECONDARYCOLOR3SEXTPROC glad_glSecondaryColor3sEXT = NULL;
+PFNGLSECONDARYCOLOR3SVEXTPROC glad_glSecondaryColor3svEXT = NULL;
+PFNGLSECONDARYCOLOR3UBEXTPROC glad_glSecondaryColor3ubEXT = NULL;
+PFNGLSECONDARYCOLOR3UBVEXTPROC glad_glSecondaryColor3ubvEXT = NULL;
+PFNGLSECONDARYCOLOR3UIEXTPROC glad_glSecondaryColor3uiEXT = NULL;
+PFNGLSECONDARYCOLOR3UIVEXTPROC glad_glSecondaryColor3uivEXT = NULL;
+PFNGLSECONDARYCOLOR3USEXTPROC glad_glSecondaryColor3usEXT = NULL;
+PFNGLSECONDARYCOLOR3USVEXTPROC glad_glSecondaryColor3usvEXT = NULL;
+PFNGLSECONDARYCOLORPOINTEREXTPROC glad_glSecondaryColorPointerEXT = NULL;
+PFNGLGENSEMAPHORESEXTPROC glad_glGenSemaphoresEXT = NULL;
+PFNGLDELETESEMAPHORESEXTPROC glad_glDeleteSemaphoresEXT = NULL;
+PFNGLISSEMAPHOREEXTPROC glad_glIsSemaphoreEXT = NULL;
+PFNGLSEMAPHOREPARAMETERUI64VEXTPROC glad_glSemaphoreParameterui64vEXT = NULL;
+PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC glad_glGetSemaphoreParameterui64vEXT = NULL;
+PFNGLWAITSEMAPHOREEXTPROC glad_glWaitSemaphoreEXT = NULL;
+PFNGLSIGNALSEMAPHOREEXTPROC glad_glSignalSemaphoreEXT = NULL;
+PFNGLIMPORTSEMAPHOREFDEXTPROC glad_glImportSemaphoreFdEXT = NULL;
+PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC glad_glImportSemaphoreWin32HandleEXT = NULL;
+PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC glad_glImportSemaphoreWin32NameEXT = NULL;
+PFNGLUSESHADERPROGRAMEXTPROC glad_glUseShaderProgramEXT = NULL;
+PFNGLACTIVEPROGRAMEXTPROC glad_glActiveProgramEXT = NULL;
+PFNGLCREATESHADERPROGRAMEXTPROC glad_glCreateShaderProgramEXT = NULL;
+PFNGLACTIVESHADERPROGRAMEXTPROC glad_glActiveShaderProgramEXT = NULL;
+PFNGLBINDPROGRAMPIPELINEEXTPROC glad_glBindProgramPipelineEXT = NULL;
+PFNGLCREATESHADERPROGRAMVEXTPROC glad_glCreateShaderProgramvEXT = NULL;
+PFNGLDELETEPROGRAMPIPELINESEXTPROC glad_glDeleteProgramPipelinesEXT = NULL;
+PFNGLGENPROGRAMPIPELINESEXTPROC glad_glGenProgramPipelinesEXT = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC glad_glGetProgramPipelineInfoLogEXT = NULL;
+PFNGLGETPROGRAMPIPELINEIVEXTPROC glad_glGetProgramPipelineivEXT = NULL;
+PFNGLISPROGRAMPIPELINEEXTPROC glad_glIsProgramPipelineEXT = NULL;
+PFNGLUSEPROGRAMSTAGESEXTPROC glad_glUseProgramStagesEXT = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEEXTPROC glad_glValidateProgramPipelineEXT = NULL;
+PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC glad_glFramebufferFetchBarrierEXT = NULL;
+PFNGLBINDIMAGETEXTUREEXTPROC glad_glBindImageTextureEXT = NULL;
+PFNGLMEMORYBARRIEREXTPROC glad_glMemoryBarrierEXT = NULL;
+PFNGLSTENCILCLEARTAGEXTPROC glad_glStencilClearTagEXT = NULL;
+PFNGLACTIVESTENCILFACEEXTPROC glad_glActiveStencilFaceEXT = NULL;
+PFNGLTEXSUBIMAGE1DEXTPROC glad_glTexSubImage1DEXT = NULL;
+PFNGLTEXSUBIMAGE2DEXTPROC glad_glTexSubImage2DEXT = NULL;
+PFNGLTEXIMAGE3DEXTPROC glad_glTexImage3DEXT = NULL;
+PFNGLTEXSUBIMAGE3DEXTPROC glad_glTexSubImage3DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glad_glFramebufferTextureLayerEXT = NULL;
+PFNGLTEXBUFFEREXTPROC glad_glTexBufferEXT = NULL;
+PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT = NULL;
+PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT = NULL;
+PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT = NULL;
+PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT = NULL;
+PFNGLCLEARCOLORIIEXTPROC glad_glClearColorIiEXT = NULL;
+PFNGLCLEARCOLORIUIEXTPROC glad_glClearColorIuiEXT = NULL;
+PFNGLARETEXTURESRESIDENTEXTPROC glad_glAreTexturesResidentEXT = NULL;
+PFNGLBINDTEXTUREEXTPROC glad_glBindTextureEXT = NULL;
+PFNGLDELETETEXTURESEXTPROC glad_glDeleteTexturesEXT = NULL;
+PFNGLGENTEXTURESEXTPROC glad_glGenTexturesEXT = NULL;
+PFNGLISTEXTUREEXTPROC glad_glIsTextureEXT = NULL;
+PFNGLPRIORITIZETEXTURESEXTPROC glad_glPrioritizeTexturesEXT = NULL;
+PFNGLTEXTURENORMALEXTPROC glad_glTextureNormalEXT = NULL;
+PFNGLGETQUERYOBJECTI64VEXTPROC glad_glGetQueryObjecti64vEXT = NULL;
+PFNGLGETQUERYOBJECTUI64VEXTPROC glad_glGetQueryObjectui64vEXT = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKEXTPROC glad_glBeginTransformFeedbackEXT = NULL;
+PFNGLENDTRANSFORMFEEDBACKEXTPROC glad_glEndTransformFeedbackEXT = NULL;
+PFNGLBINDBUFFERRANGEEXTPROC glad_glBindBufferRangeEXT = NULL;
+PFNGLBINDBUFFEROFFSETEXTPROC glad_glBindBufferOffsetEXT = NULL;
+PFNGLBINDBUFFERBASEEXTPROC glad_glBindBufferBaseEXT = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC glad_glTransformFeedbackVaryingsEXT = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC glad_glGetTransformFeedbackVaryingEXT = NULL;
+PFNGLARRAYELEMENTEXTPROC glad_glArrayElementEXT = NULL;
+PFNGLCOLORPOINTEREXTPROC glad_glColorPointerEXT = NULL;
+PFNGLDRAWARRAYSEXTPROC glad_glDrawArraysEXT = NULL;
+PFNGLEDGEFLAGPOINTEREXTPROC glad_glEdgeFlagPointerEXT = NULL;
+PFNGLGETPOINTERVEXTPROC glad_glGetPointervEXT = NULL;
+PFNGLINDEXPOINTEREXTPROC glad_glIndexPointerEXT = NULL;
+PFNGLNORMALPOINTEREXTPROC glad_glNormalPointerEXT = NULL;
+PFNGLTEXCOORDPOINTEREXTPROC glad_glTexCoordPointerEXT = NULL;
+PFNGLVERTEXPOINTEREXTPROC glad_glVertexPointerEXT = NULL;
+PFNGLVERTEXATTRIBL1DEXTPROC glad_glVertexAttribL1dEXT = NULL;
+PFNGLVERTEXATTRIBL2DEXTPROC glad_glVertexAttribL2dEXT = NULL;
+PFNGLVERTEXATTRIBL3DEXTPROC glad_glVertexAttribL3dEXT = NULL;
+PFNGLVERTEXATTRIBL4DEXTPROC glad_glVertexAttribL4dEXT = NULL;
+PFNGLVERTEXATTRIBL1DVEXTPROC glad_glVertexAttribL1dvEXT = NULL;
+PFNGLVERTEXATTRIBL2DVEXTPROC glad_glVertexAttribL2dvEXT = NULL;
+PFNGLVERTEXATTRIBL3DVEXTPROC glad_glVertexAttribL3dvEXT = NULL;
+PFNGLVERTEXATTRIBL4DVEXTPROC glad_glVertexAttribL4dvEXT = NULL;
+PFNGLVERTEXATTRIBLPOINTEREXTPROC glad_glVertexAttribLPointerEXT = NULL;
+PFNGLGETVERTEXATTRIBLDVEXTPROC glad_glGetVertexAttribLdvEXT = NULL;
+PFNGLBEGINVERTEXSHADEREXTPROC glad_glBeginVertexShaderEXT = NULL;
+PFNGLENDVERTEXSHADEREXTPROC glad_glEndVertexShaderEXT = NULL;
+PFNGLBINDVERTEXSHADEREXTPROC glad_glBindVertexShaderEXT = NULL;
+PFNGLGENVERTEXSHADERSEXTPROC glad_glGenVertexShadersEXT = NULL;
+PFNGLDELETEVERTEXSHADEREXTPROC glad_glDeleteVertexShaderEXT = NULL;
+PFNGLSHADEROP1EXTPROC glad_glShaderOp1EXT = NULL;
+PFNGLSHADEROP2EXTPROC glad_glShaderOp2EXT = NULL;
+PFNGLSHADEROP3EXTPROC glad_glShaderOp3EXT = NULL;
+PFNGLSWIZZLEEXTPROC glad_glSwizzleEXT = NULL;
+PFNGLWRITEMASKEXTPROC glad_glWriteMaskEXT = NULL;
+PFNGLINSERTCOMPONENTEXTPROC glad_glInsertComponentEXT = NULL;
+PFNGLEXTRACTCOMPONENTEXTPROC glad_glExtractComponentEXT = NULL;
+PFNGLGENSYMBOLSEXTPROC glad_glGenSymbolsEXT = NULL;
+PFNGLSETINVARIANTEXTPROC glad_glSetInvariantEXT = NULL;
+PFNGLSETLOCALCONSTANTEXTPROC glad_glSetLocalConstantEXT = NULL;
+PFNGLVARIANTBVEXTPROC glad_glVariantbvEXT = NULL;
+PFNGLVARIANTSVEXTPROC glad_glVariantsvEXT = NULL;
+PFNGLVARIANTIVEXTPROC glad_glVariantivEXT = NULL;
+PFNGLVARIANTFVEXTPROC glad_glVariantfvEXT = NULL;
+PFNGLVARIANTDVEXTPROC glad_glVariantdvEXT = NULL;
+PFNGLVARIANTUBVEXTPROC glad_glVariantubvEXT = NULL;
+PFNGLVARIANTUSVEXTPROC glad_glVariantusvEXT = NULL;
+PFNGLVARIANTUIVEXTPROC glad_glVariantuivEXT = NULL;
+PFNGLVARIANTPOINTEREXTPROC glad_glVariantPointerEXT = NULL;
+PFNGLENABLEVARIANTCLIENTSTATEEXTPROC glad_glEnableVariantClientStateEXT = NULL;
+PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC glad_glDisableVariantClientStateEXT = NULL;
+PFNGLBINDLIGHTPARAMETEREXTPROC glad_glBindLightParameterEXT = NULL;
+PFNGLBINDMATERIALPARAMETEREXTPROC glad_glBindMaterialParameterEXT = NULL;
+PFNGLBINDTEXGENPARAMETEREXTPROC glad_glBindTexGenParameterEXT = NULL;
+PFNGLBINDTEXTUREUNITPARAMETEREXTPROC glad_glBindTextureUnitParameterEXT = NULL;
+PFNGLBINDPARAMETEREXTPROC glad_glBindParameterEXT = NULL;
+PFNGLISVARIANTENABLEDEXTPROC glad_glIsVariantEnabledEXT = NULL;
+PFNGLGETVARIANTBOOLEANVEXTPROC glad_glGetVariantBooleanvEXT = NULL;
+PFNGLGETVARIANTINTEGERVEXTPROC glad_glGetVariantIntegervEXT = NULL;
+PFNGLGETVARIANTFLOATVEXTPROC glad_glGetVariantFloatvEXT = NULL;
+PFNGLGETVARIANTPOINTERVEXTPROC glad_glGetVariantPointervEXT = NULL;
+PFNGLGETINVARIANTBOOLEANVEXTPROC glad_glGetInvariantBooleanvEXT = NULL;
+PFNGLGETINVARIANTINTEGERVEXTPROC glad_glGetInvariantIntegervEXT = NULL;
+PFNGLGETINVARIANTFLOATVEXTPROC glad_glGetInvariantFloatvEXT = NULL;
+PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC glad_glGetLocalConstantBooleanvEXT = NULL;
+PFNGLGETLOCALCONSTANTINTEGERVEXTPROC glad_glGetLocalConstantIntegervEXT = NULL;
+PFNGLGETLOCALCONSTANTFLOATVEXTPROC glad_glGetLocalConstantFloatvEXT = NULL;
+PFNGLVERTEXWEIGHTFEXTPROC glad_glVertexWeightfEXT = NULL;
+PFNGLVERTEXWEIGHTFVEXTPROC glad_glVertexWeightfvEXT = NULL;
+PFNGLVERTEXWEIGHTPOINTEREXTPROC glad_glVertexWeightPointerEXT = NULL;
+PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC glad_glAcquireKeyedMutexWin32EXT = NULL;
+PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC glad_glReleaseKeyedMutexWin32EXT = NULL;
+PFNGLWINDOWRECTANGLESEXTPROC glad_glWindowRectanglesEXT = NULL;
+PFNGLIMPORTSYNCEXTPROC glad_glImportSyncEXT = NULL;
+PFNGLFRAMETERMINATORGREMEDYPROC glad_glFrameTerminatorGREMEDY = NULL;
+PFNGLSTRINGMARKERGREMEDYPROC glad_glStringMarkerGREMEDY = NULL;
+PFNGLIMAGETRANSFORMPARAMETERIHPPROC glad_glImageTransformParameteriHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERFHPPROC glad_glImageTransformParameterfHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERIVHPPROC glad_glImageTransformParameterivHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERFVHPPROC glad_glImageTransformParameterfvHP = NULL;
+PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC glad_glGetImageTransformParameterivHP = NULL;
+PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC glad_glGetImageTransformParameterfvHP = NULL;
+PFNGLMULTIMODEDRAWARRAYSIBMPROC glad_glMultiModeDrawArraysIBM = NULL;
+PFNGLMULTIMODEDRAWELEMENTSIBMPROC glad_glMultiModeDrawElementsIBM = NULL;
+PFNGLFLUSHSTATICDATAIBMPROC glad_glFlushStaticDataIBM = NULL;
+PFNGLCOLORPOINTERLISTIBMPROC glad_glColorPointerListIBM = NULL;
+PFNGLSECONDARYCOLORPOINTERLISTIBMPROC glad_glSecondaryColorPointerListIBM = NULL;
+PFNGLEDGEFLAGPOINTERLISTIBMPROC glad_glEdgeFlagPointerListIBM = NULL;
+PFNGLFOGCOORDPOINTERLISTIBMPROC glad_glFogCoordPointerListIBM = NULL;
+PFNGLINDEXPOINTERLISTIBMPROC glad_glIndexPointerListIBM = NULL;
+PFNGLNORMALPOINTERLISTIBMPROC glad_glNormalPointerListIBM = NULL;
+PFNGLTEXCOORDPOINTERLISTIBMPROC glad_glTexCoordPointerListIBM = NULL;
+PFNGLVERTEXPOINTERLISTIBMPROC glad_glVertexPointerListIBM = NULL;
+PFNGLBLENDFUNCSEPARATEINGRPROC glad_glBlendFuncSeparateINGR = NULL;
+PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC glad_glApplyFramebufferAttachmentCMAAINTEL = NULL;
+PFNGLSYNCTEXTUREINTELPROC glad_glSyncTextureINTEL = NULL;
+PFNGLUNMAPTEXTURE2DINTELPROC glad_glUnmapTexture2DINTEL = NULL;
+PFNGLMAPTEXTURE2DINTELPROC glad_glMapTexture2DINTEL = NULL;
+PFNGLVERTEXPOINTERVINTELPROC glad_glVertexPointervINTEL = NULL;
+PFNGLNORMALPOINTERVINTELPROC glad_glNormalPointervINTEL = NULL;
+PFNGLCOLORPOINTERVINTELPROC glad_glColorPointervINTEL = NULL;
+PFNGLTEXCOORDPOINTERVINTELPROC glad_glTexCoordPointervINTEL = NULL;
+PFNGLBEGINPERFQUERYINTELPROC glad_glBeginPerfQueryINTEL = NULL;
+PFNGLCREATEPERFQUERYINTELPROC glad_glCreatePerfQueryINTEL = NULL;
+PFNGLDELETEPERFQUERYINTELPROC glad_glDeletePerfQueryINTEL = NULL;
+PFNGLENDPERFQUERYINTELPROC glad_glEndPerfQueryINTEL = NULL;
+PFNGLGETFIRSTPERFQUERYIDINTELPROC glad_glGetFirstPerfQueryIdINTEL = NULL;
+PFNGLGETNEXTPERFQUERYIDINTELPROC glad_glGetNextPerfQueryIdINTEL = NULL;
+PFNGLGETPERFCOUNTERINFOINTELPROC glad_glGetPerfCounterInfoINTEL = NULL;
+PFNGLGETPERFQUERYDATAINTELPROC glad_glGetPerfQueryDataINTEL = NULL;
+PFNGLGETPERFQUERYIDBYNAMEINTELPROC glad_glGetPerfQueryIdByNameINTEL = NULL;
+PFNGLGETPERFQUERYINFOINTELPROC glad_glGetPerfQueryInfoINTEL = NULL;
+PFNGLBLENDBARRIERKHRPROC glad_glBlendBarrierKHR = NULL;
+PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
+PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL;
+PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
+PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
+PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL;
+PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
+PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
+PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
+PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL;
+PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR = NULL;
+PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR = NULL;
+PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR = NULL;
+PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR = NULL;
+PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR = NULL;
+PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR = NULL;
+PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR = NULL;
+PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR = NULL;
+PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR = NULL;
+PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR = NULL;
+PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR = NULL;
+PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glad_glMaxShaderCompilerThreadsKHR = NULL;
+PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus = NULL;
+PFNGLREADNPIXELSPROC glad_glReadnPixels = NULL;
+PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv = NULL;
+PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv = NULL;
+PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv = NULL;
+PFNGLGETGRAPHICSRESETSTATUSKHRPROC glad_glGetGraphicsResetStatusKHR = NULL;
+PFNGLREADNPIXELSKHRPROC glad_glReadnPixelsKHR = NULL;
+PFNGLGETNUNIFORMFVKHRPROC glad_glGetnUniformfvKHR = NULL;
+PFNGLGETNUNIFORMIVKHRPROC glad_glGetnUniformivKHR = NULL;
+PFNGLGETNUNIFORMUIVKHRPROC glad_glGetnUniformuivKHR = NULL;
+PFNGLRESIZEBUFFERSMESAPROC glad_glResizeBuffersMESA = NULL;
+PFNGLWINDOWPOS2DMESAPROC glad_glWindowPos2dMESA = NULL;
+PFNGLWINDOWPOS2DVMESAPROC glad_glWindowPos2dvMESA = NULL;
+PFNGLWINDOWPOS2FMESAPROC glad_glWindowPos2fMESA = NULL;
+PFNGLWINDOWPOS2FVMESAPROC glad_glWindowPos2fvMESA = NULL;
+PFNGLWINDOWPOS2IMESAPROC glad_glWindowPos2iMESA = NULL;
+PFNGLWINDOWPOS2IVMESAPROC glad_glWindowPos2ivMESA = NULL;
+PFNGLWINDOWPOS2SMESAPROC glad_glWindowPos2sMESA = NULL;
+PFNGLWINDOWPOS2SVMESAPROC glad_glWindowPos2svMESA = NULL;
+PFNGLWINDOWPOS3DMESAPROC glad_glWindowPos3dMESA = NULL;
+PFNGLWINDOWPOS3DVMESAPROC glad_glWindowPos3dvMESA = NULL;
+PFNGLWINDOWPOS3FMESAPROC glad_glWindowPos3fMESA = NULL;
+PFNGLWINDOWPOS3FVMESAPROC glad_glWindowPos3fvMESA = NULL;
+PFNGLWINDOWPOS3IMESAPROC glad_glWindowPos3iMESA = NULL;
+PFNGLWINDOWPOS3IVMESAPROC glad_glWindowPos3ivMESA = NULL;
+PFNGLWINDOWPOS3SMESAPROC glad_glWindowPos3sMESA = NULL;
+PFNGLWINDOWPOS3SVMESAPROC glad_glWindowPos3svMESA = NULL;
+PFNGLWINDOWPOS4DMESAPROC glad_glWindowPos4dMESA = NULL;
+PFNGLWINDOWPOS4DVMESAPROC glad_glWindowPos4dvMESA = NULL;
+PFNGLWINDOWPOS4FMESAPROC glad_glWindowPos4fMESA = NULL;
+PFNGLWINDOWPOS4FVMESAPROC glad_glWindowPos4fvMESA = NULL;
+PFNGLWINDOWPOS4IMESAPROC glad_glWindowPos4iMESA = NULL;
+PFNGLWINDOWPOS4IVMESAPROC glad_glWindowPos4ivMESA = NULL;
+PFNGLWINDOWPOS4SMESAPROC glad_glWindowPos4sMESA = NULL;
+PFNGLWINDOWPOS4SVMESAPROC glad_glWindowPos4svMESA = NULL;
+PFNGLBEGINCONDITIONALRENDERNVXPROC glad_glBeginConditionalRenderNVX = NULL;
+PFNGLENDCONDITIONALRENDERNVXPROC glad_glEndConditionalRenderNVX = NULL;
+PFNGLLGPUNAMEDBUFFERSUBDATANVXPROC glad_glLGPUNamedBufferSubDataNVX = NULL;
+PFNGLLGPUCOPYIMAGESUBDATANVXPROC glad_glLGPUCopyImageSubDataNVX = NULL;
+PFNGLLGPUINTERLOCKNVXPROC glad_glLGPUInterlockNVX = NULL;
+PFNGLALPHATOCOVERAGEDITHERCONTROLNVPROC glad_glAlphaToCoverageDitherControlNV = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC glad_glMultiDrawArraysIndirectBindlessNV = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC glad_glMultiDrawElementsIndirectBindlessNV = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSCOUNTNVPROC glad_glMultiDrawArraysIndirectBindlessCountNV = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSCOUNTNVPROC glad_glMultiDrawElementsIndirectBindlessCountNV = NULL;
+PFNGLGETTEXTUREHANDLENVPROC glad_glGetTextureHandleNV = NULL;
+PFNGLGETTEXTURESAMPLERHANDLENVPROC glad_glGetTextureSamplerHandleNV = NULL;
+PFNGLMAKETEXTUREHANDLERESIDENTNVPROC glad_glMakeTextureHandleResidentNV = NULL;
+PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC glad_glMakeTextureHandleNonResidentNV = NULL;
+PFNGLGETIMAGEHANDLENVPROC glad_glGetImageHandleNV = NULL;
+PFNGLMAKEIMAGEHANDLERESIDENTNVPROC glad_glMakeImageHandleResidentNV = NULL;
+PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC glad_glMakeImageHandleNonResidentNV = NULL;
+PFNGLUNIFORMHANDLEUI64NVPROC glad_glUniformHandleui64NV = NULL;
+PFNGLUNIFORMHANDLEUI64VNVPROC glad_glUniformHandleui64vNV = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC glad_glProgramUniformHandleui64NV = NULL;
+PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC glad_glProgramUniformHandleui64vNV = NULL;
+PFNGLISTEXTUREHANDLERESIDENTNVPROC glad_glIsTextureHandleResidentNV = NULL;
+PFNGLISIMAGEHANDLERESIDENTNVPROC glad_glIsImageHandleResidentNV = NULL;
+PFNGLBLENDPARAMETERINVPROC glad_glBlendParameteriNV = NULL;
+PFNGLBLENDBARRIERNVPROC glad_glBlendBarrierNV = NULL;
+PFNGLVIEWPORTPOSITIONWSCALENVPROC glad_glViewportPositionWScaleNV = NULL;
+PFNGLCREATESTATESNVPROC glad_glCreateStatesNV = NULL;
+PFNGLDELETESTATESNVPROC glad_glDeleteStatesNV = NULL;
+PFNGLISSTATENVPROC glad_glIsStateNV = NULL;
+PFNGLSTATECAPTURENVPROC glad_glStateCaptureNV = NULL;
+PFNGLGETCOMMANDHEADERNVPROC glad_glGetCommandHeaderNV = NULL;
+PFNGLGETSTAGEINDEXNVPROC glad_glGetStageIndexNV = NULL;
+PFNGLDRAWCOMMANDSNVPROC glad_glDrawCommandsNV = NULL;
+PFNGLDRAWCOMMANDSADDRESSNVPROC glad_glDrawCommandsAddressNV = NULL;
+PFNGLDRAWCOMMANDSSTATESNVPROC glad_glDrawCommandsStatesNV = NULL;
+PFNGLDRAWCOMMANDSSTATESADDRESSNVPROC glad_glDrawCommandsStatesAddressNV = NULL;
+PFNGLCREATECOMMANDLISTSNVPROC glad_glCreateCommandListsNV = NULL;
+PFNGLDELETECOMMANDLISTSNVPROC glad_glDeleteCommandListsNV = NULL;
+PFNGLISCOMMANDLISTNVPROC glad_glIsCommandListNV = NULL;
+PFNGLLISTDRAWCOMMANDSSTATESCLIENTNVPROC glad_glListDrawCommandsStatesClientNV = NULL;
+PFNGLCOMMANDLISTSEGMENTSNVPROC glad_glCommandListSegmentsNV = NULL;
+PFNGLCOMPILECOMMANDLISTNVPROC glad_glCompileCommandListNV = NULL;
+PFNGLCALLCOMMANDLISTNVPROC glad_glCallCommandListNV = NULL;
+PFNGLBEGINCONDITIONALRENDERNVPROC glad_glBeginConditionalRenderNV = NULL;
+PFNGLENDCONDITIONALRENDERNVPROC glad_glEndConditionalRenderNV = NULL;
+PFNGLSUBPIXELPRECISIONBIASNVPROC glad_glSubpixelPrecisionBiasNV = NULL;
+PFNGLCONSERVATIVERASTERPARAMETERFNVPROC glad_glConservativeRasterParameterfNV = NULL;
+PFNGLCONSERVATIVERASTERPARAMETERINVPROC glad_glConservativeRasterParameteriNV = NULL;
+PFNGLCOPYIMAGESUBDATANVPROC glad_glCopyImageSubDataNV = NULL;
+PFNGLDEPTHRANGEDNVPROC glad_glDepthRangedNV = NULL;
+PFNGLCLEARDEPTHDNVPROC glad_glClearDepthdNV = NULL;
+PFNGLDEPTHBOUNDSDNVPROC glad_glDepthBoundsdNV = NULL;
+PFNGLDRAWTEXTURENVPROC glad_glDrawTextureNV = NULL;
+PFNGLDRAWVKIMAGENVPROC glad_glDrawVkImageNV = NULL;
+PFNGLGETVKPROCADDRNVPROC glad_glGetVkProcAddrNV = NULL;
+PFNGLWAITVKSEMAPHORENVPROC glad_glWaitVkSemaphoreNV = NULL;
+PFNGLSIGNALVKSEMAPHORENVPROC glad_glSignalVkSemaphoreNV = NULL;
+PFNGLSIGNALVKFENCENVPROC glad_glSignalVkFenceNV = NULL;
+PFNGLMAPCONTROLPOINTSNVPROC glad_glMapControlPointsNV = NULL;
+PFNGLMAPPARAMETERIVNVPROC glad_glMapParameterivNV = NULL;
+PFNGLMAPPARAMETERFVNVPROC glad_glMapParameterfvNV = NULL;
+PFNGLGETMAPCONTROLPOINTSNVPROC glad_glGetMapControlPointsNV = NULL;
+PFNGLGETMAPPARAMETERIVNVPROC glad_glGetMapParameterivNV = NULL;
+PFNGLGETMAPPARAMETERFVNVPROC glad_glGetMapParameterfvNV = NULL;
+PFNGLGETMAPATTRIBPARAMETERIVNVPROC glad_glGetMapAttribParameterivNV = NULL;
+PFNGLGETMAPATTRIBPARAMETERFVNVPROC glad_glGetMapAttribParameterfvNV = NULL;
+PFNGLEVALMAPSNVPROC glad_glEvalMapsNV = NULL;
+PFNGLGETMULTISAMPLEFVNVPROC glad_glGetMultisamplefvNV = NULL;
+PFNGLSAMPLEMASKINDEXEDNVPROC glad_glSampleMaskIndexedNV = NULL;
+PFNGLTEXRENDERBUFFERNVPROC glad_glTexRenderbufferNV = NULL;
+PFNGLDELETEFENCESNVPROC glad_glDeleteFencesNV = NULL;
+PFNGLGENFENCESNVPROC glad_glGenFencesNV = NULL;
+PFNGLISFENCENVPROC glad_glIsFenceNV = NULL;
+PFNGLTESTFENCENVPROC glad_glTestFenceNV = NULL;
+PFNGLGETFENCEIVNVPROC glad_glGetFenceivNV = NULL;
+PFNGLFINISHFENCENVPROC glad_glFinishFenceNV = NULL;
+PFNGLSETFENCENVPROC glad_glSetFenceNV = NULL;
+PFNGLFRAGMENTCOVERAGECOLORNVPROC glad_glFragmentCoverageColorNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4FNVPROC glad_glProgramNamedParameter4fNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC glad_glProgramNamedParameter4fvNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4DNVPROC glad_glProgramNamedParameter4dNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC glad_glProgramNamedParameter4dvNV = NULL;
+PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC glad_glGetProgramNamedParameterfvNV = NULL;
+PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC glad_glGetProgramNamedParameterdvNV = NULL;
+PFNGLCOVERAGEMODULATIONTABLENVPROC glad_glCoverageModulationTableNV = NULL;
+PFNGLGETCOVERAGEMODULATIONTABLENVPROC glad_glGetCoverageModulationTableNV = NULL;
+PFNGLCOVERAGEMODULATIONNVPROC glad_glCoverageModulationNV = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC glad_glRenderbufferStorageMultisampleCoverageNV = NULL;
+PFNGLPROGRAMVERTEXLIMITNVPROC glad_glProgramVertexLimitNV = NULL;
+PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC glad_glFramebufferTextureFaceEXT = NULL;
+PFNGLRENDERGPUMASKNVPROC glad_glRenderGpuMaskNV = NULL;
+PFNGLMULTICASTBUFFERSUBDATANVPROC glad_glMulticastBufferSubDataNV = NULL;
+PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC glad_glMulticastCopyBufferSubDataNV = NULL;
+PFNGLMULTICASTCOPYIMAGESUBDATANVPROC glad_glMulticastCopyImageSubDataNV = NULL;
+PFNGLMULTICASTBLITFRAMEBUFFERNVPROC glad_glMulticastBlitFramebufferNV = NULL;
+PFNGLMULTICASTFRAMEBUFFERSAMPLELOCATIONSFVNVPROC glad_glMulticastFramebufferSampleLocationsfvNV = NULL;
+PFNGLMULTICASTBARRIERNVPROC glad_glMulticastBarrierNV = NULL;
+PFNGLMULTICASTWAITSYNCNVPROC glad_glMulticastWaitSyncNV = NULL;
+PFNGLMULTICASTGETQUERYOBJECTIVNVPROC glad_glMulticastGetQueryObjectivNV = NULL;
+PFNGLMULTICASTGETQUERYOBJECTUIVNVPROC glad_glMulticastGetQueryObjectuivNV = NULL;
+PFNGLMULTICASTGETQUERYOBJECTI64VNVPROC glad_glMulticastGetQueryObjecti64vNV = NULL;
+PFNGLMULTICASTGETQUERYOBJECTUI64VNVPROC glad_glMulticastGetQueryObjectui64vNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4INVPROC glad_glProgramLocalParameterI4iNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC glad_glProgramLocalParameterI4ivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC glad_glProgramLocalParametersI4ivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4UINVPROC glad_glProgramLocalParameterI4uiNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC glad_glProgramLocalParameterI4uivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC glad_glProgramLocalParametersI4uivNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4INVPROC glad_glProgramEnvParameterI4iNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4IVNVPROC glad_glProgramEnvParameterI4ivNV = NULL;
+PFNGLPROGRAMENVPARAMETERSI4IVNVPROC glad_glProgramEnvParametersI4ivNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4UINVPROC glad_glProgramEnvParameterI4uiNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4UIVNVPROC glad_glProgramEnvParameterI4uivNV = NULL;
+PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC glad_glProgramEnvParametersI4uivNV = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC glad_glGetProgramLocalParameterIivNV = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC glad_glGetProgramLocalParameterIuivNV = NULL;
+PFNGLGETPROGRAMENVPARAMETERIIVNVPROC glad_glGetProgramEnvParameterIivNV = NULL;
+PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC glad_glGetProgramEnvParameterIuivNV = NULL;
+PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC glad_glProgramSubroutineParametersuivNV = NULL;
+PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC glad_glGetProgramSubroutineParameteruivNV = NULL;
+PFNGLVERTEX2HNVPROC glad_glVertex2hNV = NULL;
+PFNGLVERTEX2HVNVPROC glad_glVertex2hvNV = NULL;
+PFNGLVERTEX3HNVPROC glad_glVertex3hNV = NULL;
+PFNGLVERTEX3HVNVPROC glad_glVertex3hvNV = NULL;
+PFNGLVERTEX4HNVPROC glad_glVertex4hNV = NULL;
+PFNGLVERTEX4HVNVPROC glad_glVertex4hvNV = NULL;
+PFNGLNORMAL3HNVPROC glad_glNormal3hNV = NULL;
+PFNGLNORMAL3HVNVPROC glad_glNormal3hvNV = NULL;
+PFNGLCOLOR3HNVPROC glad_glColor3hNV = NULL;
+PFNGLCOLOR3HVNVPROC glad_glColor3hvNV = NULL;
+PFNGLCOLOR4HNVPROC glad_glColor4hNV = NULL;
+PFNGLCOLOR4HVNVPROC glad_glColor4hvNV = NULL;
+PFNGLTEXCOORD1HNVPROC glad_glTexCoord1hNV = NULL;
+PFNGLTEXCOORD1HVNVPROC glad_glTexCoord1hvNV = NULL;
+PFNGLTEXCOORD2HNVPROC glad_glTexCoord2hNV = NULL;
+PFNGLTEXCOORD2HVNVPROC glad_glTexCoord2hvNV = NULL;
+PFNGLTEXCOORD3HNVPROC glad_glTexCoord3hNV = NULL;
+PFNGLTEXCOORD3HVNVPROC glad_glTexCoord3hvNV = NULL;
+PFNGLTEXCOORD4HNVPROC glad_glTexCoord4hNV = NULL;
+PFNGLTEXCOORD4HVNVPROC glad_glTexCoord4hvNV = NULL;
+PFNGLMULTITEXCOORD1HNVPROC glad_glMultiTexCoord1hNV = NULL;
+PFNGLMULTITEXCOORD1HVNVPROC glad_glMultiTexCoord1hvNV = NULL;
+PFNGLMULTITEXCOORD2HNVPROC glad_glMultiTexCoord2hNV = NULL;
+PFNGLMULTITEXCOORD2HVNVPROC glad_glMultiTexCoord2hvNV = NULL;
+PFNGLMULTITEXCOORD3HNVPROC glad_glMultiTexCoord3hNV = NULL;
+PFNGLMULTITEXCOORD3HVNVPROC glad_glMultiTexCoord3hvNV = NULL;
+PFNGLMULTITEXCOORD4HNVPROC glad_glMultiTexCoord4hNV = NULL;
+PFNGLMULTITEXCOORD4HVNVPROC glad_glMultiTexCoord4hvNV = NULL;
+PFNGLFOGCOORDHNVPROC glad_glFogCoordhNV = NULL;
+PFNGLFOGCOORDHVNVPROC glad_glFogCoordhvNV = NULL;
+PFNGLSECONDARYCOLOR3HNVPROC glad_glSecondaryColor3hNV = NULL;
+PFNGLSECONDARYCOLOR3HVNVPROC glad_glSecondaryColor3hvNV = NULL;
+PFNGLVERTEXWEIGHTHNVPROC glad_glVertexWeighthNV = NULL;
+PFNGLVERTEXWEIGHTHVNVPROC glad_glVertexWeighthvNV = NULL;
+PFNGLVERTEXATTRIB1HNVPROC glad_glVertexAttrib1hNV = NULL;
+PFNGLVERTEXATTRIB1HVNVPROC glad_glVertexAttrib1hvNV = NULL;
+PFNGLVERTEXATTRIB2HNVPROC glad_glVertexAttrib2hNV = NULL;
+PFNGLVERTEXATTRIB2HVNVPROC glad_glVertexAttrib2hvNV = NULL;
+PFNGLVERTEXATTRIB3HNVPROC glad_glVertexAttrib3hNV = NULL;
+PFNGLVERTEXATTRIB3HVNVPROC glad_glVertexAttrib3hvNV = NULL;
+PFNGLVERTEXATTRIB4HNVPROC glad_glVertexAttrib4hNV = NULL;
+PFNGLVERTEXATTRIB4HVNVPROC glad_glVertexAttrib4hvNV = NULL;
+PFNGLVERTEXATTRIBS1HVNVPROC glad_glVertexAttribs1hvNV = NULL;
+PFNGLVERTEXATTRIBS2HVNVPROC glad_glVertexAttribs2hvNV = NULL;
+PFNGLVERTEXATTRIBS3HVNVPROC glad_glVertexAttribs3hvNV = NULL;
+PFNGLVERTEXATTRIBS4HVNVPROC glad_glVertexAttribs4hvNV = NULL;
+PFNGLGETINTERNALFORMATSAMPLEIVNVPROC glad_glGetInternalformatSampleivNV = NULL;
+PFNGLGENOCCLUSIONQUERIESNVPROC glad_glGenOcclusionQueriesNV = NULL;
+PFNGLDELETEOCCLUSIONQUERIESNVPROC glad_glDeleteOcclusionQueriesNV = NULL;
+PFNGLISOCCLUSIONQUERYNVPROC glad_glIsOcclusionQueryNV = NULL;
+PFNGLBEGINOCCLUSIONQUERYNVPROC glad_glBeginOcclusionQueryNV = NULL;
+PFNGLENDOCCLUSIONQUERYNVPROC glad_glEndOcclusionQueryNV = NULL;
+PFNGLGETOCCLUSIONQUERYIVNVPROC glad_glGetOcclusionQueryivNV = NULL;
+PFNGLGETOCCLUSIONQUERYUIVNVPROC glad_glGetOcclusionQueryuivNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC glad_glProgramBufferParametersfvNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC glad_glProgramBufferParametersIivNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC glad_glProgramBufferParametersIuivNV = NULL;
+PFNGLGENPATHSNVPROC glad_glGenPathsNV = NULL;
+PFNGLDELETEPATHSNVPROC glad_glDeletePathsNV = NULL;
+PFNGLISPATHNVPROC glad_glIsPathNV = NULL;
+PFNGLPATHCOMMANDSNVPROC glad_glPathCommandsNV = NULL;
+PFNGLPATHCOORDSNVPROC glad_glPathCoordsNV = NULL;
+PFNGLPATHSUBCOMMANDSNVPROC glad_glPathSubCommandsNV = NULL;
+PFNGLPATHSUBCOORDSNVPROC glad_glPathSubCoordsNV = NULL;
+PFNGLPATHSTRINGNVPROC glad_glPathStringNV = NULL;
+PFNGLPATHGLYPHSNVPROC glad_glPathGlyphsNV = NULL;
+PFNGLPATHGLYPHRANGENVPROC glad_glPathGlyphRangeNV = NULL;
+PFNGLWEIGHTPATHSNVPROC glad_glWeightPathsNV = NULL;
+PFNGLCOPYPATHNVPROC glad_glCopyPathNV = NULL;
+PFNGLINTERPOLATEPATHSNVPROC glad_glInterpolatePathsNV = NULL;
+PFNGLTRANSFORMPATHNVPROC glad_glTransformPathNV = NULL;
+PFNGLPATHPARAMETERIVNVPROC glad_glPathParameterivNV = NULL;
+PFNGLPATHPARAMETERINVPROC glad_glPathParameteriNV = NULL;
+PFNGLPATHPARAMETERFVNVPROC glad_glPathParameterfvNV = NULL;
+PFNGLPATHPARAMETERFNVPROC glad_glPathParameterfNV = NULL;
+PFNGLPATHDASHARRAYNVPROC glad_glPathDashArrayNV = NULL;
+PFNGLPATHSTENCILFUNCNVPROC glad_glPathStencilFuncNV = NULL;
+PFNGLPATHSTENCILDEPTHOFFSETNVPROC glad_glPathStencilDepthOffsetNV = NULL;
+PFNGLSTENCILFILLPATHNVPROC glad_glStencilFillPathNV = NULL;
+PFNGLSTENCILSTROKEPATHNVPROC glad_glStencilStrokePathNV = NULL;
+PFNGLSTENCILFILLPATHINSTANCEDNVPROC glad_glStencilFillPathInstancedNV = NULL;
+PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC glad_glStencilStrokePathInstancedNV = NULL;
+PFNGLPATHCOVERDEPTHFUNCNVPROC glad_glPathCoverDepthFuncNV = NULL;
+PFNGLCOVERFILLPATHNVPROC glad_glCoverFillPathNV = NULL;
+PFNGLCOVERSTROKEPATHNVPROC glad_glCoverStrokePathNV = NULL;
+PFNGLCOVERFILLPATHINSTANCEDNVPROC glad_glCoverFillPathInstancedNV = NULL;
+PFNGLCOVERSTROKEPATHINSTANCEDNVPROC glad_glCoverStrokePathInstancedNV = NULL;
+PFNGLGETPATHPARAMETERIVNVPROC glad_glGetPathParameterivNV = NULL;
+PFNGLGETPATHPARAMETERFVNVPROC glad_glGetPathParameterfvNV = NULL;
+PFNGLGETPATHCOMMANDSNVPROC glad_glGetPathCommandsNV = NULL;
+PFNGLGETPATHCOORDSNVPROC glad_glGetPathCoordsNV = NULL;
+PFNGLGETPATHDASHARRAYNVPROC glad_glGetPathDashArrayNV = NULL;
+PFNGLGETPATHMETRICSNVPROC glad_glGetPathMetricsNV = NULL;
+PFNGLGETPATHMETRICRANGENVPROC glad_glGetPathMetricRangeNV = NULL;
+PFNGLGETPATHSPACINGNVPROC glad_glGetPathSpacingNV = NULL;
+PFNGLISPOINTINFILLPATHNVPROC glad_glIsPointInFillPathNV = NULL;
+PFNGLISPOINTINSTROKEPATHNVPROC glad_glIsPointInStrokePathNV = NULL;
+PFNGLGETPATHLENGTHNVPROC glad_glGetPathLengthNV = NULL;
+PFNGLPOINTALONGPATHNVPROC glad_glPointAlongPathNV = NULL;
+PFNGLMATRIXLOAD3X2FNVPROC glad_glMatrixLoad3x2fNV = NULL;
+PFNGLMATRIXLOAD3X3FNVPROC glad_glMatrixLoad3x3fNV = NULL;
+PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC glad_glMatrixLoadTranspose3x3fNV = NULL;
+PFNGLMATRIXMULT3X2FNVPROC glad_glMatrixMult3x2fNV = NULL;
+PFNGLMATRIXMULT3X3FNVPROC glad_glMatrixMult3x3fNV = NULL;
+PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC glad_glMatrixMultTranspose3x3fNV = NULL;
+PFNGLSTENCILTHENCOVERFILLPATHNVPROC glad_glStencilThenCoverFillPathNV = NULL;
+PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC glad_glStencilThenCoverStrokePathNV = NULL;
+PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC glad_glStencilThenCoverFillPathInstancedNV = NULL;
+PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC glad_glStencilThenCoverStrokePathInstancedNV = NULL;
+PFNGLPATHGLYPHINDEXRANGENVPROC glad_glPathGlyphIndexRangeNV = NULL;
+PFNGLPATHGLYPHINDEXARRAYNVPROC glad_glPathGlyphIndexArrayNV = NULL;
+PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC glad_glPathMemoryGlyphIndexArrayNV = NULL;
+PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC glad_glProgramPathFragmentInputGenNV = NULL;
+PFNGLGETPROGRAMRESOURCEFVNVPROC glad_glGetProgramResourcefvNV = NULL;
+PFNGLPATHCOLORGENNVPROC glad_glPathColorGenNV = NULL;
+PFNGLPATHTEXGENNVPROC glad_glPathTexGenNV = NULL;
+PFNGLPATHFOGGENNVPROC glad_glPathFogGenNV = NULL;
+PFNGLGETPATHCOLORGENIVNVPROC glad_glGetPathColorGenivNV = NULL;
+PFNGLGETPATHCOLORGENFVNVPROC glad_glGetPathColorGenfvNV = NULL;
+PFNGLGETPATHTEXGENIVNVPROC glad_glGetPathTexGenivNV = NULL;
+PFNGLGETPATHTEXGENFVNVPROC glad_glGetPathTexGenfvNV = NULL;
+PFNGLPIXELDATARANGENVPROC glad_glPixelDataRangeNV = NULL;
+PFNGLFLUSHPIXELDATARANGENVPROC glad_glFlushPixelDataRangeNV = NULL;
+PFNGLPOINTPARAMETERINVPROC glad_glPointParameteriNV = NULL;
+PFNGLPOINTPARAMETERIVNVPROC glad_glPointParameterivNV = NULL;
+PFNGLPRESENTFRAMEKEYEDNVPROC glad_glPresentFrameKeyedNV = NULL;
+PFNGLPRESENTFRAMEDUALFILLNVPROC glad_glPresentFrameDualFillNV = NULL;
+PFNGLGETVIDEOIVNVPROC glad_glGetVideoivNV = NULL;
+PFNGLGETVIDEOUIVNVPROC glad_glGetVideouivNV = NULL;
+PFNGLGETVIDEOI64VNVPROC glad_glGetVideoi64vNV = NULL;
+PFNGLGETVIDEOUI64VNVPROC glad_glGetVideoui64vNV = NULL;
+PFNGLPRIMITIVERESTARTNVPROC glad_glPrimitiveRestartNV = NULL;
+PFNGLPRIMITIVERESTARTINDEXNVPROC glad_glPrimitiveRestartIndexNV = NULL;
+PFNGLQUERYRESOURCENVPROC glad_glQueryResourceNV = NULL;
+PFNGLGENQUERYRESOURCETAGNVPROC glad_glGenQueryResourceTagNV = NULL;
+PFNGLDELETEQUERYRESOURCETAGNVPROC glad_glDeleteQueryResourceTagNV = NULL;
+PFNGLQUERYRESOURCETAGNVPROC glad_glQueryResourceTagNV = NULL;
+PFNGLCOMBINERPARAMETERFVNVPROC glad_glCombinerParameterfvNV = NULL;
+PFNGLCOMBINERPARAMETERFNVPROC glad_glCombinerParameterfNV = NULL;
+PFNGLCOMBINERPARAMETERIVNVPROC glad_glCombinerParameterivNV = NULL;
+PFNGLCOMBINERPARAMETERINVPROC glad_glCombinerParameteriNV = NULL;
+PFNGLCOMBINERINPUTNVPROC glad_glCombinerInputNV = NULL;
+PFNGLCOMBINEROUTPUTNVPROC glad_glCombinerOutputNV = NULL;
+PFNGLFINALCOMBINERINPUTNVPROC glad_glFinalCombinerInputNV = NULL;
+PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC glad_glGetCombinerInputParameterfvNV = NULL;
+PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC glad_glGetCombinerInputParameterivNV = NULL;
+PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC glad_glGetCombinerOutputParameterfvNV = NULL;
+PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC glad_glGetCombinerOutputParameterivNV = NULL;
+PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC glad_glGetFinalCombinerInputParameterfvNV = NULL;
+PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC glad_glGetFinalCombinerInputParameterivNV = NULL;
+PFNGLCOMBINERSTAGEPARAMETERFVNVPROC glad_glCombinerStageParameterfvNV = NULL;
+PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC glad_glGetCombinerStageParameterfvNV = NULL;
+PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC glad_glFramebufferSampleLocationsfvNV = NULL;
+PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC glad_glNamedFramebufferSampleLocationsfvNV = NULL;
+PFNGLRESOLVEDEPTHVALUESNVPROC glad_glResolveDepthValuesNV = NULL;
+PFNGLMAKEBUFFERRESIDENTNVPROC glad_glMakeBufferResidentNV = NULL;
+PFNGLMAKEBUFFERNONRESIDENTNVPROC glad_glMakeBufferNonResidentNV = NULL;
+PFNGLISBUFFERRESIDENTNVPROC glad_glIsBufferResidentNV = NULL;
+PFNGLMAKENAMEDBUFFERRESIDENTNVPROC glad_glMakeNamedBufferResidentNV = NULL;
+PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC glad_glMakeNamedBufferNonResidentNV = NULL;
+PFNGLISNAMEDBUFFERRESIDENTNVPROC glad_glIsNamedBufferResidentNV = NULL;
+PFNGLGETBUFFERPARAMETERUI64VNVPROC glad_glGetBufferParameterui64vNV = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC glad_glGetNamedBufferParameterui64vNV = NULL;
+PFNGLGETINTEGERUI64VNVPROC glad_glGetIntegerui64vNV = NULL;
+PFNGLUNIFORMUI64NVPROC glad_glUniformui64NV = NULL;
+PFNGLUNIFORMUI64VNVPROC glad_glUniformui64vNV = NULL;
+PFNGLPROGRAMUNIFORMUI64NVPROC glad_glProgramUniformui64NV = NULL;
+PFNGLPROGRAMUNIFORMUI64VNVPROC glad_glProgramUniformui64vNV = NULL;
+PFNGLTEXTUREBARRIERNVPROC glad_glTextureBarrierNV = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC glad_glTexImage2DMultisampleCoverageNV = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC glad_glTexImage3DMultisampleCoverageNV = NULL;
+PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC glad_glTextureImage2DMultisampleNV = NULL;
+PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC glad_glTextureImage3DMultisampleNV = NULL;
+PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC glad_glTextureImage2DMultisampleCoverageNV = NULL;
+PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC glad_glTextureImage3DMultisampleCoverageNV = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKNVPROC glad_glBeginTransformFeedbackNV = NULL;
+PFNGLENDTRANSFORMFEEDBACKNVPROC glad_glEndTransformFeedbackNV = NULL;
+PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC glad_glTransformFeedbackAttribsNV = NULL;
+PFNGLBINDBUFFERRANGENVPROC glad_glBindBufferRangeNV = NULL;
+PFNGLBINDBUFFEROFFSETNVPROC glad_glBindBufferOffsetNV = NULL;
+PFNGLBINDBUFFERBASENVPROC glad_glBindBufferBaseNV = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC glad_glTransformFeedbackVaryingsNV = NULL;
+PFNGLACTIVEVARYINGNVPROC glad_glActiveVaryingNV = NULL;
+PFNGLGETVARYINGLOCATIONNVPROC glad_glGetVaryingLocationNV = NULL;
+PFNGLGETACTIVEVARYINGNVPROC glad_glGetActiveVaryingNV = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC glad_glGetTransformFeedbackVaryingNV = NULL;
+PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC glad_glTransformFeedbackStreamAttribsNV = NULL;
+PFNGLBINDTRANSFORMFEEDBACKNVPROC glad_glBindTransformFeedbackNV = NULL;
+PFNGLDELETETRANSFORMFEEDBACKSNVPROC glad_glDeleteTransformFeedbacksNV = NULL;
+PFNGLGENTRANSFORMFEEDBACKSNVPROC glad_glGenTransformFeedbacksNV = NULL;
+PFNGLISTRANSFORMFEEDBACKNVPROC glad_glIsTransformFeedbackNV = NULL;
+PFNGLPAUSETRANSFORMFEEDBACKNVPROC glad_glPauseTransformFeedbackNV = NULL;
+PFNGLRESUMETRANSFORMFEEDBACKNVPROC glad_glResumeTransformFeedbackNV = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKNVPROC glad_glDrawTransformFeedbackNV = NULL;
+PFNGLVDPAUINITNVPROC glad_glVDPAUInitNV = NULL;
+PFNGLVDPAUFININVPROC glad_glVDPAUFiniNV = NULL;
+PFNGLVDPAUREGISTERVIDEOSURFACENVPROC glad_glVDPAURegisterVideoSurfaceNV = NULL;
+PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC glad_glVDPAURegisterOutputSurfaceNV = NULL;
+PFNGLVDPAUISSURFACENVPROC glad_glVDPAUIsSurfaceNV = NULL;
+PFNGLVDPAUUNREGISTERSURFACENVPROC glad_glVDPAUUnregisterSurfaceNV = NULL;
+PFNGLVDPAUGETSURFACEIVNVPROC glad_glVDPAUGetSurfaceivNV = NULL;
+PFNGLVDPAUSURFACEACCESSNVPROC glad_glVDPAUSurfaceAccessNV = NULL;
+PFNGLVDPAUMAPSURFACESNVPROC glad_glVDPAUMapSurfacesNV = NULL;
+PFNGLVDPAUUNMAPSURFACESNVPROC glad_glVDPAUUnmapSurfacesNV = NULL;
+PFNGLFLUSHVERTEXARRAYRANGENVPROC glad_glFlushVertexArrayRangeNV = NULL;
+PFNGLVERTEXARRAYRANGENVPROC glad_glVertexArrayRangeNV = NULL;
+PFNGLVERTEXATTRIBL1I64NVPROC glad_glVertexAttribL1i64NV = NULL;
+PFNGLVERTEXATTRIBL2I64NVPROC glad_glVertexAttribL2i64NV = NULL;
+PFNGLVERTEXATTRIBL3I64NVPROC glad_glVertexAttribL3i64NV = NULL;
+PFNGLVERTEXATTRIBL4I64NVPROC glad_glVertexAttribL4i64NV = NULL;
+PFNGLVERTEXATTRIBL1I64VNVPROC glad_glVertexAttribL1i64vNV = NULL;
+PFNGLVERTEXATTRIBL2I64VNVPROC glad_glVertexAttribL2i64vNV = NULL;
+PFNGLVERTEXATTRIBL3I64VNVPROC glad_glVertexAttribL3i64vNV = NULL;
+PFNGLVERTEXATTRIBL4I64VNVPROC glad_glVertexAttribL4i64vNV = NULL;
+PFNGLVERTEXATTRIBL1UI64NVPROC glad_glVertexAttribL1ui64NV = NULL;
+PFNGLVERTEXATTRIBL2UI64NVPROC glad_glVertexAttribL2ui64NV = NULL;
+PFNGLVERTEXATTRIBL3UI64NVPROC glad_glVertexAttribL3ui64NV = NULL;
+PFNGLVERTEXATTRIBL4UI64NVPROC glad_glVertexAttribL4ui64NV = NULL;
+PFNGLVERTEXATTRIBL1UI64VNVPROC glad_glVertexAttribL1ui64vNV = NULL;
+PFNGLVERTEXATTRIBL2UI64VNVPROC glad_glVertexAttribL2ui64vNV = NULL;
+PFNGLVERTEXATTRIBL3UI64VNVPROC glad_glVertexAttribL3ui64vNV = NULL;
+PFNGLVERTEXATTRIBL4UI64VNVPROC glad_glVertexAttribL4ui64vNV = NULL;
+PFNGLGETVERTEXATTRIBLI64VNVPROC glad_glGetVertexAttribLi64vNV = NULL;
+PFNGLGETVERTEXATTRIBLUI64VNVPROC glad_glGetVertexAttribLui64vNV = NULL;
+PFNGLVERTEXATTRIBLFORMATNVPROC glad_glVertexAttribLFormatNV = NULL;
+PFNGLBUFFERADDRESSRANGENVPROC glad_glBufferAddressRangeNV = NULL;
+PFNGLVERTEXFORMATNVPROC glad_glVertexFormatNV = NULL;
+PFNGLNORMALFORMATNVPROC glad_glNormalFormatNV = NULL;
+PFNGLCOLORFORMATNVPROC glad_glColorFormatNV = NULL;
+PFNGLINDEXFORMATNVPROC glad_glIndexFormatNV = NULL;
+PFNGLTEXCOORDFORMATNVPROC glad_glTexCoordFormatNV = NULL;
+PFNGLEDGEFLAGFORMATNVPROC glad_glEdgeFlagFormatNV = NULL;
+PFNGLSECONDARYCOLORFORMATNVPROC glad_glSecondaryColorFormatNV = NULL;
+PFNGLFOGCOORDFORMATNVPROC glad_glFogCoordFormatNV = NULL;
+PFNGLVERTEXATTRIBFORMATNVPROC glad_glVertexAttribFormatNV = NULL;
+PFNGLVERTEXATTRIBIFORMATNVPROC glad_glVertexAttribIFormatNV = NULL;
+PFNGLGETINTEGERUI64I_VNVPROC glad_glGetIntegerui64i_vNV = NULL;
+PFNGLAREPROGRAMSRESIDENTNVPROC glad_glAreProgramsResidentNV = NULL;
+PFNGLBINDPROGRAMNVPROC glad_glBindProgramNV = NULL;
+PFNGLDELETEPROGRAMSNVPROC glad_glDeleteProgramsNV = NULL;
+PFNGLEXECUTEPROGRAMNVPROC glad_glExecuteProgramNV = NULL;
+PFNGLGENPROGRAMSNVPROC glad_glGenProgramsNV = NULL;
+PFNGLGETPROGRAMPARAMETERDVNVPROC glad_glGetProgramParameterdvNV = NULL;
+PFNGLGETPROGRAMPARAMETERFVNVPROC glad_glGetProgramParameterfvNV = NULL;
+PFNGLGETPROGRAMIVNVPROC glad_glGetProgramivNV = NULL;
+PFNGLGETPROGRAMSTRINGNVPROC glad_glGetProgramStringNV = NULL;
+PFNGLGETTRACKMATRIXIVNVPROC glad_glGetTrackMatrixivNV = NULL;
+PFNGLGETVERTEXATTRIBDVNVPROC glad_glGetVertexAttribdvNV = NULL;
+PFNGLGETVERTEXATTRIBFVNVPROC glad_glGetVertexAttribfvNV = NULL;
+PFNGLGETVERTEXATTRIBIVNVPROC glad_glGetVertexAttribivNV = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVNVPROC glad_glGetVertexAttribPointervNV = NULL;
+PFNGLISPROGRAMNVPROC glad_glIsProgramNV = NULL;
+PFNGLLOADPROGRAMNVPROC glad_glLoadProgramNV = NULL;
+PFNGLPROGRAMPARAMETER4DNVPROC glad_glProgramParameter4dNV = NULL;
+PFNGLPROGRAMPARAMETER4DVNVPROC glad_glProgramParameter4dvNV = NULL;
+PFNGLPROGRAMPARAMETER4FNVPROC glad_glProgramParameter4fNV = NULL;
+PFNGLPROGRAMPARAMETER4FVNVPROC glad_glProgramParameter4fvNV = NULL;
+PFNGLPROGRAMPARAMETERS4DVNVPROC glad_glProgramParameters4dvNV = NULL;
+PFNGLPROGRAMPARAMETERS4FVNVPROC glad_glProgramParameters4fvNV = NULL;
+PFNGLREQUESTRESIDENTPROGRAMSNVPROC glad_glRequestResidentProgramsNV = NULL;
+PFNGLTRACKMATRIXNVPROC glad_glTrackMatrixNV = NULL;
+PFNGLVERTEXATTRIBPOINTERNVPROC glad_glVertexAttribPointerNV = NULL;
+PFNGLVERTEXATTRIB1DNVPROC glad_glVertexAttrib1dNV = NULL;
+PFNGLVERTEXATTRIB1DVNVPROC glad_glVertexAttrib1dvNV = NULL;
+PFNGLVERTEXATTRIB1FNVPROC glad_glVertexAttrib1fNV = NULL;
+PFNGLVERTEXATTRIB1FVNVPROC glad_glVertexAttrib1fvNV = NULL;
+PFNGLVERTEXATTRIB1SNVPROC glad_glVertexAttrib1sNV = NULL;
+PFNGLVERTEXATTRIB1SVNVPROC glad_glVertexAttrib1svNV = NULL;
+PFNGLVERTEXATTRIB2DNVPROC glad_glVertexAttrib2dNV = NULL;
+PFNGLVERTEXATTRIB2DVNVPROC glad_glVertexAttrib2dvNV = NULL;
+PFNGLVERTEXATTRIB2FNVPROC glad_glVertexAttrib2fNV = NULL;
+PFNGLVERTEXATTRIB2FVNVPROC glad_glVertexAttrib2fvNV = NULL;
+PFNGLVERTEXATTRIB2SNVPROC glad_glVertexAttrib2sNV = NULL;
+PFNGLVERTEXATTRIB2SVNVPROC glad_glVertexAttrib2svNV = NULL;
+PFNGLVERTEXATTRIB3DNVPROC glad_glVertexAttrib3dNV = NULL;
+PFNGLVERTEXATTRIB3DVNVPROC glad_glVertexAttrib3dvNV = NULL;
+PFNGLVERTEXATTRIB3FNVPROC glad_glVertexAttrib3fNV = NULL;
+PFNGLVERTEXATTRIB3FVNVPROC glad_glVertexAttrib3fvNV = NULL;
+PFNGLVERTEXATTRIB3SNVPROC glad_glVertexAttrib3sNV = NULL;
+PFNGLVERTEXATTRIB3SVNVPROC glad_glVertexAttrib3svNV = NULL;
+PFNGLVERTEXATTRIB4DNVPROC glad_glVertexAttrib4dNV = NULL;
+PFNGLVERTEXATTRIB4DVNVPROC glad_glVertexAttrib4dvNV = NULL;
+PFNGLVERTEXATTRIB4FNVPROC glad_glVertexAttrib4fNV = NULL;
+PFNGLVERTEXATTRIB4FVNVPROC glad_glVertexAttrib4fvNV = NULL;
+PFNGLVERTEXATTRIB4SNVPROC glad_glVertexAttrib4sNV = NULL;
+PFNGLVERTEXATTRIB4SVNVPROC glad_glVertexAttrib4svNV = NULL;
+PFNGLVERTEXATTRIB4UBNVPROC glad_glVertexAttrib4ubNV = NULL;
+PFNGLVERTEXATTRIB4UBVNVPROC glad_glVertexAttrib4ubvNV = NULL;
+PFNGLVERTEXATTRIBS1DVNVPROC glad_glVertexAttribs1dvNV = NULL;
+PFNGLVERTEXATTRIBS1FVNVPROC glad_glVertexAttribs1fvNV = NULL;
+PFNGLVERTEXATTRIBS1SVNVPROC glad_glVertexAttribs1svNV = NULL;
+PFNGLVERTEXATTRIBS2DVNVPROC glad_glVertexAttribs2dvNV = NULL;
+PFNGLVERTEXATTRIBS2FVNVPROC glad_glVertexAttribs2fvNV = NULL;
+PFNGLVERTEXATTRIBS2SVNVPROC glad_glVertexAttribs2svNV = NULL;
+PFNGLVERTEXATTRIBS3DVNVPROC glad_glVertexAttribs3dvNV = NULL;
+PFNGLVERTEXATTRIBS3FVNVPROC glad_glVertexAttribs3fvNV = NULL;
+PFNGLVERTEXATTRIBS3SVNVPROC glad_glVertexAttribs3svNV = NULL;
+PFNGLVERTEXATTRIBS4DVNVPROC glad_glVertexAttribs4dvNV = NULL;
+PFNGLVERTEXATTRIBS4FVNVPROC glad_glVertexAttribs4fvNV = NULL;
+PFNGLVERTEXATTRIBS4SVNVPROC glad_glVertexAttribs4svNV = NULL;
+PFNGLVERTEXATTRIBS4UBVNVPROC glad_glVertexAttribs4ubvNV = NULL;
+PFNGLVERTEXATTRIBI1IEXTPROC glad_glVertexAttribI1iEXT = NULL;
+PFNGLVERTEXATTRIBI2IEXTPROC glad_glVertexAttribI2iEXT = NULL;
+PFNGLVERTEXATTRIBI3IEXTPROC glad_glVertexAttribI3iEXT = NULL;
+PFNGLVERTEXATTRIBI4IEXTPROC glad_glVertexAttribI4iEXT = NULL;
+PFNGLVERTEXATTRIBI1UIEXTPROC glad_glVertexAttribI1uiEXT = NULL;
+PFNGLVERTEXATTRIBI2UIEXTPROC glad_glVertexAttribI2uiEXT = NULL;
+PFNGLVERTEXATTRIBI3UIEXTPROC glad_glVertexAttribI3uiEXT = NULL;
+PFNGLVERTEXATTRIBI4UIEXTPROC glad_glVertexAttribI4uiEXT = NULL;
+PFNGLVERTEXATTRIBI1IVEXTPROC glad_glVertexAttribI1ivEXT = NULL;
+PFNGLVERTEXATTRIBI2IVEXTPROC glad_glVertexAttribI2ivEXT = NULL;
+PFNGLVERTEXATTRIBI3IVEXTPROC glad_glVertexAttribI3ivEXT = NULL;
+PFNGLVERTEXATTRIBI4IVEXTPROC glad_glVertexAttribI4ivEXT = NULL;
+PFNGLVERTEXATTRIBI1UIVEXTPROC glad_glVertexAttribI1uivEXT = NULL;
+PFNGLVERTEXATTRIBI2UIVEXTPROC glad_glVertexAttribI2uivEXT = NULL;
+PFNGLVERTEXATTRIBI3UIVEXTPROC glad_glVertexAttribI3uivEXT = NULL;
+PFNGLVERTEXATTRIBI4UIVEXTPROC glad_glVertexAttribI4uivEXT = NULL;
+PFNGLVERTEXATTRIBI4BVEXTPROC glad_glVertexAttribI4bvEXT = NULL;
+PFNGLVERTEXATTRIBI4SVEXTPROC glad_glVertexAttribI4svEXT = NULL;
+PFNGLVERTEXATTRIBI4UBVEXTPROC glad_glVertexAttribI4ubvEXT = NULL;
+PFNGLVERTEXATTRIBI4USVEXTPROC glad_glVertexAttribI4usvEXT = NULL;
+PFNGLVERTEXATTRIBIPOINTEREXTPROC glad_glVertexAttribIPointerEXT = NULL;
+PFNGLGETVERTEXATTRIBIIVEXTPROC glad_glGetVertexAttribIivEXT = NULL;
+PFNGLGETVERTEXATTRIBIUIVEXTPROC glad_glGetVertexAttribIuivEXT = NULL;
+PFNGLBEGINVIDEOCAPTURENVPROC glad_glBeginVideoCaptureNV = NULL;
+PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC glad_glBindVideoCaptureStreamBufferNV = NULL;
+PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC glad_glBindVideoCaptureStreamTextureNV = NULL;
+PFNGLENDVIDEOCAPTURENVPROC glad_glEndVideoCaptureNV = NULL;
+PFNGLGETVIDEOCAPTUREIVNVPROC glad_glGetVideoCaptureivNV = NULL;
+PFNGLGETVIDEOCAPTURESTREAMIVNVPROC glad_glGetVideoCaptureStreamivNV = NULL;
+PFNGLGETVIDEOCAPTURESTREAMFVNVPROC glad_glGetVideoCaptureStreamfvNV = NULL;
+PFNGLGETVIDEOCAPTURESTREAMDVNVPROC glad_glGetVideoCaptureStreamdvNV = NULL;
+PFNGLVIDEOCAPTURENVPROC glad_glVideoCaptureNV = NULL;
+PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC glad_glVideoCaptureStreamParameterivNV = NULL;
+PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC glad_glVideoCaptureStreamParameterfvNV = NULL;
+PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC glad_glVideoCaptureStreamParameterdvNV = NULL;
+PFNGLVIEWPORTSWIZZLENVPROC glad_glViewportSwizzleNV = NULL;
+PFNGLMULTITEXCOORD1BOESPROC glad_glMultiTexCoord1bOES = NULL;
+PFNGLMULTITEXCOORD1BVOESPROC glad_glMultiTexCoord1bvOES = NULL;
+PFNGLMULTITEXCOORD2BOESPROC glad_glMultiTexCoord2bOES = NULL;
+PFNGLMULTITEXCOORD2BVOESPROC glad_glMultiTexCoord2bvOES = NULL;
+PFNGLMULTITEXCOORD3BOESPROC glad_glMultiTexCoord3bOES = NULL;
+PFNGLMULTITEXCOORD3BVOESPROC glad_glMultiTexCoord3bvOES = NULL;
+PFNGLMULTITEXCOORD4BOESPROC glad_glMultiTexCoord4bOES = NULL;
+PFNGLMULTITEXCOORD4BVOESPROC glad_glMultiTexCoord4bvOES = NULL;
+PFNGLTEXCOORD1BOESPROC glad_glTexCoord1bOES = NULL;
+PFNGLTEXCOORD1BVOESPROC glad_glTexCoord1bvOES = NULL;
+PFNGLTEXCOORD2BOESPROC glad_glTexCoord2bOES = NULL;
+PFNGLTEXCOORD2BVOESPROC glad_glTexCoord2bvOES = NULL;
+PFNGLTEXCOORD3BOESPROC glad_glTexCoord3bOES = NULL;
+PFNGLTEXCOORD3BVOESPROC glad_glTexCoord3bvOES = NULL;
+PFNGLTEXCOORD4BOESPROC glad_glTexCoord4bOES = NULL;
+PFNGLTEXCOORD4BVOESPROC glad_glTexCoord4bvOES = NULL;
+PFNGLVERTEX2BOESPROC glad_glVertex2bOES = NULL;
+PFNGLVERTEX2BVOESPROC glad_glVertex2bvOES = NULL;
+PFNGLVERTEX3BOESPROC glad_glVertex3bOES = NULL;
+PFNGLVERTEX3BVOESPROC glad_glVertex3bvOES = NULL;
+PFNGLVERTEX4BOESPROC glad_glVertex4bOES = NULL;
+PFNGLVERTEX4BVOESPROC glad_glVertex4bvOES = NULL;
+PFNGLALPHAFUNCXOESPROC glad_glAlphaFuncxOES = NULL;
+PFNGLCLEARCOLORXOESPROC glad_glClearColorxOES = NULL;
+PFNGLCLEARDEPTHXOESPROC glad_glClearDepthxOES = NULL;
+PFNGLCLIPPLANEXOESPROC glad_glClipPlanexOES = NULL;
+PFNGLCOLOR4XOESPROC glad_glColor4xOES = NULL;
+PFNGLDEPTHRANGEXOESPROC glad_glDepthRangexOES = NULL;
+PFNGLFOGXOESPROC glad_glFogxOES = NULL;
+PFNGLFOGXVOESPROC glad_glFogxvOES = NULL;
+PFNGLFRUSTUMXOESPROC glad_glFrustumxOES = NULL;
+PFNGLGETCLIPPLANEXOESPROC glad_glGetClipPlanexOES = NULL;
+PFNGLGETFIXEDVOESPROC glad_glGetFixedvOES = NULL;
+PFNGLGETTEXENVXVOESPROC glad_glGetTexEnvxvOES = NULL;
+PFNGLGETTEXPARAMETERXVOESPROC glad_glGetTexParameterxvOES = NULL;
+PFNGLLIGHTMODELXOESPROC glad_glLightModelxOES = NULL;
+PFNGLLIGHTMODELXVOESPROC glad_glLightModelxvOES = NULL;
+PFNGLLIGHTXOESPROC glad_glLightxOES = NULL;
+PFNGLLIGHTXVOESPROC glad_glLightxvOES = NULL;
+PFNGLLINEWIDTHXOESPROC glad_glLineWidthxOES = NULL;
+PFNGLLOADMATRIXXOESPROC glad_glLoadMatrixxOES = NULL;
+PFNGLMATERIALXOESPROC glad_glMaterialxOES = NULL;
+PFNGLMATERIALXVOESPROC glad_glMaterialxvOES = NULL;
+PFNGLMULTMATRIXXOESPROC glad_glMultMatrixxOES = NULL;
+PFNGLMULTITEXCOORD4XOESPROC glad_glMultiTexCoord4xOES = NULL;
+PFNGLNORMAL3XOESPROC glad_glNormal3xOES = NULL;
+PFNGLORTHOXOESPROC glad_glOrthoxOES = NULL;
+PFNGLPOINTPARAMETERXVOESPROC glad_glPointParameterxvOES = NULL;
+PFNGLPOINTSIZEXOESPROC glad_glPointSizexOES = NULL;
+PFNGLPOLYGONOFFSETXOESPROC glad_glPolygonOffsetxOES = NULL;
+PFNGLROTATEXOESPROC glad_glRotatexOES = NULL;
+PFNGLSCALEXOESPROC glad_glScalexOES = NULL;
+PFNGLTEXENVXOESPROC glad_glTexEnvxOES = NULL;
+PFNGLTEXENVXVOESPROC glad_glTexEnvxvOES = NULL;
+PFNGLTEXPARAMETERXOESPROC glad_glTexParameterxOES = NULL;
+PFNGLTEXPARAMETERXVOESPROC glad_glTexParameterxvOES = NULL;
+PFNGLTRANSLATEXOESPROC glad_glTranslatexOES = NULL;
+PFNGLGETLIGHTXVOESPROC glad_glGetLightxvOES = NULL;
+PFNGLGETMATERIALXVOESPROC glad_glGetMaterialxvOES = NULL;
+PFNGLPOINTPARAMETERXOESPROC glad_glPointParameterxOES = NULL;
+PFNGLSAMPLECOVERAGEXOESPROC glad_glSampleCoveragexOES = NULL;
+PFNGLACCUMXOESPROC glad_glAccumxOES = NULL;
+PFNGLBITMAPXOESPROC glad_glBitmapxOES = NULL;
+PFNGLBLENDCOLORXOESPROC glad_glBlendColorxOES = NULL;
+PFNGLCLEARACCUMXOESPROC glad_glClearAccumxOES = NULL;
+PFNGLCOLOR3XOESPROC glad_glColor3xOES = NULL;
+PFNGLCOLOR3XVOESPROC glad_glColor3xvOES = NULL;
+PFNGLCOLOR4XVOESPROC glad_glColor4xvOES = NULL;
+PFNGLCONVOLUTIONPARAMETERXOESPROC glad_glConvolutionParameterxOES = NULL;
+PFNGLCONVOLUTIONPARAMETERXVOESPROC glad_glConvolutionParameterxvOES = NULL;
+PFNGLEVALCOORD1XOESPROC glad_glEvalCoord1xOES = NULL;
+PFNGLEVALCOORD1XVOESPROC glad_glEvalCoord1xvOES = NULL;
+PFNGLEVALCOORD2XOESPROC glad_glEvalCoord2xOES = NULL;
+PFNGLEVALCOORD2XVOESPROC glad_glEvalCoord2xvOES = NULL;
+PFNGLFEEDBACKBUFFERXOESPROC glad_glFeedbackBufferxOES = NULL;
+PFNGLGETCONVOLUTIONPARAMETERXVOESPROC glad_glGetConvolutionParameterxvOES = NULL;
+PFNGLGETHISTOGRAMPARAMETERXVOESPROC glad_glGetHistogramParameterxvOES = NULL;
+PFNGLGETLIGHTXOESPROC glad_glGetLightxOES = NULL;
+PFNGLGETMAPXVOESPROC glad_glGetMapxvOES = NULL;
+PFNGLGETMATERIALXOESPROC glad_glGetMaterialxOES = NULL;
+PFNGLGETPIXELMAPXVPROC glad_glGetPixelMapxv = NULL;
+PFNGLGETTEXGENXVOESPROC glad_glGetTexGenxvOES = NULL;
+PFNGLGETTEXLEVELPARAMETERXVOESPROC glad_glGetTexLevelParameterxvOES = NULL;
+PFNGLINDEXXOESPROC glad_glIndexxOES = NULL;
+PFNGLINDEXXVOESPROC glad_glIndexxvOES = NULL;
+PFNGLLOADTRANSPOSEMATRIXXOESPROC glad_glLoadTransposeMatrixxOES = NULL;
+PFNGLMAP1XOESPROC glad_glMap1xOES = NULL;
+PFNGLMAP2XOESPROC glad_glMap2xOES = NULL;
+PFNGLMAPGRID1XOESPROC glad_glMapGrid1xOES = NULL;
+PFNGLMAPGRID2XOESPROC glad_glMapGrid2xOES = NULL;
+PFNGLMULTTRANSPOSEMATRIXXOESPROC glad_glMultTransposeMatrixxOES = NULL;
+PFNGLMULTITEXCOORD1XOESPROC glad_glMultiTexCoord1xOES = NULL;
+PFNGLMULTITEXCOORD1XVOESPROC glad_glMultiTexCoord1xvOES = NULL;
+PFNGLMULTITEXCOORD2XOESPROC glad_glMultiTexCoord2xOES = NULL;
+PFNGLMULTITEXCOORD2XVOESPROC glad_glMultiTexCoord2xvOES = NULL;
+PFNGLMULTITEXCOORD3XOESPROC glad_glMultiTexCoord3xOES = NULL;
+PFNGLMULTITEXCOORD3XVOESPROC glad_glMultiTexCoord3xvOES = NULL;
+PFNGLMULTITEXCOORD4XVOESPROC glad_glMultiTexCoord4xvOES = NULL;
+PFNGLNORMAL3XVOESPROC glad_glNormal3xvOES = NULL;
+PFNGLPASSTHROUGHXOESPROC glad_glPassThroughxOES = NULL;
+PFNGLPIXELMAPXPROC glad_glPixelMapx = NULL;
+PFNGLPIXELSTOREXPROC glad_glPixelStorex = NULL;
+PFNGLPIXELTRANSFERXOESPROC glad_glPixelTransferxOES = NULL;
+PFNGLPIXELZOOMXOESPROC glad_glPixelZoomxOES = NULL;
+PFNGLPRIORITIZETEXTURESXOESPROC glad_glPrioritizeTexturesxOES = NULL;
+PFNGLRASTERPOS2XOESPROC glad_glRasterPos2xOES = NULL;
+PFNGLRASTERPOS2XVOESPROC glad_glRasterPos2xvOES = NULL;
+PFNGLRASTERPOS3XOESPROC glad_glRasterPos3xOES = NULL;
+PFNGLRASTERPOS3XVOESPROC glad_glRasterPos3xvOES = NULL;
+PFNGLRASTERPOS4XOESPROC glad_glRasterPos4xOES = NULL;
+PFNGLRASTERPOS4XVOESPROC glad_glRasterPos4xvOES = NULL;
+PFNGLRECTXOESPROC glad_glRectxOES = NULL;
+PFNGLRECTXVOESPROC glad_glRectxvOES = NULL;
+PFNGLTEXCOORD1XOESPROC glad_glTexCoord1xOES = NULL;
+PFNGLTEXCOORD1XVOESPROC glad_glTexCoord1xvOES = NULL;
+PFNGLTEXCOORD2XOESPROC glad_glTexCoord2xOES = NULL;
+PFNGLTEXCOORD2XVOESPROC glad_glTexCoord2xvOES = NULL;
+PFNGLTEXCOORD3XOESPROC glad_glTexCoord3xOES = NULL;
+PFNGLTEXCOORD3XVOESPROC glad_glTexCoord3xvOES = NULL;
+PFNGLTEXCOORD4XOESPROC glad_glTexCoord4xOES = NULL;
+PFNGLTEXCOORD4XVOESPROC glad_glTexCoord4xvOES = NULL;
+PFNGLTEXGENXOESPROC glad_glTexGenxOES = NULL;
+PFNGLTEXGENXVOESPROC glad_glTexGenxvOES = NULL;
+PFNGLVERTEX2XOESPROC glad_glVertex2xOES = NULL;
+PFNGLVERTEX2XVOESPROC glad_glVertex2xvOES = NULL;
+PFNGLVERTEX3XOESPROC glad_glVertex3xOES = NULL;
+PFNGLVERTEX3XVOESPROC glad_glVertex3xvOES = NULL;
+PFNGLVERTEX4XOESPROC glad_glVertex4xOES = NULL;
+PFNGLVERTEX4XVOESPROC glad_glVertex4xvOES = NULL;
+PFNGLQUERYMATRIXXOESPROC glad_glQueryMatrixxOES = NULL;
+PFNGLCLEARDEPTHFOESPROC glad_glClearDepthfOES = NULL;
+PFNGLCLIPPLANEFOESPROC glad_glClipPlanefOES = NULL;
+PFNGLDEPTHRANGEFOESPROC glad_glDepthRangefOES = NULL;
+PFNGLFRUSTUMFOESPROC glad_glFrustumfOES = NULL;
+PFNGLGETCLIPPLANEFOESPROC glad_glGetClipPlanefOES = NULL;
+PFNGLORTHOFOESPROC glad_glOrthofOES = NULL;
+PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR = NULL;
+PFNGLHINTPGIPROC glad_glHintPGI = NULL;
+PFNGLDETAILTEXFUNCSGISPROC glad_glDetailTexFuncSGIS = NULL;
+PFNGLGETDETAILTEXFUNCSGISPROC glad_glGetDetailTexFuncSGIS = NULL;
+PFNGLFOGFUNCSGISPROC glad_glFogFuncSGIS = NULL;
+PFNGLGETFOGFUNCSGISPROC glad_glGetFogFuncSGIS = NULL;
+PFNGLSAMPLEMASKSGISPROC glad_glSampleMaskSGIS = NULL;
+PFNGLSAMPLEPATTERNSGISPROC glad_glSamplePatternSGIS = NULL;
+PFNGLPIXELTEXGENPARAMETERISGISPROC glad_glPixelTexGenParameteriSGIS = NULL;
+PFNGLPIXELTEXGENPARAMETERIVSGISPROC glad_glPixelTexGenParameterivSGIS = NULL;
+PFNGLPIXELTEXGENPARAMETERFSGISPROC glad_glPixelTexGenParameterfSGIS = NULL;
+PFNGLPIXELTEXGENPARAMETERFVSGISPROC glad_glPixelTexGenParameterfvSGIS = NULL;
+PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC glad_glGetPixelTexGenParameterivSGIS = NULL;
+PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC glad_glGetPixelTexGenParameterfvSGIS = NULL;
+PFNGLPOINTPARAMETERFSGISPROC glad_glPointParameterfSGIS = NULL;
+PFNGLPOINTPARAMETERFVSGISPROC glad_glPointParameterfvSGIS = NULL;
+PFNGLSHARPENTEXFUNCSGISPROC glad_glSharpenTexFuncSGIS = NULL;
+PFNGLGETSHARPENTEXFUNCSGISPROC glad_glGetSharpenTexFuncSGIS = NULL;
+PFNGLTEXIMAGE4DSGISPROC glad_glTexImage4DSGIS = NULL;
+PFNGLTEXSUBIMAGE4DSGISPROC glad_glTexSubImage4DSGIS = NULL;
+PFNGLTEXTURECOLORMASKSGISPROC glad_glTextureColorMaskSGIS = NULL;
+PFNGLGETTEXFILTERFUNCSGISPROC glad_glGetTexFilterFuncSGIS = NULL;
+PFNGLTEXFILTERFUNCSGISPROC glad_glTexFilterFuncSGIS = NULL;
+PFNGLASYNCMARKERSGIXPROC glad_glAsyncMarkerSGIX = NULL;
+PFNGLFINISHASYNCSGIXPROC glad_glFinishAsyncSGIX = NULL;
+PFNGLPOLLASYNCSGIXPROC glad_glPollAsyncSGIX = NULL;
+PFNGLGENASYNCMARKERSSGIXPROC glad_glGenAsyncMarkersSGIX = NULL;
+PFNGLDELETEASYNCMARKERSSGIXPROC glad_glDeleteAsyncMarkersSGIX = NULL;
+PFNGLISASYNCMARKERSGIXPROC glad_glIsAsyncMarkerSGIX = NULL;
+PFNGLFLUSHRASTERSGIXPROC glad_glFlushRasterSGIX = NULL;
+PFNGLFRAGMENTCOLORMATERIALSGIXPROC glad_glFragmentColorMaterialSGIX = NULL;
+PFNGLFRAGMENTLIGHTFSGIXPROC glad_glFragmentLightfSGIX = NULL;
+PFNGLFRAGMENTLIGHTFVSGIXPROC glad_glFragmentLightfvSGIX = NULL;
+PFNGLFRAGMENTLIGHTISGIXPROC glad_glFragmentLightiSGIX = NULL;
+PFNGLFRAGMENTLIGHTIVSGIXPROC glad_glFragmentLightivSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELFSGIXPROC glad_glFragmentLightModelfSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELFVSGIXPROC glad_glFragmentLightModelfvSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELISGIXPROC glad_glFragmentLightModeliSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELIVSGIXPROC glad_glFragmentLightModelivSGIX = NULL;
+PFNGLFRAGMENTMATERIALFSGIXPROC glad_glFragmentMaterialfSGIX = NULL;
+PFNGLFRAGMENTMATERIALFVSGIXPROC glad_glFragmentMaterialfvSGIX = NULL;
+PFNGLFRAGMENTMATERIALISGIXPROC glad_glFragmentMaterialiSGIX = NULL;
+PFNGLFRAGMENTMATERIALIVSGIXPROC glad_glFragmentMaterialivSGIX = NULL;
+PFNGLGETFRAGMENTLIGHTFVSGIXPROC glad_glGetFragmentLightfvSGIX = NULL;
+PFNGLGETFRAGMENTLIGHTIVSGIXPROC glad_glGetFragmentLightivSGIX = NULL;
+PFNGLGETFRAGMENTMATERIALFVSGIXPROC glad_glGetFragmentMaterialfvSGIX = NULL;
+PFNGLGETFRAGMENTMATERIALIVSGIXPROC glad_glGetFragmentMaterialivSGIX = NULL;
+PFNGLLIGHTENVISGIXPROC glad_glLightEnviSGIX = NULL;
+PFNGLFRAMEZOOMSGIXPROC glad_glFrameZoomSGIX = NULL;
+PFNGLIGLOOINTERFACESGIXPROC glad_glIglooInterfaceSGIX = NULL;
+PFNGLGETINSTRUMENTSSGIXPROC glad_glGetInstrumentsSGIX = NULL;
+PFNGLINSTRUMENTSBUFFERSGIXPROC glad_glInstrumentsBufferSGIX = NULL;
+PFNGLPOLLINSTRUMENTSSGIXPROC glad_glPollInstrumentsSGIX = NULL;
+PFNGLREADINSTRUMENTSSGIXPROC glad_glReadInstrumentsSGIX = NULL;
+PFNGLSTARTINSTRUMENTSSGIXPROC glad_glStartInstrumentsSGIX = NULL;
+PFNGLSTOPINSTRUMENTSSGIXPROC glad_glStopInstrumentsSGIX = NULL;
+PFNGLGETLISTPARAMETERFVSGIXPROC glad_glGetListParameterfvSGIX = NULL;
+PFNGLGETLISTPARAMETERIVSGIXPROC glad_glGetListParameterivSGIX = NULL;
+PFNGLLISTPARAMETERFSGIXPROC glad_glListParameterfSGIX = NULL;
+PFNGLLISTPARAMETERFVSGIXPROC glad_glListParameterfvSGIX = NULL;
+PFNGLLISTPARAMETERISGIXPROC glad_glListParameteriSGIX = NULL;
+PFNGLLISTPARAMETERIVSGIXPROC glad_glListParameterivSGIX = NULL;
+PFNGLPIXELTEXGENSGIXPROC glad_glPixelTexGenSGIX = NULL;
+PFNGLDEFORMATIONMAP3DSGIXPROC glad_glDeformationMap3dSGIX = NULL;
+PFNGLDEFORMATIONMAP3FSGIXPROC glad_glDeformationMap3fSGIX = NULL;
+PFNGLDEFORMSGIXPROC glad_glDeformSGIX = NULL;
+PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC glad_glLoadIdentityDeformationMapSGIX = NULL;
+PFNGLREFERENCEPLANESGIXPROC glad_glReferencePlaneSGIX = NULL;
+PFNGLSPRITEPARAMETERFSGIXPROC glad_glSpriteParameterfSGIX = NULL;
+PFNGLSPRITEPARAMETERFVSGIXPROC glad_glSpriteParameterfvSGIX = NULL;
+PFNGLSPRITEPARAMETERISGIXPROC glad_glSpriteParameteriSGIX = NULL;
+PFNGLSPRITEPARAMETERIVSGIXPROC glad_glSpriteParameterivSGIX = NULL;
+PFNGLTAGSAMPLEBUFFERSGIXPROC glad_glTagSampleBufferSGIX = NULL;
+PFNGLCOLORTABLESGIPROC glad_glColorTableSGI = NULL;
+PFNGLCOLORTABLEPARAMETERFVSGIPROC glad_glColorTableParameterfvSGI = NULL;
+PFNGLCOLORTABLEPARAMETERIVSGIPROC glad_glColorTableParameterivSGI = NULL;
+PFNGLCOPYCOLORTABLESGIPROC glad_glCopyColorTableSGI = NULL;
+PFNGLGETCOLORTABLESGIPROC glad_glGetColorTableSGI = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVSGIPROC glad_glGetColorTableParameterfvSGI = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVSGIPROC glad_glGetColorTableParameterivSGI = NULL;
+PFNGLFINISHTEXTURESUNXPROC glad_glFinishTextureSUNX = NULL;
+PFNGLGLOBALALPHAFACTORBSUNPROC glad_glGlobalAlphaFactorbSUN = NULL;
+PFNGLGLOBALALPHAFACTORSSUNPROC glad_glGlobalAlphaFactorsSUN = NULL;
+PFNGLGLOBALALPHAFACTORISUNPROC glad_glGlobalAlphaFactoriSUN = NULL;
+PFNGLGLOBALALPHAFACTORFSUNPROC glad_glGlobalAlphaFactorfSUN = NULL;
+PFNGLGLOBALALPHAFACTORDSUNPROC glad_glGlobalAlphaFactordSUN = NULL;
+PFNGLGLOBALALPHAFACTORUBSUNPROC glad_glGlobalAlphaFactorubSUN = NULL;
+PFNGLGLOBALALPHAFACTORUSSUNPROC glad_glGlobalAlphaFactorusSUN = NULL;
+PFNGLGLOBALALPHAFACTORUISUNPROC glad_glGlobalAlphaFactoruiSUN = NULL;
+PFNGLDRAWMESHARRAYSSUNPROC glad_glDrawMeshArraysSUN = NULL;
+PFNGLREPLACEMENTCODEUISUNPROC glad_glReplacementCodeuiSUN = NULL;
+PFNGLREPLACEMENTCODEUSSUNPROC glad_glReplacementCodeusSUN = NULL;
+PFNGLREPLACEMENTCODEUBSUNPROC glad_glReplacementCodeubSUN = NULL;
+PFNGLREPLACEMENTCODEUIVSUNPROC glad_glReplacementCodeuivSUN = NULL;
+PFNGLREPLACEMENTCODEUSVSUNPROC glad_glReplacementCodeusvSUN = NULL;
+PFNGLREPLACEMENTCODEUBVSUNPROC glad_glReplacementCodeubvSUN = NULL;
+PFNGLREPLACEMENTCODEPOINTERSUNPROC glad_glReplacementCodePointerSUN = NULL;
+PFNGLCOLOR4UBVERTEX2FSUNPROC glad_glColor4ubVertex2fSUN = NULL;
+PFNGLCOLOR4UBVERTEX2FVSUNPROC glad_glColor4ubVertex2fvSUN = NULL;
+PFNGLCOLOR4UBVERTEX3FSUNPROC glad_glColor4ubVertex3fSUN = NULL;
+PFNGLCOLOR4UBVERTEX3FVSUNPROC glad_glColor4ubVertex3fvSUN = NULL;
+PFNGLCOLOR3FVERTEX3FSUNPROC glad_glColor3fVertex3fSUN = NULL;
+PFNGLCOLOR3FVERTEX3FVSUNPROC glad_glColor3fVertex3fvSUN = NULL;
+PFNGLNORMAL3FVERTEX3FSUNPROC glad_glNormal3fVertex3fSUN = NULL;
+PFNGLNORMAL3FVERTEX3FVSUNPROC glad_glNormal3fVertex3fvSUN = NULL;
+PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glColor4fNormal3fVertex3fSUN = NULL;
+PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FVERTEX3FSUNPROC glad_glTexCoord2fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FVERTEX3FVSUNPROC glad_glTexCoord2fVertex3fvSUN = NULL;
+PFNGLTEXCOORD4FVERTEX4FSUNPROC glad_glTexCoord4fVertex4fSUN = NULL;
+PFNGLTEXCOORD4FVERTEX4FVSUNPROC glad_glTexCoord4fVertex4fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC glad_glTexCoord2fColor4ubVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC glad_glTexCoord2fColor4ubVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC glad_glTexCoord2fColor3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC glad_glTexCoord2fColor3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC glad_glTexCoord2fNormal3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC glad_glTexCoord2fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glTexCoord2fColor4fNormal3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glTexCoord2fColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC glad_glTexCoord4fColor4fNormal3fVertex4fSUN = NULL;
+PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC glad_glTexCoord4fColor4fNormal3fVertex4fvSUN = NULL;
+PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC glad_glReplacementCodeuiVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC glad_glReplacementCodeuiVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC glad_glReplacementCodeuiColor4ubVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC glad_glReplacementCodeuiColor4ubVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC glad_glReplacementCodeuiColor3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC glad_glReplacementCodeuiColor3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiColor4fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC glad_glReplacementCodeuiTexCoord2fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC glad_glReplacementCodeuiTexCoord2fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC glad_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC glad_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = NULL;
static void load_GL_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GL_VERSION_1_0) return;
glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
@@ -4453,6 +4457,11 @@ static void load_GL_AMD_draw_buffers_blend(GLADloadproc load) {
glad_glBlendEquationIndexedAMD = (PFNGLBLENDEQUATIONINDEXEDAMDPROC)load("glBlendEquationIndexedAMD");
glad_glBlendEquationSeparateIndexedAMD = (PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC)load("glBlendEquationSeparateIndexedAMD");
}
+static void load_GL_AMD_framebuffer_multisample_advanced(GLADloadproc load) {
+ if(!GLAD_GL_AMD_framebuffer_multisample_advanced) return;
+ glad_glRenderbufferStorageMultisampleAdvancedAMD = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC)load("glRenderbufferStorageMultisampleAdvancedAMD");
+ glad_glNamedRenderbufferStorageMultisampleAdvancedAMD = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC)load("glNamedRenderbufferStorageMultisampleAdvancedAMD");
+}
static void load_GL_AMD_framebuffer_sample_positions(GLADloadproc load) {
if(!GLAD_GL_AMD_framebuffer_sample_positions) return;
glad_glFramebufferSamplePositionsfvAMD = (PFNGLFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC)load("glFramebufferSamplePositionsfvAMD");
@@ -7812,6 +7821,7 @@ static int find_extensionsGL(void) {
GLAD_GL_AMD_debug_output = has_ext("GL_AMD_debug_output");
GLAD_GL_AMD_depth_clamp_separate = has_ext("GL_AMD_depth_clamp_separate");
GLAD_GL_AMD_draw_buffers_blend = has_ext("GL_AMD_draw_buffers_blend");
+ GLAD_GL_AMD_framebuffer_multisample_advanced = has_ext("GL_AMD_framebuffer_multisample_advanced");
GLAD_GL_AMD_framebuffer_sample_positions = has_ext("GL_AMD_framebuffer_sample_positions");
GLAD_GL_AMD_gcn_shader = has_ext("GL_AMD_gcn_shader");
GLAD_GL_AMD_gpu_shader_half_float = has_ext("GL_AMD_gpu_shader_half_float");
@@ -8473,6 +8483,7 @@ int gladLoadGLLoader(GLADloadproc load) {
load_GL_3DFX_tbuffer(load);
load_GL_AMD_debug_output(load);
load_GL_AMD_draw_buffers_blend(load);
+ load_GL_AMD_framebuffer_multisample_advanced(load);
load_GL_AMD_framebuffer_sample_positions(load);
load_GL_AMD_gpu_shader_int64(load);
load_GL_AMD_interleaved_elements(load);
diff --git a/externals/mbedtls b/externals/mbedtls
-Subproject 06442b840ea62e2ceda0dc58f255cfff49fed5b
+Subproject d409b75a4cf75a5b358b352c75826ddbca44db5
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index 81121167d..82e4850f7 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -1,16 +1,24 @@
add_library(audio_core STATIC
+ algorithm/filter.cpp
+ algorithm/filter.h
+ algorithm/interpolate.cpp
+ algorithm/interpolate.h
audio_out.cpp
audio_out.h
+ audio_renderer.cpp
+ audio_renderer.h
buffer.h
- cubeb_sink.cpp
- cubeb_sink.h
+ codec.cpp
+ codec.h
null_sink.h
- stream.cpp
- stream.h
sink.h
sink_details.cpp
sink_details.h
sink_stream.h
+ stream.cpp
+ stream.h
+
+ $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h>
)
create_target_directory_groups(audio_core)
diff --git a/src/audio_core/algorithm/filter.cpp b/src/audio_core/algorithm/filter.cpp
new file mode 100644
index 000000000..403b8503f
--- /dev/null
+++ b/src/audio_core/algorithm/filter.cpp
@@ -0,0 +1,79 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#define _USE_MATH_DEFINES
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <vector>
+#include "audio_core/algorithm/filter.h"
+#include "common/common_types.h"
+
+namespace AudioCore {
+
+Filter Filter::LowPass(double cutoff, double Q) {
+ const double w0 = 2.0 * M_PI * cutoff;
+ const double sin_w0 = std::sin(w0);
+ const double cos_w0 = std::cos(w0);
+ const double alpha = sin_w0 / (2 * Q);
+
+ const double a0 = 1 + alpha;
+ const double a1 = -2.0 * cos_w0;
+ const double a2 = 1 - alpha;
+ const double b0 = 0.5 * (1 - cos_w0);
+ const double b1 = 1.0 * (1 - cos_w0);
+ const double b2 = 0.5 * (1 - cos_w0);
+
+ return {a0, a1, a2, b0, b1, b2};
+}
+
+Filter::Filter() : Filter(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) {}
+
+Filter::Filter(double a0, double a1, double a2, double b0, double b1, double b2)
+ : a1(a1 / a0), a2(a2 / a0), b0(b0 / a0), b1(b1 / a0), b2(b2 / a0) {}
+
+void Filter::Process(std::vector<s16>& signal) {
+ const size_t num_frames = signal.size() / 2;
+ for (size_t i = 0; i < num_frames; i++) {
+ std::rotate(in.begin(), in.end() - 1, in.end());
+ std::rotate(out.begin(), out.end() - 1, out.end());
+
+ for (size_t ch = 0; ch < channel_count; ch++) {
+ in[0][ch] = signal[i * channel_count + ch];
+
+ out[0][ch] = b0 * in[0][ch] + b1 * in[1][ch] + b2 * in[2][ch] - a1 * out[1][ch] -
+ a2 * out[2][ch];
+
+ signal[i * 2 + ch] = std::clamp(out[0][ch], -32768.0, 32767.0);
+ }
+ }
+}
+
+/// Calculates the appropriate Q for each biquad in a cascading filter.
+/// @param total_count The total number of biquads to be cascaded.
+/// @param index 0-index of the biquad to calculate the Q value for.
+static double CascadingBiquadQ(size_t total_count, size_t index) {
+ const double pole = M_PI * (2 * index + 1) / (4.0 * total_count);
+ return 1.0 / (2.0 * std::cos(pole));
+}
+
+CascadingFilter CascadingFilter::LowPass(double cutoff, size_t cascade_size) {
+ std::vector<Filter> cascade(cascade_size);
+ for (size_t i = 0; i < cascade_size; i++) {
+ cascade[i] = Filter::LowPass(cutoff, CascadingBiquadQ(cascade_size, i));
+ }
+ return CascadingFilter{std::move(cascade)};
+}
+
+CascadingFilter::CascadingFilter() = default;
+CascadingFilter::CascadingFilter(std::vector<Filter> filters) : filters(std::move(filters)) {}
+
+void CascadingFilter::Process(std::vector<s16>& signal) {
+ for (auto& filter : filters) {
+ filter.Process(signal);
+ }
+}
+
+} // namespace AudioCore
diff --git a/src/audio_core/algorithm/filter.h b/src/audio_core/algorithm/filter.h
new file mode 100644
index 000000000..a41beef98
--- /dev/null
+++ b/src/audio_core/algorithm/filter.h
@@ -0,0 +1,62 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <vector>
+#include "common/common_types.h"
+
+namespace AudioCore {
+
+/// Digital biquad filter:
+///
+/// b0 + b1 z^-1 + b2 z^-2
+/// H(z) = ------------------------
+/// a0 + a1 z^-1 + b2 z^-2
+class Filter {
+public:
+ /// Creates a low-pass filter.
+ /// @param cutoff Determines the cutoff frequency. A value from 0.0 to 1.0.
+ /// @param Q Determines the quality factor of this filter.
+ static Filter LowPass(double cutoff, double Q = 0.7071);
+
+ /// Passthrough filter.
+ Filter();
+
+ Filter(double a0, double a1, double a2, double b0, double b1, double b2);
+
+ void Process(std::vector<s16>& signal);
+
+private:
+ static constexpr size_t channel_count = 2;
+
+ /// Coefficients are in normalized form (a0 = 1.0).
+ double a1, a2, b0, b1, b2;
+ /// Input History
+ std::array<std::array<double, channel_count>, 3> in;
+ /// Output History
+ std::array<std::array<double, channel_count>, 3> out;
+};
+
+/// Cascade filters to build up higher-order filters from lower-order ones.
+class CascadingFilter {
+public:
+ /// Creates a cascading low-pass filter.
+ /// @param cutoff Determines the cutoff frequency. A value from 0.0 to 1.0.
+ /// @param cascade_size Number of biquads in cascade.
+ static CascadingFilter LowPass(double cutoff, size_t cascade_size);
+
+ /// Passthrough.
+ CascadingFilter();
+
+ explicit CascadingFilter(std::vector<Filter> filters);
+
+ void Process(std::vector<s16>& signal);
+
+private:
+ std::vector<Filter> filters;
+};
+
+} // namespace AudioCore
diff --git a/src/audio_core/algorithm/interpolate.cpp b/src/audio_core/algorithm/interpolate.cpp
new file mode 100644
index 000000000..11459821f
--- /dev/null
+++ b/src/audio_core/algorithm/interpolate.cpp
@@ -0,0 +1,71 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#define _USE_MATH_DEFINES
+
+#include <algorithm>
+#include <cmath>
+#include <vector>
+#include "audio_core/algorithm/interpolate.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+
+namespace AudioCore {
+
+/// The Lanczos kernel
+static double Lanczos(size_t a, double x) {
+ if (x == 0.0)
+ return 1.0;
+ const double px = M_PI * x;
+ return a * std::sin(px) * std::sin(px / a) / (px * px);
+}
+
+std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, double ratio) {
+ if (input.size() < 2)
+ return {};
+
+ if (ratio <= 0) {
+ LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
+ ratio = 1.0;
+ }
+
+ if (ratio != state.current_ratio) {
+ const double cutoff_frequency = std::min(0.5 / ratio, 0.5 * ratio);
+ state.nyquist = CascadingFilter::LowPass(std::clamp(cutoff_frequency, 0.0, 0.4), 3);
+ state.current_ratio = ratio;
+ }
+ state.nyquist.Process(input);
+
+ constexpr size_t taps = InterpolationState::lanczos_taps;
+ const size_t num_frames = input.size() / 2;
+
+ std::vector<s16> output;
+ output.reserve(static_cast<size_t>(input.size() / ratio + 4));
+
+ double& pos = state.position;
+ auto& h = state.history;
+ for (size_t i = 0; i < num_frames; ++i) {
+ std::rotate(h.begin(), h.end() - 1, h.end());
+ h[0][0] = input[i * 2 + 0];
+ h[0][1] = input[i * 2 + 1];
+
+ while (pos <= 1.0) {
+ double l = 0.0;
+ double r = 0.0;
+ for (size_t j = 0; j < h.size(); j++) {
+ l += Lanczos(taps, pos + j - taps + 1) * h[j][0];
+ r += Lanczos(taps, pos + j - taps + 1) * h[j][1];
+ }
+ output.emplace_back(static_cast<s16>(std::clamp(l, -32768.0, 32767.0)));
+ output.emplace_back(static_cast<s16>(std::clamp(r, -32768.0, 32767.0)));
+
+ pos += ratio;
+ }
+ pos -= 1.0;
+ }
+
+ return output;
+}
+
+} // namespace AudioCore
diff --git a/src/audio_core/algorithm/interpolate.h b/src/audio_core/algorithm/interpolate.h
new file mode 100644
index 000000000..c79c2eef4
--- /dev/null
+++ b/src/audio_core/algorithm/interpolate.h
@@ -0,0 +1,43 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <vector>
+#include "audio_core/algorithm/filter.h"
+#include "common/common_types.h"
+
+namespace AudioCore {
+
+struct InterpolationState {
+ static constexpr size_t lanczos_taps = 4;
+ static constexpr size_t history_size = lanczos_taps * 2 - 1;
+
+ double current_ratio = 0.0;
+ CascadingFilter nyquist;
+ std::array<std::array<s16, 2>, history_size> history = {};
+ double position = 0;
+};
+
+/// Interpolates input signal to produce output signal.
+/// @param input The signal to interpolate.
+/// @param ratio Interpolation ratio.
+/// ratio > 1.0 results in fewer output samples.
+/// ratio < 1.0 results in more output samples.
+/// @returns Output signal.
+std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, double ratio);
+
+/// Interpolates input signal to produce output signal.
+/// @param input The signal to interpolate.
+/// @param input_rate The sample rate of input.
+/// @param output_rate The desired sample rate of the output.
+/// @returns Output signal.
+inline std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
+ u32 input_rate, u32 output_rate) {
+ const double ratio = static_cast<double>(input_rate) / static_cast<double>(output_rate);
+ return Interpolate(state, std::move(input), ratio);
+}
+
+} // namespace AudioCore
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp
index 3dfdf61f9..12632a95c 100644
--- a/src/audio_core/audio_out.cpp
+++ b/src/audio_core/audio_out.cpp
@@ -27,16 +27,16 @@ static Stream::Format ChannelsToStreamFormat(u32 num_channels) {
return {};
}
-StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels,
+StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels, std::string&& name,
Stream::ReleaseCallback&& release_callback) {
if (!sink) {
const SinkDetails& sink_details = GetSinkDetails(Settings::values.sink_id);
sink = sink_details.factory(Settings::values.audio_device_id);
}
- return std::make_shared<Stream>(sample_rate, ChannelsToStreamFormat(num_channels),
- std::move(release_callback),
- sink->AcquireSinkStream(sample_rate, num_channels));
+ return std::make_shared<Stream>(
+ sample_rate, ChannelsToStreamFormat(num_channels), std::move(release_callback),
+ sink->AcquireSinkStream(sample_rate, num_channels, name), std::move(name));
}
std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count) {
@@ -51,7 +51,7 @@ void AudioOut::StopStream(StreamPtr stream) {
stream->Stop();
}
-bool AudioOut::QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data) {
+bool AudioOut::QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<s16>&& data) {
return stream->QueueBuffer(std::make_shared<Buffer>(tag, std::move(data)));
}
diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h
index 95e9b53fe..39b7e656b 100644
--- a/src/audio_core/audio_out.h
+++ b/src/audio_core/audio_out.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <string>
#include <vector>
#include "audio_core/buffer.h"
@@ -20,7 +21,7 @@ namespace AudioCore {
class AudioOut {
public:
/// Opens a new audio stream
- StreamPtr OpenStream(u32 sample_rate, u32 num_channels,
+ StreamPtr OpenStream(u32 sample_rate, u32 num_channels, std::string&& name,
Stream::ReleaseCallback&& release_callback);
/// Returns a vector of recently released buffers specified by tag for the specified stream
@@ -33,7 +34,7 @@ public:
void StopStream(StreamPtr stream);
/// Queues a buffer into the specified audio stream, returns true on success
- bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data);
+ bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<s16>&& data);
private:
SinkPtr sink;
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
new file mode 100644
index 000000000..397b107f5
--- /dev/null
+++ b/src/audio_core/audio_renderer.cpp
@@ -0,0 +1,249 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "audio_core/algorithm/interpolate.h"
+#include "audio_core/audio_renderer.h"
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/memory.h"
+
+namespace AudioCore {
+
+constexpr u32 STREAM_SAMPLE_RATE{48000};
+constexpr u32 STREAM_NUM_CHANNELS{2};
+
+AudioRenderer::AudioRenderer(AudioRendererParameter params,
+ Kernel::SharedPtr<Kernel::Event> buffer_event)
+ : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) {
+
+ audio_core = std::make_unique<AudioCore::AudioOut>();
+ stream = audio_core->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer",
+ [=]() { buffer_event->Signal(); });
+ audio_core->StartStream(stream);
+
+ QueueMixedBuffer(0);
+ QueueMixedBuffer(1);
+ QueueMixedBuffer(2);
+}
+
+u32 AudioRenderer::GetSampleRate() const {
+ return worker_params.sample_rate;
+}
+
+u32 AudioRenderer::GetSampleCount() const {
+ return worker_params.sample_count;
+}
+
+u32 AudioRenderer::GetMixBufferCount() const {
+ return worker_params.mix_buffer_count;
+}
+
+std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params) {
+ // Copy UpdateDataHeader struct
+ UpdateDataHeader config{};
+ std::memcpy(&config, input_params.data(), sizeof(UpdateDataHeader));
+ u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4);
+
+ // Copy MemoryPoolInfo structs
+ std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count);
+ std::memcpy(mem_pool_info.data(),
+ input_params.data() + sizeof(UpdateDataHeader) + config.behavior_size,
+ memory_pool_count * sizeof(MemoryPoolInfo));
+
+ // Copy VoiceInfo structs
+ size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size +
+ config.voice_resource_size};
+ for (auto& voice : voices) {
+ std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo));
+ offset += sizeof(VoiceInfo);
+ }
+
+ // Update voices
+ for (auto& voice : voices) {
+ voice.UpdateState();
+ if (!voice.GetInfo().is_in_use) {
+ continue;
+ }
+ if (voice.GetInfo().is_new) {
+ voice.SetWaveIndex(voice.GetInfo().wave_buffer_head);
+ }
+ }
+
+ // Update memory pool state
+ std::vector<MemoryPoolEntry> memory_pool(memory_pool_count);
+ for (size_t index = 0; index < memory_pool.size(); ++index) {
+ if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) {
+ memory_pool[index].state = MemoryPoolStates::Attached;
+ } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) {
+ memory_pool[index].state = MemoryPoolStates::Detached;
+ }
+ }
+
+ // Release previous buffers and queue next ones for playback
+ ReleaseAndQueueBuffers();
+
+ // Copy output header
+ UpdateDataHeader response_data{worker_params};
+ std::vector<u8> output_params(response_data.total_size);
+ std::memcpy(output_params.data(), &response_data, sizeof(UpdateDataHeader));
+
+ // Copy output memory pool entries
+ std::memcpy(output_params.data() + sizeof(UpdateDataHeader), memory_pool.data(),
+ response_data.memory_pools_size);
+
+ // Copy output voice status
+ size_t voice_out_status_offset{sizeof(UpdateDataHeader) + response_data.memory_pools_size};
+ for (const auto& voice : voices) {
+ std::memcpy(output_params.data() + voice_out_status_offset, &voice.GetOutStatus(),
+ sizeof(VoiceOutStatus));
+ voice_out_status_offset += sizeof(VoiceOutStatus);
+ }
+
+ return output_params;
+}
+
+void AudioRenderer::VoiceState::SetWaveIndex(size_t index) {
+ wave_index = index & 3;
+ is_refresh_pending = true;
+}
+
+std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(size_t sample_count) {
+ if (!IsPlaying()) {
+ return {};
+ }
+
+ if (is_refresh_pending) {
+ RefreshBuffer();
+ }
+
+ const size_t max_size{samples.size() - offset};
+ const size_t dequeue_offset{offset};
+ size_t size{sample_count * STREAM_NUM_CHANNELS};
+ if (size > max_size) {
+ size = max_size;
+ }
+
+ out_status.played_sample_count += size / STREAM_NUM_CHANNELS;
+ offset += size;
+
+ const auto& wave_buffer{info.wave_buffer[wave_index]};
+ if (offset == samples.size()) {
+ offset = 0;
+
+ if (!wave_buffer.is_looping) {
+ SetWaveIndex(wave_index + 1);
+ }
+
+ out_status.wave_buffer_consumed++;
+
+ if (wave_buffer.end_of_stream) {
+ info.play_state = PlayState::Paused;
+ }
+ }
+
+ return {samples.begin() + dequeue_offset, samples.begin() + dequeue_offset + size};
+}
+
+void AudioRenderer::VoiceState::UpdateState() {
+ if (is_in_use && !info.is_in_use) {
+ // No longer in use, reset state
+ is_refresh_pending = true;
+ wave_index = 0;
+ offset = 0;
+ out_status = {};
+ }
+ is_in_use = info.is_in_use;
+}
+
+void AudioRenderer::VoiceState::RefreshBuffer() {
+ std::vector<s16> new_samples(info.wave_buffer[wave_index].buffer_sz / sizeof(s16));
+ Memory::ReadBlock(info.wave_buffer[wave_index].buffer_addr, new_samples.data(),
+ info.wave_buffer[wave_index].buffer_sz);
+
+ switch (static_cast<Codec::PcmFormat>(info.sample_format)) {
+ case Codec::PcmFormat::Int16: {
+ // PCM16 is played as-is
+ break;
+ }
+ case Codec::PcmFormat::Adpcm: {
+ // Decode ADPCM to PCM16
+ Codec::ADPCM_Coeff coeffs;
+ Memory::ReadBlock(info.additional_params_addr, coeffs.data(), sizeof(Codec::ADPCM_Coeff));
+ new_samples = Codec::DecodeADPCM(reinterpret_cast<u8*>(new_samples.data()),
+ new_samples.size() * sizeof(s16), coeffs, adpcm_state);
+ break;
+ }
+ default:
+ LOG_CRITICAL(Audio, "Unimplemented sample_format={}", info.sample_format);
+ UNREACHABLE();
+ break;
+ }
+
+ switch (info.channel_count) {
+ case 1:
+ // 1 channel is upsampled to 2 channel
+ samples.resize(new_samples.size() * 2);
+ for (size_t index = 0; index < new_samples.size(); ++index) {
+ samples[index * 2] = new_samples[index];
+ samples[index * 2 + 1] = new_samples[index];
+ }
+ break;
+ case 2: {
+ // 2 channel is played as is
+ samples = std::move(new_samples);
+ break;
+ }
+ default:
+ LOG_CRITICAL(Audio, "Unimplemented channel_count={}", info.channel_count);
+ UNREACHABLE();
+ break;
+ }
+
+ samples = Interpolate(interp_state, std::move(samples), Info().sample_rate, STREAM_SAMPLE_RATE);
+
+ is_refresh_pending = false;
+}
+
+static constexpr s16 ClampToS16(s32 value) {
+ return static_cast<s16>(std::clamp(value, -32768, 32767));
+}
+
+void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
+ constexpr size_t BUFFER_SIZE{512};
+ std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels());
+
+ for (auto& voice : voices) {
+ if (!voice.IsPlaying()) {
+ continue;
+ }
+
+ size_t offset{};
+ s64 samples_remaining{BUFFER_SIZE};
+ while (samples_remaining > 0) {
+ const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)};
+
+ if (samples.empty()) {
+ break;
+ }
+
+ samples_remaining -= samples.size() / stream->GetNumChannels();
+
+ for (const auto& sample : samples) {
+ const s32 buffer_sample{buffer[offset]};
+ buffer[offset++] =
+ ClampToS16(buffer_sample + static_cast<s32>(sample * voice.GetInfo().volume));
+ }
+ }
+ }
+ audio_core->QueueBuffer(stream, tag, std::move(buffer));
+}
+
+void AudioRenderer::ReleaseAndQueueBuffers() {
+ const auto released_buffers{audio_core->GetTagsAndReleaseBuffers(stream, 2)};
+ for (const auto& tag : released_buffers) {
+ QueueMixedBuffer(tag);
+ }
+}
+
+} // namespace AudioCore
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
new file mode 100644
index 000000000..eba67f28e
--- /dev/null
+++ b/src/audio_core/audio_renderer.h
@@ -0,0 +1,211 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <memory>
+#include <vector>
+
+#include "audio_core/algorithm/interpolate.h"
+#include "audio_core/audio_out.h"
+#include "audio_core/codec.h"
+#include "audio_core/stream.h"
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "core/hle/kernel/event.h"
+
+namespace AudioCore {
+
+enum class PlayState : u8 {
+ Started = 0,
+ Stopped = 1,
+ Paused = 2,
+};
+
+struct AudioRendererParameter {
+ u32_le sample_rate;
+ u32_le sample_count;
+ u32_le mix_buffer_count;
+ u32_le unknown_c;
+ u32_le voice_count;
+ u32_le sink_count;
+ u32_le effect_count;
+ u32_le unknown_1c;
+ u8 unknown_20;
+ INSERT_PADDING_BYTES(3);
+ u32_le splitter_count;
+ u32_le unknown_2c;
+ INSERT_PADDING_WORDS(1);
+ u32_le revision;
+};
+static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size");
+
+enum class MemoryPoolStates : u32 { // Should be LE
+ Invalid = 0x0,
+ Unknown = 0x1,
+ RequestDetach = 0x2,
+ Detached = 0x3,
+ RequestAttach = 0x4,
+ Attached = 0x5,
+ Released = 0x6,
+};
+
+struct MemoryPoolEntry {
+ MemoryPoolStates state;
+ u32_le unknown_4;
+ u32_le unknown_8;
+ u32_le unknown_c;
+};
+static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size");
+
+struct MemoryPoolInfo {
+ u64_le pool_address;
+ u64_le pool_size;
+ MemoryPoolStates pool_state;
+ INSERT_PADDING_WORDS(3); // Unknown
+};
+static_assert(sizeof(MemoryPoolInfo) == 0x20, "MemoryPoolInfo has wrong size");
+struct BiquadFilter {
+ u8 enable;
+ INSERT_PADDING_BYTES(1);
+ std::array<s16_le, 3> numerator;
+ std::array<s16_le, 2> denominator;
+};
+static_assert(sizeof(BiquadFilter) == 0xc, "BiquadFilter has wrong size");
+
+struct WaveBuffer {
+ u64_le buffer_addr;
+ u64_le buffer_sz;
+ s32_le start_sample_offset;
+ s32_le end_sample_offset;
+ u8 is_looping;
+ u8 end_of_stream;
+ u8 sent_to_server;
+ INSERT_PADDING_BYTES(5);
+ u64 context_addr;
+ u64 context_sz;
+ INSERT_PADDING_BYTES(8);
+};
+static_assert(sizeof(WaveBuffer) == 0x38, "WaveBuffer has wrong size");
+
+struct VoiceInfo {
+ u32_le id;
+ u32_le node_id;
+ u8 is_new;
+ u8 is_in_use;
+ PlayState play_state;
+ u8 sample_format;
+ u32_le sample_rate;
+ u32_le priority;
+ u32_le sorting_order;
+ u32_le channel_count;
+ float_le pitch;
+ float_le volume;
+ std::array<BiquadFilter, 2> biquad_filter;
+ u32_le wave_buffer_count;
+ u32_le wave_buffer_head;
+ INSERT_PADDING_WORDS(1);
+ u64_le additional_params_addr;
+ u64_le additional_params_sz;
+ u32_le mix_id;
+ u32_le splitter_info_id;
+ std::array<WaveBuffer, 4> wave_buffer;
+ std::array<u32_le, 6> voice_channel_resource_ids;
+ INSERT_PADDING_BYTES(24);
+};
+static_assert(sizeof(VoiceInfo) == 0x170, "VoiceInfo is wrong size");
+
+struct VoiceOutStatus {
+ u64_le played_sample_count;
+ u32_le wave_buffer_consumed;
+ u32_le voice_drops_count;
+};
+static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size");
+
+struct UpdateDataHeader {
+ UpdateDataHeader() {}
+
+ explicit UpdateDataHeader(const AudioRendererParameter& config) {
+ revision = Common::MakeMagic('R', 'E', 'V', '4'); // 5.1.0 Revision
+ behavior_size = 0xb0;
+ memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10;
+ voices_size = config.voice_count * 0x10;
+ voice_resource_size = 0x0;
+ effects_size = config.effect_count * 0x10;
+ mixes_size = 0x0;
+ sinks_size = config.sink_count * 0x20;
+ performance_manager_size = 0x10;
+ total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size + voices_size +
+ effects_size + sinks_size + performance_manager_size;
+ }
+
+ u32_le revision;
+ u32_le behavior_size;
+ u32_le memory_pools_size;
+ u32_le voices_size;
+ u32_le voice_resource_size;
+ u32_le effects_size;
+ u32_le mixes_size;
+ u32_le sinks_size;
+ u32_le performance_manager_size;
+ INSERT_PADDING_WORDS(6);
+ u32_le total_size;
+};
+static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size");
+
+class AudioRenderer {
+public:
+ AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event);
+ std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
+ void QueueMixedBuffer(Buffer::Tag tag);
+ void ReleaseAndQueueBuffers();
+ u32 GetSampleRate() const;
+ u32 GetSampleCount() const;
+ u32 GetMixBufferCount() const;
+
+private:
+ class VoiceState {
+ public:
+ bool IsPlaying() const {
+ return is_in_use && info.play_state == PlayState::Started;
+ }
+
+ const VoiceOutStatus& GetOutStatus() const {
+ return out_status;
+ }
+
+ const VoiceInfo& GetInfo() const {
+ return info;
+ }
+
+ VoiceInfo& Info() {
+ return info;
+ }
+
+ void SetWaveIndex(size_t index);
+ std::vector<s16> DequeueSamples(size_t sample_count);
+ void UpdateState();
+ void RefreshBuffer();
+
+ private:
+ bool is_in_use{};
+ bool is_refresh_pending{};
+ size_t wave_index{};
+ size_t offset{};
+ Codec::ADPCMState adpcm_state{};
+ InterpolationState interp_state{};
+ std::vector<s16> samples;
+ VoiceOutStatus out_status{};
+ VoiceInfo info{};
+ };
+
+ AudioRendererParameter worker_params;
+ Kernel::SharedPtr<Kernel::Event> buffer_event;
+ std::vector<VoiceState> voices;
+ std::unique_ptr<AudioCore::AudioOut> audio_core;
+ AudioCore::StreamPtr stream;
+};
+
+} // namespace AudioCore
diff --git a/src/audio_core/buffer.h b/src/audio_core/buffer.h
index 4bf5fd58a..a323b23ec 100644
--- a/src/audio_core/buffer.h
+++ b/src/audio_core/buffer.h
@@ -18,11 +18,16 @@ class Buffer {
public:
using Tag = u64;
- Buffer(Tag tag, std::vector<u8>&& data) : tag{tag}, data{std::move(data)} {}
+ Buffer(Tag tag, std::vector<s16>&& samples) : tag{tag}, samples{std::move(samples)} {}
/// Returns the raw audio data for the buffer
- const std::vector<u8>& GetData() const {
- return data;
+ std::vector<s16>& Samples() {
+ return samples;
+ }
+
+ /// Returns the raw audio data for the buffer
+ const std::vector<s16>& GetSamples() const {
+ return samples;
}
/// Returns the buffer tag, this is provided by the game to the audout service
@@ -32,7 +37,7 @@ public:
private:
Tag tag;
- std::vector<u8> data;
+ std::vector<s16> samples;
};
using BufferPtr = std::shared_ptr<Buffer>;
diff --git a/src/audio_core/codec.cpp b/src/audio_core/codec.cpp
new file mode 100644
index 000000000..c3021403f
--- /dev/null
+++ b/src/audio_core/codec.cpp
@@ -0,0 +1,77 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+
+#include "audio_core/codec.h"
+
+namespace AudioCore::Codec {
+
+std::vector<s16> DecodeADPCM(const u8* const data, size_t size, const ADPCM_Coeff& coeff,
+ ADPCMState& state) {
+ // GC-ADPCM with scale factor and variable coefficients.
+ // Frames are 8 bytes long containing 14 samples each.
+ // Samples are 4 bits (one nibble) long.
+
+ constexpr size_t FRAME_LEN = 8;
+ constexpr size_t SAMPLES_PER_FRAME = 14;
+ constexpr std::array<int, 16> SIGNED_NIBBLES = {
+ {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}};
+
+ const size_t sample_count = (size / FRAME_LEN) * SAMPLES_PER_FRAME;
+ const size_t ret_size =
+ sample_count % 2 == 0 ? sample_count : sample_count + 1; // Ensure multiple of two.
+ std::vector<s16> ret(ret_size);
+
+ int yn1 = state.yn1, yn2 = state.yn2;
+
+ const size_t NUM_FRAMES =
+ (sample_count + (SAMPLES_PER_FRAME - 1)) / SAMPLES_PER_FRAME; // Round up.
+ for (size_t framei = 0; framei < NUM_FRAMES; framei++) {
+ const int frame_header = data[framei * FRAME_LEN];
+ const int scale = 1 << (frame_header & 0xF);
+ const int idx = (frame_header >> 4) & 0x7;
+
+ // Coefficients are fixed point with 11 bits fractional part.
+ const int coef1 = coeff[idx * 2 + 0];
+ const int coef2 = coeff[idx * 2 + 1];
+
+ // Decodes an audio sample. One nibble produces one sample.
+ const auto decode_sample = [&](const int nibble) -> s16 {
+ const int xn = nibble * scale;
+ // We first transform everything into 11 bit fixed point, perform the second order
+ // digital filter, then transform back.
+ // 0x400 == 0.5 in 11 bit fixed point.
+ // Filter: y[n] = x[n] + 0.5 + c1 * y[n-1] + c2 * y[n-2]
+ int val = ((xn << 11) + 0x400 + coef1 * yn1 + coef2 * yn2) >> 11;
+ // Clamp to output range.
+ val = std::clamp<s32>(val, -32768, 32767);
+ // Advance output feedback.
+ yn2 = yn1;
+ yn1 = val;
+ return static_cast<s16>(val);
+ };
+
+ size_t outputi = framei * SAMPLES_PER_FRAME;
+ size_t datai = framei * FRAME_LEN + 1;
+ for (size_t i = 0; i < SAMPLES_PER_FRAME && outputi < sample_count; i += 2) {
+ const s16 sample1 = decode_sample(SIGNED_NIBBLES[data[datai] >> 4]);
+ ret[outputi] = sample1;
+ outputi++;
+
+ const s16 sample2 = decode_sample(SIGNED_NIBBLES[data[datai] & 0xF]);
+ ret[outputi] = sample2;
+ outputi++;
+
+ datai++;
+ }
+ }
+
+ state.yn1 = yn1;
+ state.yn2 = yn2;
+
+ return ret;
+}
+
+} // namespace AudioCore::Codec
diff --git a/src/audio_core/codec.h b/src/audio_core/codec.h
new file mode 100644
index 000000000..3f845c42c
--- /dev/null
+++ b/src/audio_core/codec.h
@@ -0,0 +1,44 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <vector>
+
+#include "common/common_types.h"
+
+namespace AudioCore::Codec {
+
+enum class PcmFormat : u32 {
+ Invalid = 0,
+ Int8 = 1,
+ Int16 = 2,
+ Int24 = 3,
+ Int32 = 4,
+ PcmFloat = 5,
+ Adpcm = 6,
+};
+
+/// See: Codec::DecodeADPCM
+struct ADPCMState {
+ // Two historical samples from previous processed buffer,
+ // required for ADPCM decoding
+ s16 yn1; ///< y[n-1]
+ s16 yn2; ///< y[n-2]
+};
+
+using ADPCM_Coeff = std::array<s16, 16>;
+
+/**
+ * @param data Pointer to buffer that contains ADPCM data to decode
+ * @param size Size of buffer in bytes
+ * @param coeff ADPCM coefficients
+ * @param state ADPCM state, this is updated with new state
+ * @return Decoded stereo signed PCM16 data, sample_count in length
+ */
+std::vector<s16> DecodeADPCM(const u8* const data, size_t size, const ADPCM_Coeff& coeff,
+ ADPCMState& state);
+
+}; // namespace AudioCore::Codec
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index 34ae5b062..5a1177d0c 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <cstring>
+#include <mutex>
#include "audio_core/cubeb_sink.h"
#include "audio_core/stream.h"
@@ -13,20 +14,30 @@ namespace AudioCore {
class SinkStreamImpl final : public SinkStream {
public:
- SinkStreamImpl(cubeb* ctx, cubeb_devid output_device) : ctx{ctx} {
- cubeb_stream_params params;
- params.rate = 48000;
- params.channels = GetNumChannels();
+ SinkStreamImpl(cubeb* ctx, u32 sample_rate, u32 num_channels_, cubeb_devid output_device,
+ const std::string& name)
+ : ctx{ctx}, num_channels{num_channels_} {
+
+ if (num_channels == 6) {
+ // 6-channel audio does not seem to work with cubeb + SDL, so we downsample this to 2
+ // channel for now
+ is_6_channel = true;
+ num_channels = 2;
+ }
+
+ cubeb_stream_params params{};
+ params.rate = sample_rate;
+ params.channels = num_channels;
params.format = CUBEB_SAMPLE_S16NE;
- params.layout = CUBEB_LAYOUT_STEREO;
+ params.layout = num_channels == 1 ? CUBEB_LAYOUT_MONO : CUBEB_LAYOUT_STEREO;
- u32 minimum_latency = 0;
+ u32 minimum_latency{};
if (cubeb_get_min_latency(ctx, &params, &minimum_latency) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error getting minimum latency");
}
- if (cubeb_stream_init(ctx, &stream_backend, "yuzu Audio Output", nullptr, nullptr,
- output_device, &params, std::max(512u, minimum_latency),
+ if (cubeb_stream_init(ctx, &stream_backend, name.c_str(), nullptr, nullptr, output_device,
+ &params, std::max(512u, minimum_latency),
&SinkStreamImpl::DataCallback, &SinkStreamImpl::StateCallback,
this) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error initializing cubeb stream");
@@ -51,33 +62,31 @@ public:
cubeb_stream_destroy(stream_backend);
}
- void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) override {
+ void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) override {
if (!ctx) {
return;
}
- queue.reserve(queue.size() + sample_count * GetNumChannels());
+ std::lock_guard lock{queue_mutex};
- if (num_channels == 2) {
- // Copy as-is
- std::copy(samples, samples + sample_count * GetNumChannels(),
- std::back_inserter(queue));
- } else if (num_channels == 6) {
+ queue.reserve(queue.size() + samples.size() * GetNumChannels());
+
+ if (is_6_channel) {
// Downsample 6 channels to 2
- const size_t sample_count_copy_size = sample_count * num_channels * 2;
+ const size_t sample_count_copy_size = samples.size() * 2;
queue.reserve(sample_count_copy_size);
- for (size_t i = 0; i < sample_count * num_channels; i += num_channels) {
+ for (size_t i = 0; i < samples.size(); i += num_channels) {
queue.push_back(samples[i]);
queue.push_back(samples[i + 1]);
}
} else {
- ASSERT_MSG(false, "Unimplemented");
+ // Copy as-is
+ std::copy(samples.begin(), samples.end(), std::back_inserter(queue));
}
}
u32 GetNumChannels() const {
- // Only support 2-channel stereo output for now
- return 2;
+ return num_channels;
}
private:
@@ -85,7 +94,10 @@ private:
cubeb* ctx{};
cubeb_stream* stream_backend{};
+ u32 num_channels{};
+ bool is_6_channel{};
+ std::mutex queue_mutex;
std::vector<s16> queue;
static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer,
@@ -129,8 +141,10 @@ CubebSink::~CubebSink() {
cubeb_destroy(ctx);
}
-SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels) {
- sink_streams.push_back(std::make_unique<SinkStreamImpl>(ctx, output_device));
+SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels,
+ const std::string& name) {
+ sink_streams.push_back(
+ std::make_unique<SinkStreamImpl>(ctx, sample_rate, num_channels, output_device, name));
return *sink_streams.back();
}
@@ -143,6 +157,8 @@ long SinkStreamImpl::DataCallback(cubeb_stream* stream, void* user_data, const v
return {};
}
+ std::lock_guard lock{impl->queue_mutex};
+
const size_t frames_to_write{
std::min(impl->queue.size() / impl->GetNumChannels(), static_cast<size_t>(num_frames))};
diff --git a/src/audio_core/cubeb_sink.h b/src/audio_core/cubeb_sink.h
index d07113f1f..59cbf05e9 100644
--- a/src/audio_core/cubeb_sink.h
+++ b/src/audio_core/cubeb_sink.h
@@ -18,7 +18,8 @@ public:
explicit CubebSink(std::string device_id);
~CubebSink() override;
- SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) override;
+ SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels,
+ const std::string& name) override;
private:
cubeb* ctx{};
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h
index 2e04438f7..f235d93e5 100644
--- a/src/audio_core/null_sink.h
+++ b/src/audio_core/null_sink.h
@@ -13,14 +13,14 @@ public:
explicit NullSink(std::string){};
~NullSink() override = default;
- SinkStream& AcquireSinkStream(u32 /*sample_rate*/, u32 /*num_channels*/) override {
+ SinkStream& AcquireSinkStream(u32 /*sample_rate*/, u32 /*num_channels*/,
+ const std::string& /*name*/) override {
return null_sink_stream;
}
private:
struct NullSinkStreamImpl final : SinkStream {
- void EnqueueSamples(u32 /*num_channels*/, const s16* /*samples*/,
- size_t /*sample_count*/) override {}
+ void EnqueueSamples(u32 /*num_channels*/, const std::vector<s16>& /*samples*/) override {}
} null_sink_stream;
};
diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h
index d1bb98c3d..95c7b2b6e 100644
--- a/src/audio_core/sink.h
+++ b/src/audio_core/sink.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <string>
#include "audio_core/sink_stream.h"
#include "common/common_types.h"
@@ -21,7 +22,8 @@ constexpr char auto_device_name[] = "auto";
class Sink {
public:
virtual ~Sink() = default;
- virtual SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) = 0;
+ virtual SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels,
+ const std::string& name) = 0;
};
using SinkPtr = std::unique_ptr<Sink>;
diff --git a/src/audio_core/sink_stream.h b/src/audio_core/sink_stream.h
index e7a3f01b0..41b6736d8 100644
--- a/src/audio_core/sink_stream.h
+++ b/src/audio_core/sink_stream.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <vector>
#include "common/common_types.h"
@@ -22,9 +23,8 @@ public:
* Feed stereo samples to sink.
* @param num_channels Number of channels used.
* @param samples Samples in interleaved stereo PCM16 format.
- * @param sample_count Number of samples.
*/
- virtual void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) = 0;
+ virtual void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) = 0;
};
using SinkStreamPtr = std::unique_ptr<SinkStream>;
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index a0045b7a1..ad9e2915c 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -32,17 +32,13 @@ u32 Stream::GetNumChannels() const {
return {};
}
-u32 Stream::GetSampleSize() const {
- return GetNumChannels() * 2;
-}
-
Stream::Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback,
- SinkStream& sink_stream)
+ SinkStream& sink_stream, std::string&& name_)
: sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
- sink_stream{sink_stream} {
+ sink_stream{sink_stream}, name{std::move(name_)} {
release_event = CoreTiming::RegisterEvent(
- "Stream::Release", [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); });
+ name, [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); });
}
void Stream::Play() {
@@ -55,17 +51,15 @@ void Stream::Stop() {
}
s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const {
- const size_t num_samples{buffer.GetData().size() / GetSampleSize()};
+ const size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate);
}
-static std::vector<s16> GetVolumeAdjustedSamples(const std::vector<u8>& data) {
- std::vector<s16> samples(data.size() / sizeof(s16));
- std::memcpy(samples.data(), data.data(), data.size());
+static void VolumeAdjustSamples(std::vector<s16>& samples) {
const float volume{std::clamp(Settings::values.volume, 0.0f, 1.0f)};
if (volume == 1.0f) {
- return samples;
+ return;
}
// Implementation of a volume slider with a dynamic range of 60 dB
@@ -73,8 +67,6 @@ static std::vector<s16> GetVolumeAdjustedSamples(const std::vector<u8>& data) {
for (auto& sample : samples) {
sample = static_cast<s16>(sample * volume_scale_factor);
}
-
- return samples;
}
void Stream::PlayNextBuffer() {
@@ -96,14 +88,14 @@ void Stream::PlayNextBuffer() {
active_buffer = queued_buffers.front();
queued_buffers.pop();
- const size_t sample_count{active_buffer->GetData().size() / GetSampleSize()};
- sink_stream.EnqueueSamples(
- GetNumChannels(), GetVolumeAdjustedSamples(active_buffer->GetData()).data(), sample_count);
+ VolumeAdjustSamples(active_buffer->Samples());
+ sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {});
}
void Stream::ReleaseActiveBuffer() {
+ ASSERT(active_buffer);
released_buffers.push(std::move(active_buffer));
release_callback();
PlayNextBuffer();
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 35253920e..049b92ca9 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -6,6 +6,7 @@
#include <functional>
#include <memory>
+#include <string>
#include <vector>
#include <queue>
@@ -33,7 +34,7 @@ public:
using ReleaseCallback = std::function<void()>;
Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback,
- SinkStream& sink_stream);
+ SinkStream& sink_stream, std::string&& name_);
/// Plays the audio stream
void Play();
@@ -68,9 +69,6 @@ public:
/// Gets the number of channels
u32 GetNumChannels() const;
- /// Gets the sample size in bytes
- u32 GetSampleSize() const;
-
private:
/// Current state of the stream
enum class State {
@@ -96,6 +94,7 @@ private:
std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
SinkStream& sink_stream; ///< Output sink for the stream
+ std::string name; ///< Name of the stream, must be unique
};
using StreamPtr = std::shared_ptr<Stream>;
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index d5d4f6f82..939b8a7d3 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -29,8 +29,6 @@ add_library(common STATIC
assert.h
bit_field.h
bit_set.h
- break_points.cpp
- break_points.h
cityhash.cpp
cityhash.h
color.h
diff --git a/src/common/alignment.h b/src/common/alignment.h
index b77da4a92..b9dd38746 100644
--- a/src/common/alignment.h
+++ b/src/common/alignment.h
@@ -9,13 +9,13 @@ namespace Common {
template <typename T>
constexpr T AlignUp(T value, size_t size) {
- static_assert(std::is_unsigned<T>::value, "T must be an unsigned value.");
+ static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>(value + (size - value % size) % size);
}
template <typename T>
constexpr T AlignDown(T value, size_t size) {
- static_assert(std::is_unsigned<T>::value, "T must be an unsigned value.");
+ static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>(value - value % size);
}
diff --git a/src/common/bit_set.h b/src/common/bit_set.h
index 84e3cbe58..5a197d8c1 100644
--- a/src/common/bit_set.h
+++ b/src/common/bit_set.h
@@ -96,7 +96,7 @@ static inline int LeastSignificantSetBit(u64 val) {
template <typename IntTy>
class BitSet {
- static_assert(!std::is_signed<IntTy>::value, "BitSet should not be used with signed types");
+ static_assert(!std::is_signed_v<IntTy>, "BitSet should not be used with signed types");
public:
// A reference to a particular bit, returned from operator[].
diff --git a/src/common/break_points.cpp b/src/common/break_points.cpp
deleted file mode 100644
index fa367a4ca..000000000
--- a/src/common/break_points.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <sstream>
-#include "common/break_points.h"
-
-bool BreakPoints::IsAddressBreakPoint(u32 iAddress) const {
- auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress; };
- auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond);
- return it != m_BreakPoints.end();
-}
-
-bool BreakPoints::IsTempBreakPoint(u32 iAddress) const {
- auto cond = [&iAddress](const TBreakPoint& bp) {
- return bp.iAddress == iAddress && bp.bTemporary;
- };
- auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond);
- return it != m_BreakPoints.end();
-}
-
-BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const {
- TBreakPointsStr bps;
- for (auto breakpoint : m_BreakPoints) {
- if (!breakpoint.bTemporary) {
- std::stringstream bp;
- bp << std::hex << breakpoint.iAddress << " " << (breakpoint.bOn ? "n" : "");
- bps.push_back(bp.str());
- }
- }
-
- return bps;
-}
-
-void BreakPoints::AddFromStrings(const TBreakPointsStr& bps) {
- for (auto bps_item : bps) {
- TBreakPoint bp;
- std::stringstream bpstr;
- bpstr << std::hex << bps_item;
- bpstr >> bp.iAddress;
- bp.bOn = bps_item.find("n") != bps_item.npos;
- bp.bTemporary = false;
- Add(bp);
- }
-}
-
-void BreakPoints::Add(const TBreakPoint& bp) {
- if (!IsAddressBreakPoint(bp.iAddress)) {
- m_BreakPoints.push_back(bp);
- // if (jit)
- // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
- }
-}
-
-void BreakPoints::Add(u32 em_address, bool temp) {
- if (!IsAddressBreakPoint(em_address)) // only add new addresses
- {
- TBreakPoint pt; // breakpoint settings
- pt.bOn = true;
- pt.bTemporary = temp;
- pt.iAddress = em_address;
-
- m_BreakPoints.push_back(pt);
-
- // if (jit)
- // jit->GetBlockCache()->InvalidateICache(em_address, 4);
- }
-}
-
-void BreakPoints::Remove(u32 em_address) {
- auto cond = [&em_address](const TBreakPoint& bp) { return bp.iAddress == em_address; };
- auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond);
- if (it != m_BreakPoints.end())
- m_BreakPoints.erase(it);
-}
-
-void BreakPoints::Clear() {
- // if (jit)
- //{
- // std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(),
- // [](const TBreakPoint& bp)
- // {
- // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
- // }
- // );
- //}
-
- m_BreakPoints.clear();
-}
diff --git a/src/common/break_points.h b/src/common/break_points.h
deleted file mode 100644
index e15b9f842..000000000
--- a/src/common/break_points.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <string>
-#include <vector>
-#include "common/common_types.h"
-
-class DebugInterface;
-
-struct TBreakPoint {
- u32 iAddress;
- bool bOn;
- bool bTemporary;
-};
-
-// Code breakpoints.
-class BreakPoints {
-public:
- typedef std::vector<TBreakPoint> TBreakPoints;
- typedef std::vector<std::string> TBreakPointsStr;
-
- const TBreakPoints& GetBreakPoints() {
- return m_BreakPoints;
- }
-
- TBreakPointsStr GetStrings() const;
- void AddFromStrings(const TBreakPointsStr& bps);
-
- // is address breakpoint
- bool IsAddressBreakPoint(u32 iAddress) const;
- bool IsTempBreakPoint(u32 iAddress) const;
-
- // Add BreakPoint
- void Add(u32 em_address, bool temp = false);
- void Add(const TBreakPoint& bp);
-
- // Remove Breakpoint
- void Remove(u32 iAddress);
- void Clear();
-
- void DeleteByAddress(u32 Address);
-
-private:
- TBreakPoints m_BreakPoints;
- u32 m_iBreakOnCount;
-};
diff --git a/src/common/color.h b/src/common/color.h
index 24a445dac..0379040be 100644
--- a/src/common/color.h
+++ b/src/common/color.h
@@ -4,6 +4,8 @@
#pragma once
+#include <cstring>
+
#include "common/common_types.h"
#include "common/swap.h"
#include "common/vector_math.h"
@@ -55,7 +57,7 @@ constexpr u8 Convert8To6(u8 value) {
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
*/
-inline const Math::Vec4<u8> DecodeRGBA8(const u8* bytes) {
+inline Math::Vec4<u8> DecodeRGBA8(const u8* bytes) {
return {bytes[3], bytes[2], bytes[1], bytes[0]};
}
@@ -64,7 +66,7 @@ inline const Math::Vec4<u8> DecodeRGBA8(const u8* bytes) {
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
*/
-inline const Math::Vec4<u8> DecodeRGB8(const u8* bytes) {
+inline Math::Vec4<u8> DecodeRGB8(const u8* bytes) {
return {bytes[2], bytes[1], bytes[0], 255};
}
@@ -73,7 +75,7 @@ inline const Math::Vec4<u8> DecodeRGB8(const u8* bytes) {
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
*/
-inline const Math::Vec4<u8> DecodeRG8(const u8* bytes) {
+inline Math::Vec4<u8> DecodeRG8(const u8* bytes) {
return {bytes[1], bytes[0], 0, 255};
}
@@ -82,8 +84,9 @@ inline const Math::Vec4<u8> DecodeRG8(const u8* bytes) {
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
*/
-inline const Math::Vec4<u8> DecodeRGB565(const u8* bytes) {
- const u16_le pixel = *reinterpret_cast<const u16_le*>(bytes);
+inline Math::Vec4<u8> DecodeRGB565(const u8* bytes) {
+ u16_le pixel;
+ std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F),
Convert5To8(pixel & 0x1F), 255};
}
@@ -93,8 +96,9 @@ inline const Math::Vec4<u8> DecodeRGB565(const u8* bytes) {
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
*/
-inline const Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
- const u16_le pixel = *reinterpret_cast<const u16_le*>(bytes);
+inline Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
+ u16_le pixel;
+ std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F),
Convert5To8((pixel >> 1) & 0x1F), Convert1To8(pixel & 0x1)};
}
@@ -104,8 +108,9 @@ inline const Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
*/
-inline const Math::Vec4<u8> DecodeRGBA4(const u8* bytes) {
- const u16_le pixel = *reinterpret_cast<const u16_le*>(bytes);
+inline Math::Vec4<u8> DecodeRGBA4(const u8* bytes) {
+ u16_le pixel;
+ std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF),
Convert4To8((pixel >> 4) & 0xF), Convert4To8(pixel & 0xF)};
}
@@ -116,7 +121,9 @@ inline const Math::Vec4<u8> DecodeRGBA4(const u8* bytes) {
* @return Depth value as an u32
*/
inline u32 DecodeD16(const u8* bytes) {
- return *reinterpret_cast<const u16_le*>(bytes);
+ u16_le data;
+ std::memcpy(&data, bytes, sizeof(data));
+ return data;
}
/**
@@ -133,7 +140,7 @@ inline u32 DecodeD24(const u8* bytes) {
* @param bytes Pointer to encoded source values
* @return Resulting values stored as a Math::Vec2
*/
-inline const Math::Vec2<u32> DecodeD24S8(const u8* bytes) {
+inline Math::Vec2<u32> DecodeD24S8(const u8* bytes) {
return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]};
}
@@ -175,8 +182,10 @@ inline void EncodeRG8(const Math::Vec4<u8>& color, u8* bytes) {
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGB565(const Math::Vec4<u8>& color, u8* bytes) {
- *reinterpret_cast<u16_le*>(bytes) =
+ const u16_le data =
(Convert8To5(color.r()) << 11) | (Convert8To6(color.g()) << 5) | Convert8To5(color.b());
+
+ std::memcpy(bytes, &data, sizeof(data));
}
/**
@@ -185,9 +194,10 @@ inline void EncodeRGB565(const Math::Vec4<u8>& color, u8* bytes) {
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGB5A1(const Math::Vec4<u8>& color, u8* bytes) {
- *reinterpret_cast<u16_le*>(bytes) = (Convert8To5(color.r()) << 11) |
- (Convert8To5(color.g()) << 6) |
- (Convert8To5(color.b()) << 1) | Convert8To1(color.a());
+ const u16_le data = (Convert8To5(color.r()) << 11) | (Convert8To5(color.g()) << 6) |
+ (Convert8To5(color.b()) << 1) | Convert8To1(color.a());
+
+ std::memcpy(bytes, &data, sizeof(data));
}
/**
@@ -196,9 +206,10 @@ inline void EncodeRGB5A1(const Math::Vec4<u8>& color, u8* bytes) {
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGBA4(const Math::Vec4<u8>& color, u8* bytes) {
- *reinterpret_cast<u16_le*>(bytes) = (Convert8To4(color.r()) << 12) |
- (Convert8To4(color.g()) << 8) |
- (Convert8To4(color.b()) << 4) | Convert8To4(color.a());
+ const u16 data = (Convert8To4(color.r()) << 12) | (Convert8To4(color.g()) << 8) |
+ (Convert8To4(color.b()) << 4) | Convert8To4(color.a());
+
+ std::memcpy(bytes, &data, sizeof(data));
}
/**
@@ -207,7 +218,8 @@ inline void EncodeRGBA4(const Math::Vec4<u8>& color, u8* bytes) {
* @param bytes Pointer where to store the encoded value
*/
inline void EncodeD16(u32 value, u8* bytes) {
- *reinterpret_cast<u16_le*>(bytes) = value & 0xFFFF;
+ const u16_le data = static_cast<u16>(value);
+ std::memcpy(bytes, &data, sizeof(data));
}
/**
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 7aeda737f..3ce590062 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -884,11 +884,21 @@ std::string_view RemoveTrailingSlash(std::string_view path) {
return path;
}
-std::string SanitizePath(std::string_view path_) {
+std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
std::string path(path_);
- std::replace(path.begin(), path.end(), '\\', '/');
+ char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\';
+ char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/';
+
+ if (directory_separator == DirectorySeparator::PlatformDefault) {
+#ifdef _WIN32
+ type1 = '/';
+ type2 = '\\';
+#endif
+ }
+
+ std::replace(path.begin(), path.end(), type1, type2);
path.erase(std::unique(path.begin(), path.end(),
- [](char c1, char c2) { return c1 == '/' && c2 == '/'; }),
+ [type2](char c1, char c2) { return c1 == type2 && c2 == type2; }),
path.end());
return std::string(RemoveTrailingSlash(path));
}
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 28697d527..2711872ae 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -8,6 +8,7 @@
#include <cstdio>
#include <fstream>
#include <functional>
+#include <limits>
#include <string>
#include <string_view>
#include <type_traits>
@@ -181,8 +182,12 @@ std::vector<T> SliceVector(const std::vector<T>& vector, size_t first, size_t la
return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
}
-// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'.
-std::string SanitizePath(std::string_view path);
+enum class DirectorySeparator { ForwardSlash, BackwardSlash, PlatformDefault };
+
+// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
+// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
+std::string SanitizePath(std::string_view path,
+ DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
// simple wrapper for cstdlib file functions to
// hopefully will make error checking easier
@@ -207,39 +212,42 @@ public:
template <typename T>
size_t ReadArray(T* data, size_t length) const {
- static_assert(std::is_trivially_copyable<T>(),
+ static_assert(std::is_trivially_copyable_v<T>,
"Given array does not consist of trivially copyable objects");
- if (!IsOpen())
- return -1;
+ if (!IsOpen()) {
+ return std::numeric_limits<size_t>::max();
+ }
return std::fread(data, sizeof(T), length, m_file);
}
template <typename T>
size_t WriteArray(const T* data, size_t length) {
- static_assert(std::is_trivially_copyable<T>(),
+ static_assert(std::is_trivially_copyable_v<T>,
"Given array does not consist of trivially copyable objects");
- if (!IsOpen())
- return -1;
+ if (!IsOpen()) {
+ return std::numeric_limits<size_t>::max();
+ }
+
return std::fwrite(data, sizeof(T), length, m_file);
}
template <typename T>
size_t ReadBytes(T* data, size_t length) const {
- static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
+ static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
return ReadArray(reinterpret_cast<char*>(data), length);
}
template <typename T>
size_t WriteBytes(const T* data, size_t length) {
- static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable");
+ static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
return WriteArray(reinterpret_cast<const char*>(data), length);
}
template <typename T>
size_t WriteObject(const T& object) {
- static_assert(!std::is_pointer<T>::value, "Given object is a pointer");
+ static_assert(!std::is_pointer_v<T>, "WriteObject arguments must not be a pointer");
return WriteArray(&object, 1);
}
diff --git a/src/common/hash.h b/src/common/hash.h
index 73c326980..2c761e545 100644
--- a/src/common/hash.h
+++ b/src/common/hash.h
@@ -28,7 +28,7 @@ static inline u64 ComputeHash64(const void* data, size_t len) {
*/
template <typename T>
static inline u64 ComputeStructHash64(const T& data) {
- static_assert(std::is_trivially_copyable<T>(),
+ static_assert(std::is_trivially_copyable_v<T>,
"Type passed to ComputeStructHash64 must be trivially copyable");
return ComputeHash64(&data, sizeof(data));
}
@@ -38,7 +38,7 @@ template <typename T>
struct HashableStruct {
// In addition to being trivially copyable, T must also have a trivial default constructor,
// because any member initialization would be overridden by memset
- static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial");
+ static_assert(std::is_trivial_v<T>, "Type passed to HashableStruct must be trivial");
/*
* We use a union because "implicitly-defined copy/move constructor for a union X copies the
* object representation of X." and "implicitly-defined copy assignment operator for a union X
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 816414e8d..1323f8d0f 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -171,15 +171,21 @@ void FileBackend::Write(const Entry& entry) {
SUB(Service, ARP) \
SUB(Service, BCAT) \
SUB(Service, BPC) \
+ SUB(Service, BTDRV) \
SUB(Service, BTM) \
SUB(Service, Capture) \
+ SUB(Service, ERPT) \
+ SUB(Service, ETicket) \
+ SUB(Service, EUPLD) \
SUB(Service, Fatal) \
SUB(Service, FGM) \
SUB(Service, Friend) \
SUB(Service, FS) \
+ SUB(Service, GRC) \
SUB(Service, HID) \
SUB(Service, LBL) \
SUB(Service, LDN) \
+ SUB(Service, LDR) \
SUB(Service, LM) \
SUB(Service, Migration) \
SUB(Service, Mii) \
@@ -188,11 +194,13 @@ void FileBackend::Write(const Entry& entry) {
SUB(Service, NFC) \
SUB(Service, NFP) \
SUB(Service, NIFM) \
+ SUB(Service, NIM) \
SUB(Service, NS) \
SUB(Service, NVDRV) \
SUB(Service, PCIE) \
SUB(Service, PCTL) \
SUB(Service, PCV) \
+ SUB(Service, PM) \
SUB(Service, PREPO) \
SUB(Service, PSC) \
SUB(Service, SET) \
@@ -200,6 +208,7 @@ void FileBackend::Write(const Entry& entry) {
SUB(Service, SPL) \
SUB(Service, SSL) \
SUB(Service, Time) \
+ SUB(Service, USB) \
SUB(Service, VI) \
SUB(Service, WLAN) \
CLS(HW) \
@@ -293,13 +302,14 @@ Backend* GetBackend(std::string_view backend_name) {
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
unsigned int line_num, const char* function, const char* format,
const fmt::format_args& args) {
- auto filter = Impl::Instance().GetGlobalFilter();
+ auto& instance = Impl::Instance();
+ const auto& filter = instance.GetGlobalFilter();
if (!filter.CheckMessage(log_class, log_level))
return;
Entry entry =
CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args));
- Impl::Instance().PushEntry(std::move(entry));
+ instance.PushEntry(std::move(entry));
}
} // namespace Log
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 7ab5277ea..e12f47f8f 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -58,15 +58,21 @@ enum class Class : ClassType {
Service_Audio, ///< The Audio (Audio control) service
Service_BCAT, ///< The BCAT service
Service_BPC, ///< The BPC service
+ Service_BTDRV, ///< The Bluetooth driver service
Service_BTM, ///< The BTM service
Service_Capture, ///< The capture service
+ Service_ERPT, ///< The error reporting service
+ Service_ETicket, ///< The ETicket service
+ Service_EUPLD, ///< The error upload service
Service_Fatal, ///< The Fatal service
Service_FGM, ///< The FGM service
Service_Friend, ///< The friend service
Service_FS, ///< The FS (Filesystem) service
+ Service_GRC, ///< The game recording service
Service_HID, ///< The HID (Human interface device) service
Service_LBL, ///< The LBL (LCD backlight) service
Service_LDN, ///< The LDN (Local domain network) service
+ Service_LDR, ///< The loader service
Service_LM, ///< The LM (Logger) service
Service_Migration, ///< The migration service
Service_Mii, ///< The Mii service
@@ -75,11 +81,13 @@ enum class Class : ClassType {
Service_NFC, ///< The NFC (Near-field communication) service
Service_NFP, ///< The NFP service
Service_NIFM, ///< The NIFM (Network interface) service
+ Service_NIM, ///< The NIM service
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
Service_PCIE, ///< The PCIe service
Service_PCTL, ///< The PCTL (Parental control) service
Service_PCV, ///< The PCV service
+ Service_PM, ///< The PM service
Service_PREPO, ///< The PREPO (Play report) service
Service_PSC, ///< The PSC service
Service_SET, ///< The SET (Settings) service
@@ -87,6 +95,7 @@ enum class Class : ClassType {
Service_SPL, ///< The SPL service
Service_SSL, ///< The SSL service
Service_Time, ///< The time service
+ Service_USB, ///< The USB (Universal Serial Bus) service
Service_VI, ///< The VI (Video interface) service
Service_WLAN, ///< The WLAN (Wireless local area network) service
HW, ///< Low-level hardware emulation
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h
index 38a450d69..133122c5f 100644
--- a/src/common/thread_queue_list.h
+++ b/src/common/thread_queue_list.h
@@ -16,7 +16,7 @@ struct ThreadQueueList {
// (dynamically resizable) circular buffers to remove their overhead when
// inserting and popping.
- typedef unsigned int Priority;
+ using Priority = unsigned int;
// Number of priority levels. (Valid levels are [0..NUM_QUEUES).)
static const Priority NUM_QUEUES = N;
@@ -26,9 +26,9 @@ struct ThreadQueueList {
}
// Only for debugging, returns priority level.
- Priority contains(const T& uid) {
+ Priority contains(const T& uid) const {
for (Priority i = 0; i < NUM_QUEUES; ++i) {
- Queue& cur = queues[i];
+ const Queue& cur = queues[i];
if (std::find(cur.data.cbegin(), cur.data.cend(), uid) != cur.data.cend()) {
return i;
}
@@ -37,8 +37,8 @@ struct ThreadQueueList {
return -1;
}
- T get_first() {
- Queue* cur = first;
+ T get_first() const {
+ const Queue* cur = first;
while (cur != nullptr) {
if (!cur->data.empty()) {
return cur->data.front();
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index cca43bd4c..8feb49941 100644
--- a/src/common/vector_math.h
+++ b/src/common/vector_math.h
@@ -43,139 +43,135 @@ template <typename T>
class Vec4;
template <typename T>
-static inline Vec2<T> MakeVec(const T& x, const T& y);
-template <typename T>
-static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z);
-template <typename T>
-static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w);
-
-template <typename T>
class Vec2 {
public:
T x{};
T y{};
- Vec2() = default;
- Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
+ constexpr Vec2() = default;
+ constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
template <typename T2>
- Vec2<T2> Cast() const {
- return Vec2<T2>((T2)x, (T2)y);
+ constexpr Vec2<T2> Cast() const {
+ return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
}
- static Vec2 AssignToAll(const T& f) {
- return Vec2<T>(f, f);
+ static constexpr Vec2 AssignToAll(const T& f) {
+ return Vec2{f, f};
}
- Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
- return MakeVec(x + other.x, y + other.y);
+ constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
+ return {x + other.x, y + other.y};
}
- void operator+=(const Vec2& other) {
+ constexpr Vec2& operator+=(const Vec2& other) {
x += other.x;
y += other.y;
+ return *this;
}
- Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
- return MakeVec(x - other.x, y - other.y);
+ constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
+ return {x - other.x, y - other.y};
}
- void operator-=(const Vec2& other) {
+ constexpr Vec2& operator-=(const Vec2& other) {
x -= other.x;
y -= other.y;
+ return *this;
}
template <typename U = T>
- Vec2<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
- return MakeVec(-x, -y);
+ constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
+ return {-x, -y};
}
- Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
- return MakeVec(x * other.x, y * other.y);
+ constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
+ return {x * other.x, y * other.y};
}
+
template <typename V>
- Vec2<decltype(T{} * V{})> operator*(const V& f) const {
- return MakeVec(x * f, y * f);
+ constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
+ return {x * f, y * f};
}
+
template <typename V>
- void operator*=(const V& f) {
+ constexpr Vec2& operator*=(const V& f) {
*this = *this * f;
+ return *this;
}
+
template <typename V>
- Vec2<decltype(T{} / V{})> operator/(const V& f) const {
- return MakeVec(x / f, y / f);
+ constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
+ return {x / f, y / f};
}
+
template <typename V>
- void operator/=(const V& f) {
+ constexpr Vec2& operator/=(const V& f) {
*this = *this / f;
+ return *this;
}
- T Length2() const {
+ constexpr T Length2() const {
return x * x + y * y;
}
// Only implemented for T=float
float Length() const;
- void SetLength(const float l);
- Vec2 WithLength(const float l) const;
- float Distance2To(Vec2& other);
- Vec2 Normalized() const;
float Normalize(); // returns the previous length, which is often useful
- T& operator[](int i) // allow vector[1] = 3 (vector.y=3)
- {
+ constexpr T& operator[](std::size_t i) {
return *((&x) + i);
}
- T operator[](const int i) const {
+ constexpr const T& operator[](std::size_t i) const {
return *((&x) + i);
}
- void SetZero() {
+ constexpr void SetZero() {
x = 0;
y = 0;
}
// Common aliases: UV (texel coordinates), ST (texture coordinates)
- T& u() {
+ constexpr T& u() {
return x;
}
- T& v() {
+ constexpr T& v() {
return y;
}
- T& s() {
+ constexpr T& s() {
return x;
}
- T& t() {
+ constexpr T& t() {
return y;
}
- const T& u() const {
+ constexpr const T& u() const {
return x;
}
- const T& v() const {
+ constexpr const T& v() const {
return y;
}
- const T& s() const {
+ constexpr const T& s() const {
return x;
}
- const T& t() const {
+ constexpr const T& t() const {
return y;
}
// swizzlers - create a subvector of specific components
- const Vec2 yx() const {
+ constexpr Vec2 yx() const {
return Vec2(y, x);
}
- const Vec2 vu() const {
+ constexpr Vec2 vu() const {
return Vec2(y, x);
}
- const Vec2 ts() const {
+ constexpr Vec2 ts() const {
return Vec2(y, x);
}
};
template <typename T, typename V>
-Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
+constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
return Vec2<T>(f * vec.x, f * vec.y);
}
-typedef Vec2<float> Vec2f;
+using Vec2f = Vec2<float>;
template <>
inline float Vec2<float>::Length() const {
@@ -196,147 +192,151 @@ public:
T y{};
T z{};
- Vec3() = default;
- Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
+ constexpr Vec3() = default;
+ constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
template <typename T2>
- Vec3<T2> Cast() const {
- return MakeVec<T2>((T2)x, (T2)y, (T2)z);
+ constexpr Vec3<T2> Cast() const {
+ return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
}
- // Only implemented for T=int and T=float
- static Vec3 FromRGB(unsigned int rgb);
- unsigned int ToRGB() const; // alpha bits set to zero
-
- static Vec3 AssignToAll(const T& f) {
- return MakeVec(f, f, f);
+ static constexpr Vec3 AssignToAll(const T& f) {
+ return Vec3(f, f, f);
}
- Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
- return MakeVec(x + other.x, y + other.y, z + other.z);
+ constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
+ return {x + other.x, y + other.y, z + other.z};
}
- void operator+=(const Vec3& other) {
+
+ constexpr Vec3& operator+=(const Vec3& other) {
x += other.x;
y += other.y;
z += other.z;
+ return *this;
}
- Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
- return MakeVec(x - other.x, y - other.y, z - other.z);
+
+ constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
+ return {x - other.x, y - other.y, z - other.z};
}
- void operator-=(const Vec3& other) {
+
+ constexpr Vec3& operator-=(const Vec3& other) {
x -= other.x;
y -= other.y;
z -= other.z;
+ return *this;
}
template <typename U = T>
- Vec3<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
- return MakeVec(-x, -y, -z);
+ constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
+ return {-x, -y, -z};
}
- Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
- return MakeVec(x * other.x, y * other.y, z * other.z);
+
+ constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
+ return {x * other.x, y * other.y, z * other.z};
}
+
template <typename V>
- Vec3<decltype(T{} * V{})> operator*(const V& f) const {
- return MakeVec(x * f, y * f, z * f);
+ constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
+ return {x * f, y * f, z * f};
}
+
template <typename V>
- void operator*=(const V& f) {
+ constexpr Vec3& operator*=(const V& f) {
*this = *this * f;
+ return *this;
}
template <typename V>
- Vec3<decltype(T{} / V{})> operator/(const V& f) const {
- return MakeVec(x / f, y / f, z / f);
+ constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
+ return {x / f, y / f, z / f};
}
+
template <typename V>
- void operator/=(const V& f) {
+ constexpr Vec3& operator/=(const V& f) {
*this = *this / f;
+ return *this;
}
- T Length2() const {
+ constexpr T Length2() const {
return x * x + y * y + z * z;
}
// Only implemented for T=float
float Length() const;
- void SetLength(const float l);
- Vec3 WithLength(const float l) const;
- float Distance2To(Vec3& other);
Vec3 Normalized() const;
float Normalize(); // returns the previous length, which is often useful
- T& operator[](int i) // allow vector[2] = 3 (vector.z=3)
- {
+ constexpr T& operator[](std::size_t i) {
return *((&x) + i);
}
- T operator[](const int i) const {
+
+ constexpr const T& operator[](std::size_t i) const {
return *((&x) + i);
}
- void SetZero() {
+ constexpr void SetZero() {
x = 0;
y = 0;
z = 0;
}
// Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
- T& u() {
+ constexpr T& u() {
return x;
}
- T& v() {
+ constexpr T& v() {
return y;
}
- T& w() {
+ constexpr T& w() {
return z;
}
- T& r() {
+ constexpr T& r() {
return x;
}
- T& g() {
+ constexpr T& g() {
return y;
}
- T& b() {
+ constexpr T& b() {
return z;
}
- T& s() {
+ constexpr T& s() {
return x;
}
- T& t() {
+ constexpr T& t() {
return y;
}
- T& q() {
+ constexpr T& q() {
return z;
}
- const T& u() const {
+ constexpr const T& u() const {
return x;
}
- const T& v() const {
+ constexpr const T& v() const {
return y;
}
- const T& w() const {
+ constexpr const T& w() const {
return z;
}
- const T& r() const {
+ constexpr const T& r() const {
return x;
}
- const T& g() const {
+ constexpr const T& g() const {
return y;
}
- const T& b() const {
+ constexpr const T& b() const {
return z;
}
- const T& s() const {
+ constexpr const T& s() const {
return x;
}
- const T& t() const {
+ constexpr const T& t() const {
return y;
}
- const T& q() const {
+ constexpr const T& q() const {
return z;
}
@@ -345,7 +345,7 @@ public:
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
// component names (x<->r) and permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) \
- const Vec2<T> name() const { \
+ constexpr Vec2<T> name() const { \
return Vec2<T>(a, b); \
}
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
@@ -366,7 +366,7 @@ public:
};
template <typename T, typename V>
-Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
+constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
}
@@ -387,7 +387,7 @@ inline float Vec3<float>::Normalize() {
return length;
}
-typedef Vec3<float> Vec3f;
+using Vec3f = Vec3<float>;
template <typename T>
class Vec4 {
@@ -397,86 +397,88 @@ public:
T z{};
T w{};
- Vec4() = default;
- Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}
+ constexpr Vec4() = default;
+ constexpr Vec4(const T& x_, const T& y_, const T& z_, const T& w_)
+ : x(x_), y(y_), z(z_), w(w_) {}
template <typename T2>
- Vec4<T2> Cast() const {
- return Vec4<T2>((T2)x, (T2)y, (T2)z, (T2)w);
+ constexpr Vec4<T2> Cast() const {
+ return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
+ static_cast<T2>(w));
}
- // Only implemented for T=int and T=float
- static Vec4 FromRGBA(unsigned int rgba);
- unsigned int ToRGBA() const;
-
- static Vec4 AssignToAll(const T& f) {
- return Vec4<T>(f, f, f, f);
+ static constexpr Vec4 AssignToAll(const T& f) {
+ return Vec4(f, f, f, f);
}
- Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
- return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w);
+ constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
+ return {x + other.x, y + other.y, z + other.z, w + other.w};
}
- void operator+=(const Vec4& other) {
+
+ constexpr Vec4& operator+=(const Vec4& other) {
x += other.x;
y += other.y;
z += other.z;
w += other.w;
+ return *this;
}
- Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
- return MakeVec(x - other.x, y - other.y, z - other.z, w - other.w);
+
+ constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
+ return {x - other.x, y - other.y, z - other.z, w - other.w};
}
- void operator-=(const Vec4& other) {
+
+ constexpr Vec4& operator-=(const Vec4& other) {
x -= other.x;
y -= other.y;
z -= other.z;
w -= other.w;
+ return *this;
}
template <typename U = T>
- Vec4<std::enable_if_t<std::is_signed<U>::value, U>> operator-() const {
- return MakeVec(-x, -y, -z, -w);
+ constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
+ return {-x, -y, -z, -w};
}
- Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
- return MakeVec(x * other.x, y * other.y, z * other.z, w * other.w);
+
+ constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
+ return {x * other.x, y * other.y, z * other.z, w * other.w};
}
+
template <typename V>
- Vec4<decltype(T{} * V{})> operator*(const V& f) const {
- return MakeVec(x * f, y * f, z * f, w * f);
+ constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
+ return {x * f, y * f, z * f, w * f};
}
+
template <typename V>
- void operator*=(const V& f) {
+ constexpr Vec4& operator*=(const V& f) {
*this = *this * f;
+ return *this;
}
+
template <typename V>
- Vec4<decltype(T{} / V{})> operator/(const V& f) const {
- return MakeVec(x / f, y / f, z / f, w / f);
+ constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
+ return {x / f, y / f, z / f, w / f};
}
+
template <typename V>
- void operator/=(const V& f) {
+ constexpr Vec4& operator/=(const V& f) {
*this = *this / f;
+ return *this;
}
- T Length2() const {
+ constexpr T Length2() const {
return x * x + y * y + z * z + w * w;
}
- // Only implemented for T=float
- float Length() const;
- void SetLength(const float l);
- Vec4 WithLength(const float l) const;
- float Distance2To(Vec4& other);
- Vec4 Normalized() const;
- float Normalize(); // returns the previous length, which is often useful
-
- T& operator[](int i) // allow vector[2] = 3 (vector.z=3)
- {
+ constexpr T& operator[](std::size_t i) {
return *((&x) + i);
}
- T operator[](const int i) const {
+
+ constexpr const T& operator[](std::size_t i) const {
return *((&x) + i);
}
- void SetZero() {
+ constexpr void SetZero() {
x = 0;
y = 0;
z = 0;
@@ -484,29 +486,29 @@ public:
}
// Common alias: RGBA (colors)
- T& r() {
+ constexpr T& r() {
return x;
}
- T& g() {
+ constexpr T& g() {
return y;
}
- T& b() {
+ constexpr T& b() {
return z;
}
- T& a() {
+ constexpr T& a() {
return w;
}
- const T& r() const {
+ constexpr const T& r() const {
return x;
}
- const T& g() const {
+ constexpr const T& g() const {
return y;
}
- const T& b() const {
+ constexpr const T& b() const {
return z;
}
- const T& a() const {
+ constexpr const T& a() const {
return w;
}
@@ -518,7 +520,7 @@ public:
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
// permutations (xy<->yx)
#define _DEFINE_SWIZZLER2(a, b, name) \
- const Vec2<T> name() const { \
+ constexpr Vec2<T> name() const { \
return Vec2<T>(a, b); \
}
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
@@ -545,7 +547,7 @@ public:
#undef _DEFINE_SWIZZLER2
#define _DEFINE_SWIZZLER3(a, b, c, name) \
- const Vec3<T> name() const { \
+ constexpr Vec3<T> name() const { \
return Vec3<T>(a, b, c); \
}
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
@@ -579,51 +581,51 @@ public:
};
template <typename T, typename V>
-Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
- return MakeVec(f * vec.x, f * vec.y, f * vec.z, f * vec.w);
+constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
+ return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
}
-typedef Vec4<float> Vec4f;
+using Vec4f = Vec4<float>;
template <typename T>
-static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) {
+constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) {
return a.x * b.x + a.y * b.y;
}
template <typename T>
-static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
+constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
template <typename T>
-static inline decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
+constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
template <typename T>
-static inline Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) {
- return MakeVec(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
+constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) {
+ return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
}
// linear interpolation via float: 0.0=begin, 1.0=end
template <typename X>
-static inline decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
- const float t) {
+constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
+ const float t) {
return begin * (1.f - t) + end * t;
}
// linear interpolation via int: 0=begin, base=end
template <typename X, int base>
-static inline decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end,
- const int t) {
+constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end,
+ const int t) {
return (begin * (base - t) + end * t) / base;
}
// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
// interpolation.
template <typename X>
-inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s,
- const float t) {
+constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s,
+ const float t) {
auto y0 = Lerp(x00, x01, s);
auto y1 = Lerp(x10, x11, s);
return Lerp(y0, y1, t);
@@ -631,42 +633,42 @@ inline auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x1
// Utility vector factories
template <typename T>
-static inline Vec2<T> MakeVec(const T& x, const T& y) {
+constexpr Vec2<T> MakeVec(const T& x, const T& y) {
return Vec2<T>{x, y};
}
template <typename T>
-static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
+constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
return Vec3<T>{x, y, z};
}
template <typename T>
-static inline Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
+constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
return MakeVec(x, y, zw[0], zw[1]);
}
template <typename T>
-static inline Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
+constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
return MakeVec(xy[0], xy[1], z);
}
template <typename T>
-static inline Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
+constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
return MakeVec(x, yz[0], yz[1]);
}
template <typename T>
-static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
+constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
return Vec4<T>{x, y, z, w};
}
template <typename T>
-static inline Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
+constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
return MakeVec(xy[0], xy[1], z, w);
}
template <typename T>
-static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
+constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
return MakeVec(x, yz[0], yz[1], w);
}
@@ -674,17 +676,17 @@ static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
// out soon enough due to misuse of the returned structure.
template <typename T>
-static inline Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
+constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
return MakeVec(xy[0], xy[1], zw[0], zw[1]);
}
template <typename T>
-static inline Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
+constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
return MakeVec(xyz[0], xyz[1], xyz[2], w);
}
template <typename T>
-static inline Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
+constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
return MakeVec(x, yzw[0], yzw[1], yzw[2]);
}
diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h
index 0f52f704b..ec76e0a47 100644
--- a/src/common/x64/xbyak_util.h
+++ b/src/common/x64/xbyak_util.h
@@ -34,7 +34,7 @@ inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
template <typename T>
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
- static_assert(std::is_pointer<T>(), "Argument must be a (function) pointer.");
+ static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
size_t addr = reinterpret_cast<size_t>(f);
if (IsWithin2G(code, addr)) {
code.call(f);
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c11f017da..0b0ae5ccc 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -104,8 +104,6 @@ add_library(core STATIC
hle/lock.cpp
hle/lock.h
hle/result.h
- hle/romfs.cpp
- hle/romfs.h
hle/service/acc/acc.cpp
hle/service/acc/acc.h
hle/service/acc/acc_aa.cpp
@@ -251,6 +249,10 @@ add_library(core STATIC
hle/service/nvdrv/devices/nvhost_gpu.h
hle/service/nvdrv/devices/nvhost_nvdec.cpp
hle/service/nvdrv/devices/nvhost_nvdec.h
+ hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+ hle/service/nvdrv/devices/nvhost_nvjpg.h
+ hle/service/nvdrv/devices/nvhost_vic.cpp
+ hle/service/nvdrv/devices/nvhost_vic.h
hle/service/nvdrv/devices/nvmap.cpp
hle/service/nvdrv/devices/nvmap.h
hle/service/nvdrv/interface.cpp
@@ -315,6 +317,8 @@ add_library(core STATIC
hle/service/time/interface.h
hle/service/time/time.cpp
hle/service/time/time.h
+ hle/service/usb/usb.cpp
+ hle/service/usb/usb.h
hle/service/vi/vi.cpp
hle/service/vi/vi.h
hle/service/vi/vi_m.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index ceb3f7683..20e5200a8 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -86,7 +86,16 @@ public:
}
void AddTicks(u64 ticks) override {
- CoreTiming::AddTicks(ticks - num_interpreted_instructions);
+ // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
+ // rough approximation of the amount of executed ticks in the system, it may be thrown off
+ // if not all cores are doing a similar amount of work. Instead of doing this, we should
+ // device a way so that timing is consistent across all cores without increasing the ticks 4
+ // times.
+ u64 amortized_ticks = (ticks - num_interpreted_instructions) / Core::NUM_CPU_CORES;
+ // Always execute at least one tick.
+ amortized_ticks = std::max<u64>(amortized_ticks, 1);
+
+ CoreTiming::AddTicks(amortized_ticks);
num_interpreted_instructions = 0;
}
u64 GetTicksRemaining() override {
@@ -234,9 +243,7 @@ void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
}
void ARM_Dynarmic::PrepareReschedule() {
- if (jit->IsExecuting()) {
- jit->HaltExecution();
- }
+ jit->HaltExecution();
}
void ARM_Dynarmic::ClearInstructionCache() {
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index 4c11f35a4..6bc349460 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -203,7 +203,7 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
}
Kernel::Thread* thread = Kernel::GetCurrentThread();
SaveContext(thread->context);
- if (last_bkpt_hit || (num_instructions == 1)) {
+ if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) {
last_bkpt_hit = false;
GDBStub::Break();
GDBStub::SendTrap(thread, 5);
diff --git a/src/core/core.cpp b/src/core/core.cpp
index e01c45cdd..83d4d742b 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -62,7 +62,6 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
// execute. Otherwise, get out of the loop function.
if (GDBStub::GetCpuHaltFlag()) {
if (GDBStub::GetCpuStepFlag()) {
- GDBStub::SetCpuStepFlag(false);
tight_loop = false;
} else {
return ResultStatus::Success;
@@ -78,6 +77,10 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
}
}
+ if (GDBStub::IsServerEnabled()) {
+ GDBStub::SetCpuStepFlag(false);
+ }
+
return status;
}
@@ -85,8 +88,8 @@ System::ResultStatus System::SingleStep() {
return RunLoop(false);
}
-System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& filepath) {
- app_loader = Loader::GetLoader(std::make_shared<FileSys::RealVfsFile>(filepath));
+System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) {
+ app_loader = Loader::GetLoader(virtual_filesystem->OpenFile(filepath, FileSys::Mode::Read));
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
@@ -99,18 +102,8 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
static_cast<int>(system_mode.second));
- switch (system_mode.second) {
- case Loader::ResultStatus::ErrorMissingKeys:
- return ResultStatus::ErrorLoader_ErrorMissingKeys;
- case Loader::ResultStatus::ErrorDecrypting:
- return ResultStatus::ErrorLoader_ErrorDecrypting;
- case Loader::ResultStatus::ErrorInvalidFormat:
- return ResultStatus::ErrorLoader_ErrorInvalidFormat;
- case Loader::ResultStatus::ErrorUnsupportedArch:
- return ResultStatus::ErrorUnsupportedArch;
- default:
+ if (system_mode.second != Loader::ResultStatus::Success)
return ResultStatus::ErrorSystemMode;
- }
}
ResultStatus init_result{Init(emu_window)};
@@ -126,17 +119,9 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
System::Shutdown();
- switch (load_result) {
- case Loader::ResultStatus::ErrorMissingKeys:
- return ResultStatus::ErrorLoader_ErrorMissingKeys;
- case Loader::ResultStatus::ErrorDecrypting:
- return ResultStatus::ErrorLoader_ErrorDecrypting;
- case Loader::ResultStatus::ErrorInvalidFormat:
- return ResultStatus::ErrorLoader_ErrorInvalidFormat;
- case Loader::ResultStatus::ErrorUnsupportedArch:
- return ResultStatus::ErrorUnsupportedArch;
- default:
- return ResultStatus::ErrorLoader;
+ if (load_result != Loader::ResultStatus::Success) {
+ return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
+ static_cast<u32>(load_result));
}
}
status = ResultStatus::Success;
@@ -166,11 +151,15 @@ Cpu& System::CpuCore(size_t core_index) {
return *cpu_cores[core_index];
}
-System::ResultStatus System::Init(EmuWindow& emu_window) {
+System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
LOG_DEBUG(HW_Memory, "initialized OK");
CoreTiming::Init();
+ // Create a default fs if one doesn't already exist.
+ if (virtual_filesystem == nullptr)
+ virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
+
current_process = Kernel::Process::Create("main");
cpu_barrier = std::make_shared<CpuBarrier>();
@@ -183,7 +172,7 @@ System::ResultStatus System::Init(EmuWindow& emu_window) {
service_manager = std::make_shared<Service::SM::ServiceManager>();
Kernel::Init();
- Service::Init(service_manager);
+ Service::Init(service_manager, virtual_filesystem);
GDBStub::Init();
renderer = VideoCore::CreateRenderer(emu_window);
diff --git a/src/core/core.h b/src/core/core.h
index a3be88aa8..d98b15a71 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -17,12 +17,17 @@
#include "core/memory.h"
#include "core/perf_stats.h"
#include "core/telemetry_session.h"
+#include "file_sys/vfs_real.h"
+#include "hle/service/filesystem/filesystem.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu.h"
-class EmuWindow;
class ARM_Interface;
+namespace Core::Frontend {
+class EmuWindow;
+}
+
namespace Service::SM {
class ServiceManager;
}
@@ -47,21 +52,15 @@ public:
/// Enumeration representing the return values of the System Initialize and Load process.
enum class ResultStatus : u32 {
- Success, ///< Succeeded
- ErrorNotInitialized, ///< Error trying to use core prior to initialization
- ErrorGetLoader, ///< Error finding the correct application loader
- ErrorSystemMode, ///< Error determining the system mode
- ErrorLoader, ///< Error loading the specified application
- ErrorLoader_ErrorMissingKeys, ///< Error because the key/keys needed to run could not be
- ///< found.
- ErrorLoader_ErrorDecrypting, ///< Error loading the specified application due to encryption
- ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an
- /// invalid format
- ErrorSystemFiles, ///< Error in finding system files
- ErrorSharedFont, ///< Error in finding shared font
- ErrorVideoCore, ///< Error in the video core
- ErrorUnsupportedArch, ///< Unsupported Architecture (32-Bit ROMs)
- ErrorUnknown ///< Any other error
+ Success, ///< Succeeded
+ ErrorNotInitialized, ///< Error trying to use core prior to initialization
+ ErrorGetLoader, ///< Error finding the correct application loader
+ ErrorSystemMode, ///< Error determining the system mode
+ ErrorSystemFiles, ///< Error in finding system files
+ ErrorSharedFont, ///< Error in finding shared font
+ ErrorVideoCore, ///< Error in the video core
+ ErrorUnknown, ///< Any other error
+ ErrorLoader, ///< The base for loader errors (too many to repeat)
};
/**
@@ -82,6 +81,17 @@ public:
*/
ResultStatus SingleStep();
+ /**
+ * Invalidate the CPU instruction caches
+ * This function should only be used by GDB Stub to support breakpoints, memory updates and
+ * step/continue commands.
+ */
+ void InvalidateCpuInstructionCaches() {
+ for (auto& cpu : cpu_cores) {
+ cpu->ArmInterface().ClearInstructionCache();
+ }
+ }
+
/// Shutdown the emulated system.
void Shutdown();
@@ -92,7 +102,7 @@ public:
* @param filepath String path to the executable application to load on the host file system.
* @returns ResultStatus code, indicating if the operation succeeded.
*/
- ResultStatus Load(EmuWindow& emu_window, const std::string& filepath);
+ ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath);
/**
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
@@ -200,6 +210,14 @@ public:
return debug_context;
}
+ void SetFilesystem(FileSys::VirtualFilesystem vfs) {
+ virtual_filesystem = std::move(vfs);
+ }
+
+ FileSys::VirtualFilesystem GetFilesystem() const {
+ return virtual_filesystem;
+ }
+
private:
System();
@@ -212,8 +230,10 @@ private:
* input.
* @return ResultStatus code, indicating if the operation succeeded.
*/
- ResultStatus Init(EmuWindow& emu_window);
+ ResultStatus Init(Frontend::EmuWindow& emu_window);
+ /// RealVfsFilesystem instance
+ FileSys::VirtualFilesystem virtual_filesystem;
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<VideoCore::RendererBase> renderer;
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index 46a522fcd..b042ee02b 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -14,6 +14,7 @@
#include "core/core_timing.h"
#include "core/hle/kernel/scheduler.h"
#include "core/hle/kernel/thread.h"
+#include "core/hle/lock.h"
#include "core/settings.h"
namespace Core {
@@ -90,6 +91,7 @@ void Cpu::RunLoop(bool tight_loop) {
LOG_TRACE(Core, "Core-{} idling", core_index);
if (IsMainCore()) {
+ // TODO(Subv): Only let CoreTiming idle if all 4 cores are idling.
CoreTiming::Idle();
CoreTiming::Advance();
}
@@ -125,6 +127,8 @@ void Cpu::Reschedule() {
}
reschedule_pending = false;
+ // Lock the global kernel mutex when we manipulate the HLE state
+ std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
scheduler->Reschedule();
}
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 976952903..56cdae194 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -79,7 +79,7 @@ private:
std::shared_ptr<CpuBarrier> cpu_barrier;
std::shared_ptr<Kernel::Scheduler> scheduler;
- bool reschedule_pending{};
+ std::atomic<bool> reschedule_pending = false;
size_t core_index;
};
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index a1b6f96f1..f977d1b32 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -135,13 +135,11 @@ void ClearPendingEvents() {
void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
ASSERT(event_type != nullptr);
s64 timeout = GetTicks() + cycles_into_future;
-
// If this event needs to be scheduled before the next advance(), force one early
if (!is_global_timer_sane)
ForceExceptionCheck(cycles_into_future);
-
event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
- std::push_heap(event_queue.begin(), event_queue.end(), std::greater<Event>());
+ std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
void ScheduleEventThreadsafe(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
@@ -156,7 +154,7 @@ void UnscheduleEvent(const EventType* event_type, u64 userdata) {
// Removing random items breaks the invariant so we have to re-establish it.
if (itr != event_queue.end()) {
event_queue.erase(itr, event_queue.end());
- std::make_heap(event_queue.begin(), event_queue.end(), std::greater<Event>());
+ std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
}
@@ -167,7 +165,7 @@ void RemoveEvent(const EventType* event_type) {
// Removing random items breaks the invariant so we have to re-establish it.
if (itr != event_queue.end()) {
event_queue.erase(itr, event_queue.end());
- std::make_heap(event_queue.begin(), event_queue.end(), std::greater<Event>());
+ std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
}
@@ -190,7 +188,7 @@ void MoveEvents() {
for (Event ev; ts_queue.Pop(ev);) {
ev.fifo_order = event_fifo_id++;
event_queue.emplace_back(std::move(ev));
- std::push_heap(event_queue.begin(), event_queue.end(), std::greater<Event>());
+ std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
}
@@ -205,7 +203,7 @@ void Advance() {
while (!event_queue.empty() && event_queue.front().time <= global_timer) {
Event evt = std::move(event_queue.front());
- std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<Event>());
+ std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
event_queue.pop_back();
evt.type->callback(evt.userdata, static_cast<int>(global_timer - evt.time));
}
@@ -226,8 +224,8 @@ void Idle() {
downcount = 0;
}
-u64 GetGlobalTimeUs() {
- return GetTicks() * 1000000 / BASE_CLOCK_RATE;
+std::chrono::microseconds GetGlobalTimeUs() {
+ return std::chrono::microseconds{GetTicks() * 1000000 / BASE_CLOCK_RATE};
}
int GetDowncount() {
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 7fe6380ad..dfa161c0d 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -17,12 +17,17 @@
* ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
*/
+#include <chrono>
#include <functional>
#include <string>
#include "common/common_types.h"
namespace CoreTiming {
+struct EventType;
+
+using TimedCallback = std::function<void(u64 userdata, int cycles_late)>;
+
/**
* CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
* required to end slice -1 and start slice 0 before the first cycle of code is executed.
@@ -30,8 +35,6 @@ namespace CoreTiming {
void Init();
void Shutdown();
-typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback;
-
/**
* This should only be called from the emu thread, if you are calling it any other thread, you are
* doing something evil
@@ -40,8 +43,6 @@ u64 GetTicks();
u64 GetIdleTicks();
void AddTicks(u64 ticks);
-struct EventType;
-
/**
* Returns the event_type identifier. if name is not unique, it will assert.
*/
@@ -86,7 +87,7 @@ void ClearPendingEvents();
void ForceExceptionCheck(s64 cycles);
-u64 GetGlobalTimeUs();
+std::chrono::microseconds GetGlobalTimeUs();
int GetDowncount();
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 395eea8ae..8e05b9d0e 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -5,20 +5,23 @@
#include <array>
#include <string>
#include <core/loader/loader.h>
+#include "common/logging/log.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/file_sys/vfs_offset.h"
namespace FileSys {
+constexpr std::array<const char*, 0x4> partition_names = {"update", "normal", "secure", "logo"};
+
XCI::XCI(VirtualFile file_) : file(std::move(file_)), partitions(0x4) {
if (file->ReadObject(&header) != sizeof(GamecardHeader)) {
- status = Loader::ResultStatus::ErrorInvalidFormat;
+ status = Loader::ResultStatus::ErrorBadXCIHeader;
return;
}
if (header.magic != Common::MakeMagic('H', 'E', 'A', 'D')) {
- status = Loader::ResultStatus::ErrorInvalidFormat;
+ status = Loader::ResultStatus::ErrorBadXCIHeader;
return;
}
@@ -30,9 +33,6 @@ XCI::XCI(VirtualFile file_) : file(std::move(file_)), partitions(0x4) {
return;
}
- static constexpr std::array<const char*, 0x4> partition_names = {"update", "normal", "secure",
- "logo"};
-
for (XCIPartition partition :
{XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) {
auto raw = main_hfs.GetFile(partition_names[static_cast<size_t>(partition)]);
@@ -107,19 +107,19 @@ VirtualFile XCI::GetNCAFileByType(NCAContentType type) const {
return nullptr;
}
-std::vector<std::shared_ptr<VfsFile>> XCI::GetFiles() const {
+std::vector<VirtualFile> XCI::GetFiles() const {
return {};
}
-std::vector<std::shared_ptr<VfsDirectory>> XCI::GetSubdirectories() const {
- return std::vector<std::shared_ptr<VfsDirectory>>();
+std::vector<VirtualDir> XCI::GetSubdirectories() const {
+ return {};
}
std::string XCI::GetName() const {
return file->GetName();
}
-std::shared_ptr<VfsDirectory> XCI::GetParentDirectory() const {
+VirtualDir XCI::GetParentDirectory() const {
return file->GetContainingDirectory();
}
@@ -129,15 +129,21 @@ bool XCI::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
if (partitions[static_cast<size_t>(part)] == nullptr) {
- return Loader::ResultStatus::ErrorInvalidFormat;
+ return Loader::ResultStatus::ErrorXCIMissingPartition;
}
for (const VirtualFile& file : partitions[static_cast<size_t>(part)]->GetFiles()) {
if (file->GetExtension() != "nca")
continue;
auto nca = std::make_shared<NCA>(file);
- if (nca->GetStatus() == Loader::ResultStatus::Success)
+ if (nca->GetStatus() == Loader::ResultStatus::Success) {
ncas.push_back(std::move(nca));
+ } else {
+ const u16 error_id = static_cast<u16>(nca->GetStatus());
+ LOG_CRITICAL(Loader, "Could not load NCA {}/{}, failed with error code {:04X} ({})",
+ partition_names[static_cast<size_t>(part)], nca->GetName(), error_id,
+ Loader::GetMessageForResultStatus(nca->GetStatus()));
+ }
}
return Loader::ResultStatus::Success;
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h
index e089d737c..4618d9c00 100644
--- a/src/core/file_sys/card_image.h
+++ b/src/core/file_sys/card_image.h
@@ -71,13 +71,13 @@ public:
std::shared_ptr<NCA> GetNCAByType(NCAContentType type) const;
VirtualFile GetNCAFileByType(NCAContentType type) const;
- std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
+ std::vector<VirtualFile> GetFiles() const override;
- std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
+ std::vector<VirtualDir> GetSubdirectories() const override;
std::string GetName() const override;
- std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
+ VirtualDir GetParentDirectory() const override;
protected:
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 79e70f6ef..47afcad9b 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -76,12 +76,17 @@ bool IsValidNCA(const NCAHeader& header) {
return header.magic == Common::MakeMagic('N', 'C', 'A', '3');
}
-boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
+u8 NCA::GetCryptoRevision() const {
u8 master_key_id = header.crypto_type;
if (header.crypto_type_2 > master_key_id)
master_key_id = header.crypto_type_2;
if (master_key_id > 0)
--master_key_id;
+ return master_key_id;
+}
+
+boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
+ const auto master_key_id = GetCryptoRevision();
if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index))
return boost::none;
@@ -108,44 +113,105 @@ boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType ty
return out;
}
-VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const {
+boost::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
+ const auto master_key_id = GetCryptoRevision();
+
+ u128 rights_id{};
+ memcpy(rights_id.data(), header.rights_id.data(), 16);
+ if (rights_id == u128{}) {
+ status = Loader::ResultStatus::ErrorInvalidRightsID;
+ return boost::none;
+ }
+
+ auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
+ if (titlekey == Core::Crypto::Key128{}) {
+ status = Loader::ResultStatus::ErrorMissingTitlekey;
+ return boost::none;
+ }
+
+ if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
+ status = Loader::ResultStatus::ErrorMissingTitlekek;
+ return boost::none;
+ }
+
+ Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
+ keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id), Core::Crypto::Mode::ECB);
+ cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), Core::Crypto::Op::Decrypt);
+
+ return titlekey;
+}
+
+VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting_offset) {
if (!encrypted)
return in;
- switch (header.raw.header.crypto_type) {
+ switch (s_header.raw.header.crypto_type) {
case NCASectionCryptoType::NONE:
LOG_DEBUG(Crypto, "called with mode=NONE");
return in;
case NCASectionCryptoType::CTR:
LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
{
- const auto key = GetKeyAreaKey(NCASectionCryptoType::CTR);
- if (key == boost::none)
- return nullptr;
+ boost::optional<Core::Crypto::Key128> key = boost::none;
+ if (has_rights_id) {
+ status = Loader::ResultStatus::Success;
+ key = GetTitlekey();
+ if (key == boost::none) {
+ if (status == Loader::ResultStatus::Success)
+ status = Loader::ResultStatus::ErrorMissingTitlekey;
+ return nullptr;
+ }
+ } else {
+ key = GetKeyAreaKey(NCASectionCryptoType::CTR);
+ if (key == boost::none) {
+ status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
+ return nullptr;
+ }
+ }
+
auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(
std::move(in), key.value(), starting_offset);
std::vector<u8> iv(16);
for (u8 i = 0; i < 8; ++i)
- iv[i] = header.raw.section_ctr[0x8 - i - 1];
+ iv[i] = s_header.raw.section_ctr[0x8 - i - 1];
out->SetIV(iv);
return std::static_pointer_cast<VfsFile>(out);
}
case NCASectionCryptoType::XTS:
- // TODO(DarkLordZach): Implement XTSEncryptionLayer and title key encryption.
+ // TODO(DarkLordZach): Implement XTSEncryptionLayer.
default:
LOG_ERROR(Crypto, "called with unhandled crypto type={:02X}",
- static_cast<u8>(header.raw.header.crypto_type));
+ static_cast<u8>(s_header.raw.header.crypto_type));
return nullptr;
}
}
NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
- if (sizeof(NCAHeader) != file->ReadObject(&header))
+ status = Loader::ResultStatus::Success;
+
+ if (file == nullptr) {
+ status = Loader::ResultStatus::ErrorNullFile;
+ return;
+ }
+
+ if (sizeof(NCAHeader) != file->ReadObject(&header)) {
LOG_ERROR(Loader, "File reader errored out during header read.");
+ status = Loader::ResultStatus::ErrorBadNCAHeader;
+ return;
+ }
encrypted = false;
if (!IsValidNCA(header)) {
+ if (header.magic == Common::MakeMagic('N', 'C', 'A', '2')) {
+ status = Loader::ResultStatus::ErrorNCA2;
+ return;
+ }
+ if (header.magic == Common::MakeMagic('N', 'C', 'A', '0')) {
+ status = Loader::ResultStatus::ErrorNCA0;
+ return;
+ }
+
NCAHeader dec_header{};
Core::Crypto::AESCipher<Core::Crypto::Key256> cipher(
keys.GetKey(Core::Crypto::S256KeyType::Header), Core::Crypto::Mode::XTS);
@@ -155,14 +221,26 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
header = dec_header;
encrypted = true;
} else {
+ if (dec_header.magic == Common::MakeMagic('N', 'C', 'A', '2')) {
+ status = Loader::ResultStatus::ErrorNCA2;
+ return;
+ }
+ if (dec_header.magic == Common::MakeMagic('N', 'C', 'A', '0')) {
+ status = Loader::ResultStatus::ErrorNCA0;
+ return;
+ }
+
if (!keys.HasKey(Core::Crypto::S256KeyType::Header))
- status = Loader::ResultStatus::ErrorMissingKeys;
+ status = Loader::ResultStatus::ErrorMissingHeaderKey;
else
- status = Loader::ResultStatus::ErrorDecrypting;
+ status = Loader::ResultStatus::ErrorIncorrectHeaderKey;
return;
}
}
+ has_rights_id = std::find_if_not(header.rights_id.begin(), header.rights_id.end(),
+ [](char c) { return c == '\0'; }) != header.rights_id.end();
+
const std::ptrdiff_t number_sections =
std::count_if(std::begin(header.section_tables), std::end(header.section_tables),
[](NCASectionTableEntry entry) { return entry.media_offset > 0; });
@@ -195,7 +273,12 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
files.push_back(std::move(dec));
romfs = files.back();
} else {
- status = Loader::ResultStatus::ErrorMissingKeys;
+ if (status != Loader::ResultStatus::Success)
+ return;
+ if (has_rights_id)
+ status = Loader::ResultStatus::ErrorIncorrectTitlekeyOrTitlekek;
+ else
+ status = Loader::ResultStatus::ErrorIncorrectKeyAreaKey;
return;
}
} else if (section.raw.header.filesystem_type == NCASectionFilesystemType::PFS0) {
@@ -215,7 +298,12 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
exefs = dirs.back();
}
} else {
- status = Loader::ResultStatus::ErrorMissingKeys;
+ if (status != Loader::ResultStatus::Success)
+ return;
+ if (has_rights_id)
+ status = Loader::ResultStatus::ErrorIncorrectTitlekeyOrTitlekek;
+ else
+ status = Loader::ResultStatus::ErrorIncorrectKeyAreaKey;
return;
}
}
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index 6492163b5..b82e65ad5 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -12,6 +12,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
+#include "control_metadata.h"
#include "core/crypto/key_manager.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/loader/loader.h"
@@ -95,8 +96,10 @@ protected:
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
private:
+ u8 GetCryptoRevision() const;
boost::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const;
- VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset) const;
+ boost::optional<Core::Crypto::Key128> GetTitlekey();
+ VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset);
std::vector<VirtualDir> dirs;
std::vector<VirtualFile> files;
@@ -106,6 +109,7 @@ private:
VirtualFile file;
NCAHeader header{};
+ bool has_rights_id{};
Loader::ResultStatus status{};
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index cc3b745f7..6582cc240 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -62,6 +62,13 @@ enum class Language : u8 {
Chinese = 14,
};
+static constexpr std::array<const char*, 15> LANGUAGE_NAMES = {
+ "AmericanEnglish", "BritishEnglish", "Japanese",
+ "French", "German", "LatinAmericanSpanish",
+ "Spanish", "Italian", "Dutch",
+ "CanadianFrench", "Portugese", "Russian",
+ "Korean", "Taiwanese", "Chinese"};
+
// A class representing the format used by NX metadata files, typically named Control.nacp.
// These store application name, dev name, title id, and other miscellaneous data.
class NACP {
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h
index 213ce1826..3759e743a 100644
--- a/src/core/file_sys/directory.h
+++ b/src/core/file_sys/directory.h
@@ -4,8 +4,9 @@
#pragma once
-#include <array>
#include <cstddef>
+#include <iterator>
+#include <string_view>
#include "common/common_funcs.h"
#include "common/common_types.h"
@@ -21,9 +22,14 @@ enum EntryType : u8 {
// Structure of a directory entry, from
// http://switchbrew.org/index.php?title=Filesystem_services#DirectoryEntry
-const size_t FILENAME_LENGTH = 0x300;
struct Entry {
- char filename[FILENAME_LENGTH];
+ Entry(std::string_view view, EntryType entry_type, u64 entry_size)
+ : type{entry_type}, file_size{entry_size} {
+ const size_t copy_size = view.copy(filename, std::size(filename) - 1);
+ filename[copy_size] = '\0';
+ }
+
+ char filename[0x300];
INSERT_PADDING_BYTES(4);
EntryType type;
INSERT_PADDING_BYTES(3);
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 47e032b19..c377edc9c 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -24,19 +24,19 @@ bool PartitionFilesystem::Header::HasValidMagicValue() const {
PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
// At least be as large as the header
if (file->GetSize() < sizeof(Header)) {
- status = Loader::ResultStatus::Error;
+ status = Loader::ResultStatus::ErrorBadPFSHeader;
return;
}
// For cartridges, HFSs can get very large, so we need to calculate the size up to
// the actual content itself instead of just blindly reading in the entire file.
if (sizeof(Header) != file->ReadObject(&pfs_header)) {
- status = Loader::ResultStatus::Error;
+ status = Loader::ResultStatus::ErrorBadPFSHeader;
return;
}
if (!pfs_header.HasValidMagicValue()) {
- status = Loader::ResultStatus::ErrorInvalidFormat;
+ status = Loader::ResultStatus::ErrorBadPFSHeader;
return;
}
@@ -51,7 +51,7 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
const size_t total_size = file_data.size();
if (total_size != metadata_size) {
- status = Loader::ResultStatus::Error;
+ status = Loader::ResultStatus::ErrorIncorrectPFSFileSize;
return;
}
diff --git a/src/core/file_sys/partition_filesystem.h b/src/core/file_sys/partition_filesystem.h
index 7c7a75816..be7bc32a8 100644
--- a/src/core/file_sys/partition_filesystem.h
+++ b/src/core/file_sys/partition_filesystem.h
@@ -13,7 +13,7 @@
#include "core/file_sys/vfs.h"
namespace Loader {
-enum class ResultStatus;
+enum class ResultStatus : u16;
}
namespace FileSys {
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index 63d4b6e4f..279f987d4 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -12,26 +12,26 @@ namespace FileSys {
Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
size_t total_size = static_cast<size_t>(file->GetSize());
if (total_size < sizeof(Header))
- return Loader::ResultStatus::Error;
+ return Loader::ResultStatus::ErrorBadNPDMHeader;
// TODO(DarkLordZach): Use ReadObject when Header/AcidHeader becomes trivially copyable.
std::vector<u8> npdm_header_data = file->ReadBytes(sizeof(Header));
if (sizeof(Header) != npdm_header_data.size())
- return Loader::ResultStatus::Error;
+ return Loader::ResultStatus::ErrorBadNPDMHeader;
std::memcpy(&npdm_header, npdm_header_data.data(), sizeof(Header));
std::vector<u8> acid_header_data = file->ReadBytes(sizeof(AcidHeader), npdm_header.acid_offset);
if (sizeof(AcidHeader) != acid_header_data.size())
- return Loader::ResultStatus::Error;
+ return Loader::ResultStatus::ErrorBadACIDHeader;
std::memcpy(&acid_header, acid_header_data.data(), sizeof(AcidHeader));
if (sizeof(AciHeader) != file->ReadObject(&aci_header, npdm_header.aci_offset))
- return Loader::ResultStatus::Error;
+ return Loader::ResultStatus::ErrorBadACIHeader;
if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset))
- return Loader::ResultStatus::Error;
+ return Loader::ResultStatus::ErrorBadFileAccessControl;
if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset))
- return Loader::ResultStatus::Error;
+ return Loader::ResultStatus::ErrorBadFileAccessHeader;
return Loader::ResultStatus::Success;
}
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index 06a7315db..74a91052b 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -13,7 +13,7 @@
#include "partition_filesystem.h"
namespace Loader {
-enum class ResultStatus;
+enum class ResultStatus : u16;
}
namespace FileSys {
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index e3a578c0f..f3cf50d5a 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
#include "common/common_types.h"
+#include "common/swap.h"
#include "core/hle/result.h"
namespace FileSys {
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index dae1c16ef..a5ec50b1a 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -4,12 +4,160 @@
#include <algorithm>
#include <numeric>
+#include <string>
+#include "common/common_paths.h"
#include "common/file_util.h"
#include "common/logging/backend.h"
#include "core/file_sys/vfs.h"
namespace FileSys {
+VfsFilesystem::VfsFilesystem(VirtualDir root_) : root(std::move(root_)) {}
+
+VfsFilesystem::~VfsFilesystem() = default;
+
+std::string VfsFilesystem::GetName() const {
+ return root->GetName();
+}
+
+bool VfsFilesystem::IsReadable() const {
+ return root->IsReadable();
+}
+
+bool VfsFilesystem::IsWritable() const {
+ return root->IsWritable();
+}
+
+VfsEntryType VfsFilesystem::GetEntryType(std::string_view path_) const {
+ const auto path = FileUtil::SanitizePath(path_);
+ if (root->GetFileRelative(path) != nullptr)
+ return VfsEntryType::File;
+ if (root->GetDirectoryRelative(path) != nullptr)
+ return VfsEntryType::Directory;
+
+ return VfsEntryType::None;
+}
+
+VirtualFile VfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_);
+ return root->GetFileRelative(path);
+}
+
+VirtualFile VfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_);
+ return root->CreateFileRelative(path);
+}
+
+VirtualFile VfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) {
+ const auto old_path = FileUtil::SanitizePath(old_path_);
+ const auto new_path = FileUtil::SanitizePath(new_path_);
+
+ // VfsDirectory impls are only required to implement copy across the current directory.
+ if (FileUtil::GetParentPath(old_path) == FileUtil::GetParentPath(new_path)) {
+ if (!root->Copy(FileUtil::GetFilename(old_path), FileUtil::GetFilename(new_path)))
+ return nullptr;
+ return OpenFile(new_path, Mode::ReadWrite);
+ }
+
+ // Do it using RawCopy. Non-default impls are encouraged to optimize this.
+ const auto old_file = OpenFile(old_path, Mode::Read);
+ if (old_file == nullptr)
+ return nullptr;
+ auto new_file = OpenFile(new_path, Mode::Read);
+ if (new_file != nullptr)
+ return nullptr;
+ new_file = CreateFile(new_path, Mode::Write);
+ if (new_file == nullptr)
+ return nullptr;
+ if (!VfsRawCopy(old_file, new_file))
+ return nullptr;
+ return new_file;
+}
+
+VirtualFile VfsFilesystem::MoveFile(std::string_view old_path, std::string_view new_path) {
+ const auto sanitized_old_path = FileUtil::SanitizePath(old_path);
+ const auto sanitized_new_path = FileUtil::SanitizePath(new_path);
+
+ // Again, non-default impls are highly encouraged to provide a more optimized version of this.
+ auto out = CopyFile(sanitized_old_path, sanitized_new_path);
+ if (out == nullptr)
+ return nullptr;
+ if (DeleteFile(sanitized_old_path))
+ return out;
+ return nullptr;
+}
+
+bool VfsFilesystem::DeleteFile(std::string_view path_) {
+ const auto path = FileUtil::SanitizePath(path_);
+ auto parent = OpenDirectory(FileUtil::GetParentPath(path), Mode::Write);
+ if (parent == nullptr)
+ return false;
+ return parent->DeleteFile(FileUtil::GetFilename(path));
+}
+
+VirtualDir VfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_);
+ return root->GetDirectoryRelative(path);
+}
+
+VirtualDir VfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_);
+ return root->CreateDirectoryRelative(path);
+}
+
+VirtualDir VfsFilesystem::CopyDirectory(std::string_view old_path_, std::string_view new_path_) {
+ const auto old_path = FileUtil::SanitizePath(old_path_);
+ const auto new_path = FileUtil::SanitizePath(new_path_);
+
+ // Non-default impls are highly encouraged to provide a more optimized version of this.
+ auto old_dir = OpenDirectory(old_path, Mode::Read);
+ if (old_dir == nullptr)
+ return nullptr;
+ auto new_dir = OpenDirectory(new_path, Mode::Read);
+ if (new_dir != nullptr)
+ return nullptr;
+ new_dir = CreateDirectory(new_path, Mode::Write);
+ if (new_dir == nullptr)
+ return nullptr;
+
+ for (const auto& file : old_dir->GetFiles()) {
+ const auto x =
+ CopyFile(old_path + DIR_SEP + file->GetName(), new_path + DIR_SEP + file->GetName());
+ if (x == nullptr)
+ return nullptr;
+ }
+
+ for (const auto& dir : old_dir->GetSubdirectories()) {
+ const auto x =
+ CopyDirectory(old_path + DIR_SEP + dir->GetName(), new_path + DIR_SEP + dir->GetName());
+ if (x == nullptr)
+ return nullptr;
+ }
+
+ return new_dir;
+}
+
+VirtualDir VfsFilesystem::MoveDirectory(std::string_view old_path, std::string_view new_path) {
+ const auto sanitized_old_path = FileUtil::SanitizePath(old_path);
+ const auto sanitized_new_path = FileUtil::SanitizePath(new_path);
+
+ // Non-default impls are highly encouraged to provide a more optimized version of this.
+ auto out = CopyDirectory(sanitized_old_path, sanitized_new_path);
+ if (out == nullptr)
+ return nullptr;
+ if (DeleteDirectory(sanitized_old_path))
+ return out;
+ return nullptr;
+}
+
+bool VfsFilesystem::DeleteDirectory(std::string_view path_) {
+ const auto path = FileUtil::SanitizePath(path_);
+ auto parent = OpenDirectory(FileUtil::GetParentPath(path), Mode::Write);
+ if (parent == nullptr)
+ return false;
+ return parent->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path));
+}
+
VfsFile::~VfsFile() = default;
std::string VfsFile::GetExtension() const {
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index fab9e2b45..78a63c59b 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -11,17 +11,79 @@
#include <vector>
#include "boost/optional.hpp"
#include "common/common_types.h"
+#include "core/file_sys/mode.h"
namespace FileSys {
-struct VfsFile;
-struct VfsDirectory;
-// Convenience typedefs to use VfsDirectory and VfsFile
-using VirtualDir = std::shared_ptr<FileSys::VfsDirectory>;
-using VirtualFile = std::shared_ptr<FileSys::VfsFile>;
+class VfsDirectory;
+class VfsFile;
+class VfsFilesystem;
+
+// Convenience typedefs to use Vfs* interfaces
+using VirtualFilesystem = std::shared_ptr<VfsFilesystem>;
+using VirtualDir = std::shared_ptr<VfsDirectory>;
+using VirtualFile = std::shared_ptr<VfsFile>;
+
+// An enumeration representing what can be at the end of a path in a VfsFilesystem
+enum class VfsEntryType {
+ None,
+ File,
+ Directory,
+};
+
+// A class representing an abstract filesystem. A default implementation given the root VirtualDir
+// is provided for convenience, but if the Vfs implementation has any additional state or
+// functionality, they will need to override.
+class VfsFilesystem : NonCopyable {
+public:
+ explicit VfsFilesystem(VirtualDir root);
+ virtual ~VfsFilesystem();
+
+ // Gets the friendly name for the filesystem.
+ virtual std::string GetName() const;
+
+ // Return whether or not the user has read permissions on this filesystem.
+ virtual bool IsReadable() const;
+ // Return whether or not the user has write permission on this filesystem.
+ virtual bool IsWritable() const;
+
+ // Determine if the entry at path is non-existant, a file, or a directory.
+ virtual VfsEntryType GetEntryType(std::string_view path) const;
+
+ // Opens the file with path relative to root. If it doesn't exist, returns nullptr.
+ virtual VirtualFile OpenFile(std::string_view path, Mode perms);
+ // Creates a new, empty file at path
+ virtual VirtualFile CreateFile(std::string_view path, Mode perms);
+ // Copies the file from old_path to new_path, returning the new file on success and nullptr on
+ // failure.
+ virtual VirtualFile CopyFile(std::string_view old_path, std::string_view new_path);
+ // Moves the file from old_path to new_path, returning the moved file on success and nullptr on
+ // failure.
+ virtual VirtualFile MoveFile(std::string_view old_path, std::string_view new_path);
+ // Deletes the file with path relative to root, returing true on success.
+ virtual bool DeleteFile(std::string_view path);
+
+ // Opens the directory with path relative to root. If it doesn't exist, returns nullptr.
+ virtual VirtualDir OpenDirectory(std::string_view path, Mode perms);
+ // Creates a new, empty directory at path
+ virtual VirtualDir CreateDirectory(std::string_view path, Mode perms);
+ // Copies the directory from old_path to new_path, returning the new directory on success and
+ // nullptr on failure.
+ virtual VirtualDir CopyDirectory(std::string_view old_path, std::string_view new_path);
+ // Moves the directory from old_path to new_path, returning the moved directory on success and
+ // nullptr on failure.
+ virtual VirtualDir MoveDirectory(std::string_view old_path, std::string_view new_path);
+ // Deletes the directory with path relative to root, returing true on success.
+ virtual bool DeleteDirectory(std::string_view path);
+
+protected:
+ // Root directory in default implementation.
+ VirtualDir root;
+};
// A class representing a file in an abstract filesystem.
-struct VfsFile : NonCopyable {
+class VfsFile : NonCopyable {
+public:
virtual ~VfsFile();
// Retrieves the file name.
@@ -119,7 +181,8 @@ struct VfsFile : NonCopyable {
};
// A class representing a directory in an abstract filesystem.
-struct VfsDirectory : NonCopyable {
+class VfsDirectory : NonCopyable {
+public:
virtual ~VfsDirectory();
// Retrives the file located at path as if the current directory was root. Returns nullptr if
@@ -235,7 +298,8 @@ protected:
// A convenience partial-implementation of VfsDirectory that stubs out methods that should only work
// if writable. This is to avoid redundant empty methods everywhere.
-struct ReadOnlyVfsDirectory : public VfsDirectory {
+class ReadOnlyVfsDirectory : public VfsDirectory {
+public:
bool IsWritable() const override;
bool IsReadable() const override;
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h
index 235970dc5..cb92d1570 100644
--- a/src/core/file_sys/vfs_offset.h
+++ b/src/core/file_sys/vfs_offset.h
@@ -15,7 +15,8 @@ namespace FileSys {
// Similar to seeking to an offset.
// If the file is writable, operations that would write past the end of the offset file will expand
// the size of this wrapper.
-struct OffsetVfsFile : public VfsFile {
+class OffsetVfsFile : public VfsFile {
+public:
OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0,
std::string new_name = "", VirtualDir new_parent = nullptr);
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 82d54da4a..1b5919737 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -6,7 +6,7 @@
#include <cstddef>
#include <iterator>
#include <utility>
-
+#include "common/assert.h"
#include "common/common_paths.h"
#include "common/logging/log.h"
#include "core/file_sys/vfs_real.h"
@@ -29,6 +29,8 @@ static std::string ModeFlagsToString(Mode mode) {
mode_str = "a";
else if (mode & Mode::Write)
mode_str = "w";
+ else
+ UNREACHABLE_MSG("Invalid file open mode: {:02X}", static_cast<u8>(mode));
}
mode_str += "b";
@@ -36,8 +38,174 @@ static std::string ModeFlagsToString(Mode mode) {
return mode_str;
}
-RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_)
- : backing(path_, ModeFlagsToString(perms_).c_str()), path(path_),
+RealVfsFilesystem::RealVfsFilesystem() : VfsFilesystem(nullptr) {}
+
+std::string RealVfsFilesystem::GetName() const {
+ return "Real";
+}
+
+bool RealVfsFilesystem::IsReadable() const {
+ return true;
+}
+
+bool RealVfsFilesystem::IsWritable() const {
+ return true;
+}
+
+VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (!FileUtil::Exists(path))
+ return VfsEntryType::None;
+ if (FileUtil::IsDirectory(path))
+ return VfsEntryType::Directory;
+
+ return VfsEntryType::File;
+}
+
+VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (cache.find(path) != cache.end()) {
+ auto weak = cache[path];
+ if (!weak.expired()) {
+ return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms));
+ }
+ }
+
+ if (!FileUtil::Exists(path) && (perms & Mode::WriteAppend) != 0)
+ FileUtil::CreateEmptyFile(path);
+
+ auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str());
+ cache[path] = backing;
+
+ // Cannot use make_shared as RealVfsFile constructor is private
+ return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms));
+}
+
+VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (!FileUtil::Exists(path) && !FileUtil::CreateEmptyFile(path))
+ return nullptr;
+ return OpenFile(path, perms);
+}
+
+VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) {
+ const auto old_path =
+ FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault);
+ const auto new_path =
+ FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault);
+
+ if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
+ FileUtil::IsDirectory(old_path) || !FileUtil::Copy(old_path, new_path))
+ return nullptr;
+ return OpenFile(new_path, Mode::ReadWrite);
+}
+
+VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
+ const auto old_path =
+ FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault);
+ const auto new_path =
+ FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault);
+
+ if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
+ FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path))
+ return nullptr;
+
+ if (cache.find(old_path) != cache.end()) {
+ auto cached = cache[old_path];
+ if (!cached.expired()) {
+ auto file = cached.lock();
+ file->Open(new_path, "r+b");
+ cache.erase(old_path);
+ cache[new_path] = file;
+ }
+ }
+ return OpenFile(new_path, Mode::ReadWrite);
+}
+
+bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (cache.find(path) != cache.end()) {
+ if (!cache[path].expired())
+ cache[path].lock()->Close();
+ cache.erase(path);
+ }
+ return FileUtil::Delete(path);
+}
+
+VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ // Cannot use make_shared as RealVfsDirectory constructor is private
+ return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
+}
+
+VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (!FileUtil::Exists(path) && !FileUtil::CreateDir(path))
+ return nullptr;
+ // Cannot use make_shared as RealVfsDirectory constructor is private
+ return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
+}
+
+VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_,
+ std::string_view new_path_) {
+ const auto old_path =
+ FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault);
+ const auto new_path =
+ FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
+ !FileUtil::IsDirectory(old_path))
+ return nullptr;
+ FileUtil::CopyDir(old_path, new_path);
+ return OpenDirectory(new_path, Mode::ReadWrite);
+}
+
+VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
+ std::string_view new_path_) {
+ const auto old_path =
+ FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault);
+ const auto new_path =
+ FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault);
+ if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
+ FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path))
+ return nullptr;
+
+ for (auto& kv : cache) {
+ // Path in cache starts with old_path
+ if (kv.first.rfind(old_path, 0) == 0) {
+ const auto file_old_path =
+ FileUtil::SanitizePath(kv.first, FileUtil::DirectorySeparator::PlatformDefault);
+ const auto file_new_path =
+ FileUtil::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()),
+ FileUtil::DirectorySeparator::PlatformDefault);
+ auto cached = cache[file_old_path];
+ if (!cached.expired()) {
+ auto file = cached.lock();
+ file->Open(file_new_path, "r+b");
+ cache.erase(file_old_path);
+ cache[file_new_path] = file;
+ }
+ }
+ }
+
+ return OpenDirectory(new_path, Mode::ReadWrite);
+}
+
+bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
+ const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault);
+ for (auto& kv : cache) {
+ // Path in cache starts with old_path
+ if (kv.first.rfind(path, 0) == 0) {
+ if (!cache[kv.first].expired())
+ cache[kv.first].lock()->Close();
+ cache.erase(kv.first);
+ }
+ }
+ return FileUtil::DeleteDirRecursively(path);
+}
+
+RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FileUtil::IOFile> backing_,
+ const std::string& path_, Mode perms_)
+ : base(base_), backing(std::move(backing_)), path(path_),
parent_path(FileUtil::GetParentPath(path_)),
path_components(FileUtil::SplitPathComponents(path_)),
parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
@@ -48,15 +216,15 @@ std::string RealVfsFile::GetName() const {
}
size_t RealVfsFile::GetSize() const {
- return backing.GetSize();
+ return backing->GetSize();
}
bool RealVfsFile::Resize(size_t new_size) {
- return backing.Resize(new_size);
+ return backing->Resize(new_size);
}
std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const {
- return std::make_shared<RealVfsDirectory>(parent_path, perms);
+ return base.OpenDirectory(parent_path, perms);
}
bool RealVfsFile::IsWritable() const {
@@ -68,62 +236,118 @@ bool RealVfsFile::IsReadable() const {
}
size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const {
- if (!backing.Seek(offset, SEEK_SET))
+ if (!backing->Seek(offset, SEEK_SET))
return 0;
- return backing.ReadBytes(data, length);
+ return backing->ReadBytes(data, length);
}
size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) {
- if (!backing.Seek(offset, SEEK_SET))
+ if (!backing->Seek(offset, SEEK_SET))
return 0;
- return backing.WriteBytes(data, length);
+ return backing->WriteBytes(data, length);
}
bool RealVfsFile::Rename(std::string_view name) {
- std::string name_str(name.begin(), name.end());
- const auto out = FileUtil::Rename(GetName(), name_str);
+ return base.MoveFile(path, parent_path + DIR_SEP + std::string(name)) != nullptr;
+}
+
+bool RealVfsFile::Close() {
+ return backing->Close();
+}
- path = (parent_path + DIR_SEP).append(name);
- path_components = parent_components;
- path_components.push_back(std::move(name_str));
- backing = FileUtil::IOFile(path, ModeFlagsToString(perms).c_str());
+// TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if
+// constexpr' because there is a compile error in the branch not used.
+
+template <>
+std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>() const {
+ if (perms == Mode::Append)
+ return {};
+
+ std::vector<VirtualFile> out;
+ FileUtil::ForeachDirectoryEntry(
+ nullptr, path,
+ [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) {
+ const std::string full_path = directory + DIR_SEP + filename;
+ if (!FileUtil::IsDirectory(full_path))
+ out.emplace_back(base.OpenFile(full_path, perms));
+ return true;
+ });
return out;
}
-bool RealVfsFile::Close() {
- return backing.Close();
+template <>
+std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDirectory>() const {
+ if (perms == Mode::Append)
+ return {};
+
+ std::vector<VirtualDir> out;
+ FileUtil::ForeachDirectoryEntry(
+ nullptr, path,
+ [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) {
+ const std::string full_path = directory + DIR_SEP + filename;
+ if (FileUtil::IsDirectory(full_path))
+ out.emplace_back(base.OpenDirectory(full_path, perms));
+ return true;
+ });
+
+ return out;
}
-RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
- : path(FileUtil::RemoveTrailingSlash(path_)), parent_path(FileUtil::GetParentPath(path)),
+RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_)
+ : base(base_), path(FileUtil::RemoveTrailingSlash(path_)),
+ parent_path(FileUtil::GetParentPath(path)),
path_components(FileUtil::SplitPathComponents(path)),
parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)),
perms(perms_) {
if (!FileUtil::Exists(path) && perms & Mode::WriteAppend)
FileUtil::CreateDir(path);
+}
- if (perms == Mode::Append)
- return;
+std::shared_ptr<VfsFile> RealVfsDirectory::GetFileRelative(std::string_view path) const {
+ const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
+ if (!FileUtil::Exists(full_path))
+ return nullptr;
+ return base.OpenFile(full_path, perms);
+}
- FileUtil::ForeachDirectoryEntry(
- nullptr, path,
- [this](u64* entries_out, const std::string& directory, const std::string& filename) {
- std::string full_path = directory + DIR_SEP + filename;
- if (FileUtil::IsDirectory(full_path))
- subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(full_path, perms));
- else
- files.emplace_back(std::make_shared<RealVfsFile>(full_path, perms));
- return true;
- });
+std::shared_ptr<VfsDirectory> RealVfsDirectory::GetDirectoryRelative(std::string_view path) const {
+ const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
+ if (!FileUtil::Exists(full_path))
+ return nullptr;
+ return base.OpenDirectory(full_path, perms);
+}
+
+std::shared_ptr<VfsFile> RealVfsDirectory::GetFile(std::string_view name) const {
+ return GetFileRelative(name);
+}
+
+std::shared_ptr<VfsDirectory> RealVfsDirectory::GetSubdirectory(std::string_view name) const {
+ return GetDirectoryRelative(name);
+}
+
+std::shared_ptr<VfsFile> RealVfsDirectory::CreateFileRelative(std::string_view path) {
+ const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
+ return base.CreateFile(full_path, perms);
+}
+
+std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateDirectoryRelative(std::string_view path) {
+ const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path));
+ auto parent = std::string(FileUtil::GetParentPath(full_path));
+ return base.CreateDirectory(full_path, perms);
+}
+
+bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
+ auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(name));
+ return base.DeleteDirectory(full_path);
}
std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const {
- return files;
+ return IterateEntries<RealVfsFile, VfsFile>();
}
std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const {
- return subdirectories;
+ return IterateEntries<RealVfsDirectory, VfsDirectory>();
}
bool RealVfsDirectory::IsWritable() const {
@@ -142,57 +366,32 @@ std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
if (path_components.size() <= 1)
return nullptr;
- return std::make_shared<RealVfsDirectory>(parent_path, perms);
+ return base.OpenDirectory(parent_path, perms);
}
std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) {
const std::string subdir_path = (path + DIR_SEP).append(name);
-
- if (!FileUtil::CreateDir(subdir_path)) {
- return nullptr;
- }
-
- subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(subdir_path, perms));
- return subdirectories.back();
+ return base.CreateDirectory(subdir_path, perms);
}
std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) {
const std::string file_path = (path + DIR_SEP).append(name);
-
- if (!FileUtil::CreateEmptyFile(file_path)) {
- return nullptr;
- }
-
- files.emplace_back(std::make_shared<RealVfsFile>(file_path, perms));
- return files.back();
+ return base.CreateFile(file_path, perms);
}
bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) {
const std::string subdir_path = (path + DIR_SEP).append(name);
-
- return FileUtil::DeleteDirRecursively(subdir_path);
+ return base.DeleteDirectory(subdir_path);
}
bool RealVfsDirectory::DeleteFile(std::string_view name) {
- const auto file = GetFile(name);
-
- if (file == nullptr) {
- return false;
- }
-
- files.erase(std::find(files.begin(), files.end(), file));
-
- auto real_file = std::static_pointer_cast<RealVfsFile>(file);
- real_file->Close();
-
const std::string file_path = (path + DIR_SEP).append(name);
- return FileUtil::Delete(file_path);
+ return base.DeleteFile(file_path);
}
bool RealVfsDirectory::Rename(std::string_view name) {
const std::string new_name = (parent_path + DIR_SEP).append(name);
-
- return FileUtil::Rename(path, new_name);
+ return base.MoveFile(path, new_name) != nullptr;
}
std::string RealVfsDirectory::GetFullPath() const {
@@ -202,16 +401,6 @@ std::string RealVfsDirectory::GetFullPath() const {
}
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- const auto iter = std::find(files.begin(), files.end(), file);
- if (iter == files.end())
- return false;
-
- const std::ptrdiff_t offset = std::distance(files.begin(), iter);
- files[offset] = files.back();
- files.pop_back();
-
- subdirectories.emplace_back(std::move(dir));
-
- return true;
+ return false;
}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index 243d58576..8a1e79ef6 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -6,18 +6,45 @@
#include <string_view>
+#include <boost/container/flat_map.hpp>
#include "common/file_util.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/vfs.h"
namespace FileSys {
+class RealVfsFilesystem : public VfsFilesystem {
+public:
+ RealVfsFilesystem();
+
+ std::string GetName() const override;
+ bool IsReadable() const override;
+ bool IsWritable() const override;
+ VfsEntryType GetEntryType(std::string_view path) const override;
+ VirtualFile OpenFile(std::string_view path, Mode perms = Mode::Read) override;
+ VirtualFile CreateFile(std::string_view path, Mode perms = Mode::ReadWrite) override;
+ VirtualFile CopyFile(std::string_view old_path, std::string_view new_path) override;
+ VirtualFile MoveFile(std::string_view old_path, std::string_view new_path) override;
+ bool DeleteFile(std::string_view path) override;
+ VirtualDir OpenDirectory(std::string_view path, Mode perms = Mode::Read) override;
+ VirtualDir CreateDirectory(std::string_view path, Mode perms = Mode::ReadWrite) override;
+ VirtualDir CopyDirectory(std::string_view old_path, std::string_view new_path) override;
+ VirtualDir MoveDirectory(std::string_view old_path, std::string_view new_path) override;
+ bool DeleteDirectory(std::string_view path) override;
+
+private:
+ boost::container::flat_map<std::string, std::weak_ptr<FileUtil::IOFile>> cache;
+};
+
// An implmentation of VfsFile that represents a file on the user's computer.
-struct RealVfsFile : public VfsFile {
- friend struct RealVfsDirectory;
+class RealVfsFile : public VfsFile {
+ friend class RealVfsDirectory;
+ friend class RealVfsFilesystem;
- RealVfsFile(const std::string& name, Mode perms = Mode::Read);
+ RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<FileUtil::IOFile> backing,
+ const std::string& path, Mode perms = Mode::Read);
+public:
std::string GetName() const override;
size_t GetSize() const override;
bool Resize(size_t new_size) override;
@@ -31,7 +58,8 @@ struct RealVfsFile : public VfsFile {
private:
bool Close();
- FileUtil::IOFile backing;
+ RealVfsFilesystem& base;
+ std::shared_ptr<FileUtil::IOFile> backing;
std::string path;
std::string parent_path;
std::vector<std::string> path_components;
@@ -40,9 +68,19 @@ private:
};
// An implementation of VfsDirectory that represents a directory on the user's computer.
-struct RealVfsDirectory : public VfsDirectory {
- RealVfsDirectory(const std::string& path, Mode perms = Mode::Read);
+class RealVfsDirectory : public VfsDirectory {
+ friend class RealVfsFilesystem;
+ RealVfsDirectory(RealVfsFilesystem& base, const std::string& path, Mode perms = Mode::Read);
+
+public:
+ std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const override;
+ std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const override;
+ std::shared_ptr<VfsFile> GetFile(std::string_view name) const override;
+ std::shared_ptr<VfsDirectory> GetSubdirectory(std::string_view name) const override;
+ std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path) override;
+ std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path) override;
+ bool DeleteSubdirectoryRecursive(std::string_view name) override;
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
bool IsWritable() const override;
@@ -60,13 +98,15 @@ protected:
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
private:
+ template <typename T, typename R>
+ std::vector<std::shared_ptr<R>> IterateEntries() const;
+
+ RealVfsFilesystem& base;
std::string path;
std::string parent_path;
std::vector<std::string> path_components;
std::vector<std::string> parent_components;
Mode perms;
- std::vector<std::shared_ptr<VfsFile>> files;
- std::vector<std::shared_ptr<VfsDirectory>> subdirectories;
};
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h
index ba469647b..b3b468233 100644
--- a/src/core/file_sys/vfs_vector.h
+++ b/src/core/file_sys/vfs_vector.h
@@ -10,7 +10,8 @@ namespace FileSys {
// An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
// Vector data is supplied upon construction.
-struct VectorVfsDirectory : public VfsDirectory {
+class VectorVfsDirectory : public VfsDirectory {
+public:
explicit VectorVfsDirectory(std::vector<VirtualFile> files = {},
std::vector<VirtualDir> dirs = {}, VirtualDir parent = nullptr,
std::string name = "");
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp
index 2d776c693..9dd493efb 100644
--- a/src/core/frontend/emu_window.cpp
+++ b/src/core/frontend/emu_window.cpp
@@ -8,6 +8,8 @@
#include "core/frontend/input.h"
#include "core/settings.h"
+namespace Core::Frontend {
+
class EmuWindow::TouchState : public Input::Factory<Input::TouchDevice>,
public std::enable_shared_from_this<TouchState> {
public:
@@ -108,3 +110,5 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) {
NotifyFramebufferLayoutChanged(Layout::DefaultFrameLayout(width, height));
}
+
+} // namespace Core::Frontend
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index e8c29adfb..384dc7822 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -10,6 +10,8 @@
#include "common/common_types.h"
#include "core/frontend/framebuffer_layout.h"
+namespace Core::Frontend {
+
/**
* Abstraction class used to provide an interface between emulation code and the frontend
* (e.g. SDL, QGLWidget, GLFW, etc...).
@@ -166,3 +168,5 @@ private:
*/
std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y);
};
+
+} // namespace Core::Frontend
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 75f6b8235..332e5c3d0 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -41,40 +41,42 @@
#include "core/loader/loader.h"
#include "core/memory.h"
-const int GDB_BUFFER_SIZE = 10000;
+namespace GDBStub {
+namespace {
+constexpr int GDB_BUFFER_SIZE = 10000;
-const char GDB_STUB_START = '$';
-const char GDB_STUB_END = '#';
-const char GDB_STUB_ACK = '+';
-const char GDB_STUB_NACK = '-';
+constexpr char GDB_STUB_START = '$';
+constexpr char GDB_STUB_END = '#';
+constexpr char GDB_STUB_ACK = '+';
+constexpr char GDB_STUB_NACK = '-';
#ifndef SIGTRAP
-const u32 SIGTRAP = 5;
+constexpr u32 SIGTRAP = 5;
#endif
#ifndef SIGTERM
-const u32 SIGTERM = 15;
+constexpr u32 SIGTERM = 15;
#endif
#ifndef MSG_WAITALL
-const u32 MSG_WAITALL = 8;
+constexpr u32 MSG_WAITALL = 8;
#endif
-const u32 LR_REGISTER = 30;
-const u32 SP_REGISTER = 31;
-const u32 PC_REGISTER = 32;
-const u32 CPSR_REGISTER = 33;
-const u32 UC_ARM64_REG_Q0 = 34;
-const u32 FPSCR_REGISTER = 66;
+constexpr u32 LR_REGISTER = 30;
+constexpr u32 SP_REGISTER = 31;
+constexpr u32 PC_REGISTER = 32;
+constexpr u32 CPSR_REGISTER = 33;
+constexpr u32 UC_ARM64_REG_Q0 = 34;
+constexpr u32 FPSCR_REGISTER = 66;
// TODO/WiP - Used while working on support for FPU
-const u32 TODO_DUMMY_REG_997 = 997;
-const u32 TODO_DUMMY_REG_998 = 998;
+constexpr u32 TODO_DUMMY_REG_997 = 997;
+constexpr u32 TODO_DUMMY_REG_998 = 998;
// For sample XML files see the GDB source /gdb/features
// GDB also wants the l character at the start
// This XML defines what the registers are for this specific ARM device
-static const char* target_xml =
+constexpr char target_xml[] =
R"(l<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
@@ -140,30 +142,28 @@ static const char* target_xml =
</target>
)";
-namespace GDBStub {
-
-static int gdbserver_socket = -1;
+int gdbserver_socket = -1;
-static u8 command_buffer[GDB_BUFFER_SIZE];
-static u32 command_length;
+u8 command_buffer[GDB_BUFFER_SIZE];
+u32 command_length;
-static u32 latest_signal = 0;
-static bool memory_break = false;
+u32 latest_signal = 0;
+bool memory_break = false;
-static Kernel::Thread* current_thread = nullptr;
-static u32 current_core = 0;
+Kernel::Thread* current_thread = nullptr;
+u32 current_core = 0;
// Binding to a port within the reserved ports range (0-1023) requires root permissions,
// so default to a port outside of that range.
-static u16 gdbstub_port = 24689;
+u16 gdbstub_port = 24689;
-static bool halt_loop = true;
-static bool step_loop = false;
-static bool send_trap = false;
+bool halt_loop = true;
+bool step_loop = false;
+bool send_trap = false;
// If set to false, the server will never be started and no
// gdbstub-related functions will be executed.
-static std::atomic<bool> server_enabled(false);
+std::atomic<bool> server_enabled(false);
#ifdef _WIN32
WSADATA InitData;
@@ -171,23 +171,26 @@ WSADATA InitData;
struct Breakpoint {
bool active;
- PAddr addr;
+ VAddr addr;
u64 len;
+ std::array<u8, 4> inst;
};
-static std::map<u64, Breakpoint> breakpoints_execute;
-static std::map<u64, Breakpoint> breakpoints_read;
-static std::map<u64, Breakpoint> breakpoints_write;
+using BreakpointMap = std::map<VAddr, Breakpoint>;
+BreakpointMap breakpoints_execute;
+BreakpointMap breakpoints_read;
+BreakpointMap breakpoints_write;
struct Module {
std::string name;
- PAddr beg;
- PAddr end;
+ VAddr beg;
+ VAddr end;
};
-static std::vector<Module> modules;
+std::vector<Module> modules;
+} // Anonymous namespace
-void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext) {
+void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext) {
Module module;
if (add_elf_ext) {
Common::SplitPath(name, nullptr, &module.name, nullptr);
@@ -418,11 +421,11 @@ static u8 CalculateChecksum(const u8* buffer, size_t length) {
}
/**
- * Get the list of breakpoints for a given breakpoint type.
+ * Get the map of breakpoints for a given breakpoint type.
*
- * @param type Type of breakpoint list.
+ * @param type Type of breakpoint map.
*/
-static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) {
+static BreakpointMap& GetBreakpointMap(BreakpointType type) {
switch (type) {
case BreakpointType::Execute:
return breakpoints_execute;
@@ -441,20 +444,24 @@ static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) {
* @param type Type of breakpoint.
* @param addr Address of breakpoint.
*/
-static void RemoveBreakpoint(BreakpointType type, PAddr addr) {
- std::map<u64, Breakpoint>& p = GetBreakpointList(type);
+static void RemoveBreakpoint(BreakpointType type, VAddr addr) {
+ BreakpointMap& p = GetBreakpointMap(type);
- auto bp = p.find(static_cast<u64>(addr));
- if (bp != p.end()) {
- LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
- bp->second.len, bp->second.addr, static_cast<int>(type));
- p.erase(static_cast<u64>(addr));
+ const auto bp = p.find(addr);
+ if (bp == p.end()) {
+ return;
}
+
+ LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
+ bp->second.len, bp->second.addr, static_cast<int>(type));
+ Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size());
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
+ p.erase(addr);
}
-BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) {
- std::map<u64, Breakpoint>& p = GetBreakpointList(type);
- auto next_breakpoint = p.lower_bound(static_cast<u64>(addr));
+BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, BreakpointType type) {
+ const BreakpointMap& p = GetBreakpointMap(type);
+ const auto next_breakpoint = p.lower_bound(addr);
BreakpointAddress breakpoint;
if (next_breakpoint != p.end()) {
@@ -468,36 +475,38 @@ BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type)
return breakpoint;
}
-bool CheckBreakpoint(PAddr addr, BreakpointType type) {
+bool CheckBreakpoint(VAddr addr, BreakpointType type) {
if (!IsConnected()) {
return false;
}
- std::map<u64, Breakpoint>& p = GetBreakpointList(type);
+ const BreakpointMap& p = GetBreakpointMap(type);
+ const auto bp = p.find(addr);
- auto bp = p.find(static_cast<u64>(addr));
- if (bp != p.end()) {
- u64 len = bp->second.len;
+ if (bp == p.end()) {
+ return false;
+ }
- // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints
- // no matter if it's a 4-byte or 2-byte instruction. When you execute a
- // Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on
- // two instructions instead of the single instruction you placed the breakpoint
- // on. So, as a way to make sure that execution breakpoints are only breaking
- // on the instruction that was specified, set the length of an execution
- // breakpoint to 1. This should be fine since the CPU should never begin executing
- // an instruction anywhere except the beginning of the instruction.
- if (type == BreakpointType::Execute) {
- len = 1;
- }
+ u64 len = bp->second.len;
- if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
- LOG_DEBUG(Debug_GDBStub,
- "Found breakpoint type {} @ {:016X}, range: {:016X}"
- " - {:016X} ({:X} bytes)",
- static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len);
- return true;
- }
+ // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints
+ // no matter if it's a 4-byte or 2-byte instruction. When you execute a
+ // Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on
+ // two instructions instead of the single instruction you placed the breakpoint
+ // on. So, as a way to make sure that execution breakpoints are only breaking
+ // on the instruction that was specified, set the length of an execution
+ // breakpoint to 1. This should be fine since the CPU should never begin executing
+ // an instruction anywhere except the beginning of the instruction.
+ if (type == BreakpointType::Execute) {
+ len = 1;
+ }
+
+ if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
+ LOG_DEBUG(Debug_GDBStub,
+ "Found breakpoint type {} @ {:016X}, range: {:016X}"
+ " - {:016X} ({:X} bytes)",
+ static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len);
+ return true;
}
return false;
@@ -931,6 +940,7 @@ static void WriteMemory() {
GdbHexToMem(data.data(), len_pos + 1, len);
Memory::WriteBlock(addr, data.data(), len);
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
SendReply("OK");
}
@@ -950,6 +960,7 @@ static void Step() {
step_loop = true;
halt_loop = true;
send_trap = true;
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
}
/// Tell the CPU if we hit a memory breakpoint.
@@ -966,6 +977,7 @@ static void Continue() {
memory_break = false;
step_loop = false;
halt_loop = false;
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
}
/**
@@ -975,13 +987,17 @@ static void Continue() {
* @param addr Address of breakpoint.
* @param len Length of breakpoint.
*/
-static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) {
- std::map<u64, Breakpoint>& p = GetBreakpointList(type);
+static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
+ BreakpointMap& p = GetBreakpointMap(type);
Breakpoint breakpoint;
breakpoint.active = true;
breakpoint.addr = addr;
breakpoint.len = len;
+ Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
+ static constexpr std::array<u8, 4> btrap{{0xd4, 0x20, 0x7d, 0x0}};
+ Memory::WriteBlock(addr, btrap.data(), btrap.size());
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
p.insert({addr, breakpoint});
LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}",
@@ -1015,7 +1031,7 @@ static void AddBreakpoint() {
auto start_offset = command_buffer + 3;
auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
- PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
+ VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
start_offset = addr_pos + 1;
u64 len =
@@ -1064,7 +1080,7 @@ static void RemoveBreakpoint() {
auto start_offset = command_buffer + 3;
auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
- PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
+ VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
if (type == BreakpointType::Access) {
// Access is made up of Read and Write types, so add both breakpoints
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h
index a6b50c26c..5a36524b2 100644
--- a/src/core/gdbstub/gdbstub.h
+++ b/src/core/gdbstub/gdbstub.h
@@ -22,7 +22,7 @@ enum class BreakpointType {
};
struct BreakpointAddress {
- PAddr address;
+ VAddr address;
BreakpointType type;
};
@@ -53,7 +53,7 @@ bool IsServerEnabled();
bool IsConnected();
/// Register module.
-void RegisterModule(std::string name, PAddr beg, PAddr end, bool add_elf_ext = true);
+void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext = true);
/**
* Signal to the gdbstub server that it should halt CPU execution.
@@ -74,7 +74,7 @@ void HandlePacket();
* @param addr Address to search from.
* @param type Type of breakpoint.
*/
-BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, GDBStub::BreakpointType type);
+BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, GDBStub::BreakpointType type);
/**
* Check if a breakpoint of the specified type exists at the given address.
@@ -82,7 +82,7 @@ BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, GDBStub::BreakpointTy
* @param addr Address of breakpoint.
* @param type Type of breakpoint.
*/
-bool CheckBreakpoint(PAddr addr, GDBStub::BreakpointType type);
+bool CheckBreakpoint(VAddr addr, GDBStub::BreakpointType type);
/// If set to true, the CPU will halt at the beginning of the next CPU loop.
bool GetCpuHaltFlag();
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 7a17ed162..03a954a9f 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -32,9 +32,8 @@ static ResultCode WaitForAddress(VAddr address, s64 timeout) {
}
// Gets the threads waiting on an address.
-static void GetThreadsWaitingOnAddress(std::vector<SharedPtr<Thread>>& waiting_threads,
- VAddr address) {
- auto RetrieveWaitingThreads =
+static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) {
+ const auto RetrieveWaitingThreads =
[](size_t core_index, std::vector<SharedPtr<Thread>>& waiting_threads, VAddr arb_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
auto& thread_list = scheduler->GetThreadList();
@@ -45,16 +44,20 @@ static void GetThreadsWaitingOnAddress(std::vector<SharedPtr<Thread>>& waiting_t
}
};
- // Retrieve a list of all threads that are waiting for this address.
- RetrieveWaitingThreads(0, waiting_threads, address);
- RetrieveWaitingThreads(1, waiting_threads, address);
- RetrieveWaitingThreads(2, waiting_threads, address);
- RetrieveWaitingThreads(3, waiting_threads, address);
+ // Retrieve all threads that are waiting for this address.
+ std::vector<SharedPtr<Thread>> threads;
+ RetrieveWaitingThreads(0, threads, address);
+ RetrieveWaitingThreads(1, threads, address);
+ RetrieveWaitingThreads(2, threads, address);
+ RetrieveWaitingThreads(3, threads, address);
+
// Sort them by priority, such that the highest priority ones come first.
- std::sort(waiting_threads.begin(), waiting_threads.end(),
+ std::sort(threads.begin(), threads.end(),
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
return lhs->current_priority < rhs->current_priority;
});
+
+ return threads;
}
// Wake up num_to_wake (or all) threads in a vector.
@@ -76,9 +79,7 @@ static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num
// Signals an address being waited on.
ResultCode SignalToAddress(VAddr address, s32 num_to_wake) {
- // Get threads waiting on the address.
- std::vector<SharedPtr<Thread>> waiting_threads;
- GetThreadsWaitingOnAddress(waiting_threads, address);
+ std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
WakeThreads(waiting_threads, num_to_wake);
return RESULT_SUCCESS;
@@ -110,12 +111,11 @@ ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 valu
}
// Get threads waiting on the address.
- std::vector<SharedPtr<Thread>> waiting_threads;
- GetThreadsWaitingOnAddress(waiting_threads, address);
+ std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
// Determine the modified value depending on the waiting count.
s32 updated_value;
- if (waiting_threads.size() == 0) {
+ if (waiting_threads.empty()) {
updated_value = value - 1;
} else if (num_to_wake <= 0 || waiting_threads.size() <= static_cast<u32>(num_to_wake)) {
updated_value = value + 1;
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 7933c105c..134e41ebc 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -14,8 +14,8 @@
namespace Kernel {
-ClientPort::ClientPort() {}
-ClientPort::~ClientPort() {}
+ClientPort::ClientPort() = default;
+ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
// Note: Threads do not wait for the server endpoint to call
@@ -40,4 +40,12 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
}
+void ClientPort::ConnectionClosed() {
+ if (active_sessions == 0) {
+ return;
+ }
+
+ --active_sessions;
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index b42c94bde..b1269ea5c 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -37,14 +37,20 @@ public:
*/
ResultVal<SharedPtr<ClientSession>> Connect();
- SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
- u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
- u32 active_sessions; ///< Number of currently open sessions to this port
- std::string name; ///< Name of client port (optional)
+ /**
+ * Signifies that a previously active connection has been closed,
+ * decreasing the total number of active connections to this port.
+ */
+ void ConnectionClosed();
private:
ClientPort();
~ClientPort() override;
+
+ SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
+ u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
+ u32 active_sessions = 0; ///< Number of currently open sessions to this port
+ std::string name; ///< Name of client port (optional)
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 1c99911b2..3c20c05e8 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -31,10 +31,9 @@ public:
return HANDLE_TYPE;
}
- ResetType reset_type; ///< Current ResetType
-
- bool signaled; ///< Whether the event has already been signaled
- std::string name; ///< Name of event (optional)
+ ResetType GetResetType() const {
+ return reset_type;
+ }
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
@@ -47,6 +46,11 @@ public:
private:
Event();
~Event() override;
+
+ ResetType reset_type; ///< Current ResetType
+
+ bool signaled; ///< Whether the event has already been signaled
+ std::string name; ///< Name of event (optional)
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 5dd1b68d7..82a3fb5a8 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -201,7 +201,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdb
return RESULT_SUCCESS;
}
-ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
+ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread) {
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf;
Memory::ReadBlock(*thread.owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
dst_cmdbuf.size() * sizeof(u32));
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 9ce52db24..f0d07f1b6 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -132,7 +132,7 @@ public:
ResultCode PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf, Process& src_process,
HandleTable& src_table);
/// Writes data from this context back to the requesting process/thread.
- ResultCode WriteToOutgoingCommandBuffer(Thread& thread);
+ ResultCode WriteToOutgoingCommandBuffer(const Thread& thread);
u32_le GetCommand() const {
return command;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1b0cd0abf..8c19e86d3 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -11,7 +11,7 @@
namespace Kernel {
-unsigned int Object::next_object_id;
+std::atomic<u32> Object::next_object_id{0};
/// Initialize the kernel
void Init() {
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 83df68dfd..526ac9cc3 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -4,6 +4,7 @@
#pragma once
+#include <atomic>
#include <string>
#include <utility>
@@ -42,8 +43,8 @@ public:
virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only.
- unsigned int GetObjectId() const {
- return object_id;
+ u32 GetObjectId() const {
+ return object_id.load(std::memory_order_relaxed);
}
virtual std::string GetTypeName() const {
@@ -61,23 +62,23 @@ public:
bool IsWaitable() const;
public:
- static unsigned int next_object_id;
+ static std::atomic<u32> next_object_id;
private:
friend void intrusive_ptr_add_ref(Object*);
friend void intrusive_ptr_release(Object*);
- unsigned int ref_count = 0;
- unsigned int object_id = next_object_id++;
+ std::atomic<u32> ref_count{0};
+ std::atomic<u32> object_id{next_object_id++};
};
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
inline void intrusive_ptr_add_ref(Object* object) {
- ++object->ref_count;
+ object->ref_count.fetch_add(1, std::memory_order_relaxed);
}
inline void intrusive_ptr_release(Object* object) {
- if (--object->ref_count == 0) {
+ if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete object;
}
}
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 94065c736..e770b9103 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -25,7 +25,7 @@ Scheduler::~Scheduler() {
}
}
-bool Scheduler::HaveReadyThreads() {
+bool Scheduler::HaveReadyThreads() const {
std::lock_guard<std::mutex> lock(scheduler_mutex);
return ready_queue.get_first() != nullptr;
}
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index 1a4ee8f36..6a61ef64e 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -21,7 +21,7 @@ public:
~Scheduler();
/// Returns whether there are any threads that are ready to run.
- bool HaveReadyThreads();
+ bool HaveReadyThreads() const;
/// Reschedules to the next available thread (call after current thread is suspended)
void Reschedule();
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 60370e9ec..d09ca5992 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -27,7 +27,7 @@ ServerSession::~ServerSession() {
// Decrease the port's connection count.
if (parent->port)
- parent->port->active_sessions--;
+ parent->port->ConnectionClosed();
// TODO(Subv): Wake up all the ClientSession's waiting threads and set
// the SendSyncRequest result to 0xC920181A.
@@ -71,6 +71,14 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
const u32 object_id{context.GetDomainMessageHeader()->object_id};
switch (domain_message_header->command) {
case IPC::DomainMessageHeader::CommandType::SendMessage:
+ if (object_id > domain_request_handlers.size()) {
+ LOG_CRITICAL(IPC,
+ "object_id {} is too big! This probably means a recent service call "
+ "to {} needed to return a new interface!",
+ object_id, name);
+ UNREACHABLE();
+ return RESULT_SUCCESS; // Ignore error if asserts are off
+ }
return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 5db2db687..b24f409b3 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -532,7 +532,6 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
CASCADE_RESULT(thread->guest_handle, g_handle_table.Create(thread));
*out_handle = thread->guest_handle;
- Core::System::GetInstance().PrepareReschedule();
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
LOG_TRACE(Kernel_SVC,
@@ -706,8 +705,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
- ASSERT(thread->status != ThreadStatus::Running);
- thread->status = ThreadStatus::WaitMutex;
+ ASSERT(thread->status == ThreadStatus::WaitMutex);
thread->wakeup_callback = nullptr;
owner->AddMutexWaiter(thread);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index b9022feae..a1a7867ce 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -23,6 +23,7 @@
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
+#include "core/hle/lock.h"
#include "core/hle/result.h"
#include "core/memory.h"
@@ -104,6 +105,10 @@ void ExitCurrentThread() {
*/
static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
const auto proper_handle = static_cast<Handle>(thread_handle);
+
+ // Lock the global kernel mutex when we enter the kernel HLE.
+ std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
+
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
if (thread == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
@@ -155,8 +160,10 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
if (nanoseconds == -1)
return;
- CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType,
- callback_handle);
+ // This function might be called from any thread so we have to be cautious and use the
+ // thread-safe version of ScheduleEvent.
+ CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType,
+ callback_handle);
}
void Thread::CancelWakeupTimer() {
@@ -419,12 +426,33 @@ VAddr Thread::GetCommandBufferAddress() const {
}
void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
+ if (thread->lock_owner == this) {
+ // If the thread is already waiting for this thread to release the mutex, ensure that the
+ // waiters list is consistent and return without doing anything.
+ auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
+ ASSERT(itr != wait_mutex_threads.end());
+ return;
+ }
+
+ // A thread can't wait on two different mutexes at the same time.
+ ASSERT(thread->lock_owner == nullptr);
+
+ // Ensure that the thread is not already in the list of mutex waiters
+ auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
+ ASSERT(itr == wait_mutex_threads.end());
+
thread->lock_owner = this;
wait_mutex_threads.emplace_back(std::move(thread));
UpdatePriority();
}
void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
+ ASSERT(thread->lock_owner == this);
+
+ // Ensure that the thread is in the list of mutex waiters
+ auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
+ ASSERT(itr != wait_mutex_threads.end());
+
boost::remove_erase(wait_mutex_threads, thread);
thread->lock_owner = nullptr;
UpdatePriority();
diff --git a/src/core/hle/romfs.cpp b/src/core/hle/romfs.cpp
deleted file mode 100644
index 3157df71d..000000000
--- a/src/core/hle/romfs.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <cstring>
-#include "common/swap.h"
-#include "core/hle/romfs.h"
-
-namespace RomFS {
-
-struct Header {
- u32_le header_length;
- u32_le dir_hash_table_offset;
- u32_le dir_hash_table_length;
- u32_le dir_table_offset;
- u32_le dir_table_length;
- u32_le file_hash_table_offset;
- u32_le file_hash_table_length;
- u32_le file_table_offset;
- u32_le file_table_length;
- u32_le data_offset;
-};
-
-static_assert(sizeof(Header) == 0x28, "Header has incorrect size");
-
-struct DirectoryMetadata {
- u32_le parent_dir_offset;
- u32_le next_dir_offset;
- u32_le first_child_dir_offset;
- u32_le first_file_offset;
- u32_le same_hash_next_dir_offset;
- u32_le name_length; // in bytes
- // followed by directory name
-};
-
-static_assert(sizeof(DirectoryMetadata) == 0x18, "DirectoryMetadata has incorrect size");
-
-struct FileMetadata {
- u32_le parent_dir_offset;
- u32_le next_file_offset;
- u64_le data_offset;
- u64_le data_length;
- u32_le same_hash_next_file_offset;
- u32_le name_length; // in bytes
- // followed by file name
-};
-
-static_assert(sizeof(FileMetadata) == 0x20, "FileMetadata has incorrect size");
-
-static bool MatchName(const u8* buffer, u32 name_length, const std::u16string& name) {
- std::vector<char16_t> name_buffer(name_length / sizeof(char16_t));
- std::memcpy(name_buffer.data(), buffer, name_length);
- return name == std::u16string(name_buffer.begin(), name_buffer.end());
-}
-
-const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path) {
- constexpr u32 INVALID_FIELD = 0xFFFFFFFF;
-
- // Split path into directory names and file name
- std::vector<std::u16string> dir_names = path;
- dir_names.pop_back();
- const std::u16string& file_name = path.back();
-
- Header header;
- std::memcpy(&header, romfs, sizeof(header));
-
- // Find directories of each level
- DirectoryMetadata dir;
- const u8* current_dir = romfs + header.dir_table_offset;
- std::memcpy(&dir, current_dir, sizeof(dir));
- for (const std::u16string& dir_name : dir_names) {
- u32 child_dir_offset;
- child_dir_offset = dir.first_child_dir_offset;
- while (true) {
- if (child_dir_offset == INVALID_FIELD) {
- return nullptr;
- }
- const u8* current_child_dir = romfs + header.dir_table_offset + child_dir_offset;
- std::memcpy(&dir, current_child_dir, sizeof(dir));
- if (MatchName(current_child_dir + sizeof(dir), dir.name_length, dir_name)) {
- current_dir = current_child_dir;
- break;
- }
- child_dir_offset = dir.next_dir_offset;
- }
- }
-
- // Find the file
- FileMetadata file;
- u32 file_offset = dir.first_file_offset;
- while (file_offset != INVALID_FIELD) {
- const u8* current_file = romfs + header.file_table_offset + file_offset;
- std::memcpy(&file, current_file, sizeof(file));
- if (MatchName(current_file + sizeof(file), file.name_length, file_name)) {
- return romfs + header.data_offset + file.data_offset;
- }
- file_offset = file.next_file_offset;
- }
- return nullptr;
-}
-
-} // namespace RomFS
diff --git a/src/core/hle/romfs.h b/src/core/hle/romfs.h
deleted file mode 100644
index ee9f29760..000000000
--- a/src/core/hle/romfs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <string>
-#include <vector>
-#include "common/common_types.h"
-
-namespace RomFS {
-
-/**
- * Gets the pointer to a file in a RomFS image.
- * @param romfs The pointer to the RomFS image
- * @param path A vector containing the directory names and file name of the path to the file
- * @return the pointer to the file
- * @todo reimplement this with a full RomFS manager
- */
-const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path);
-
-} // namespace RomFS
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 6d15b46ed..f3c5b1b9c 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -42,7 +42,7 @@ public:
{0, &IProfile::Get, "Get"},
{1, &IProfile::GetBase, "GetBase"},
{10, nullptr, "GetImageSize"},
- {11, nullptr, "LoadImage"},
+ {11, &IProfile::LoadImage, "LoadImage"},
};
RegisterHandlers(functions);
}
@@ -83,6 +83,27 @@ private:
rb.PushRaw(profile_base);
}
+ void LoadImage(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ // smallest jpeg https://github.com/mathiasbynens/small/blob/master/jpeg.jpg
+ // TODO(mailwl): load actual profile image from disk, width 256px, max size 0x20000
+ const u32 jpeg_size = 107;
+ static const std::array<u8, jpeg_size> jpeg{
+ 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03,
+ 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x08, 0x06, 0x06, 0x05, 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a,
+ 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10,
+ 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x11, 0x00,
+ 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01,
+ 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
+ };
+ ctx.WriteBuffer(jpeg.data(), jpeg_size);
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(jpeg_size);
+ }
+
u128 user_id; ///< The user id this profile refers to.
};
@@ -119,6 +140,13 @@ private:
}
};
+void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(1);
+}
+
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 0a01d954c..88cabaa01 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -14,6 +14,7 @@ public:
public:
explicit Interface(std::shared_ptr<Module> module, const char* name);
+ void GetUserCount(Kernel::HLERequestContext& ctx);
void GetUserExistence(Kernel::HLERequestContext& ctx);
void ListAllUsers(Kernel::HLERequestContext& ctx);
void ListOpenUsers(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 9ffb40b22..8b2a71f37 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetUserCount"},
+ {0, &ACC_SU::GetUserCount, "GetUserCount"},
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
{2, &ACC_SU::ListAllUsers, "ListAllUsers"},
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 44e21ac09..d84c8b2e1 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetUserCount"},
+ {0, &ACC_U0::GetUserCount, "GetUserCount"},
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
{2, &ACC_U0::ListAllUsers, "ListAllUsers"},
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index d101d4e0d..0ceaf06b5 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetUserCount"},
+ {0, &ACC_U1::GetUserCount, "GetUserCount"},
{1, &ACC_U1::GetUserExistence, "GetUserExistence"},
{2, &ACC_U1::ListAllUsers, "ListAllUsers"},
{3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9404d6b8c..762763463 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -136,7 +136,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
{17, nullptr, "SetControllerFirmwareUpdateSection"},
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
- {19, nullptr, "SetScreenShotImageOrientation"},
+ {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"},
{20, nullptr, "SetDesirableKeyboardLayout"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
@@ -254,6 +254,13 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
LOG_WARNING(Service_AM, "(STUBBED) called");
}
+void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+}
+
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
// TODO(Subv): Find out how AM determines the display to use, for now just create the layer
// in the Default display.
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 8f4f98346..862f338ac 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -83,6 +83,7 @@ private:
void LockExit(Kernel::HLERequestContext& ctx);
void UnlockExit(Kernel::HLERequestContext& ctx);
void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
+ void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx);
void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 7a185c6c8..4109cb7f7 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -13,6 +13,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module_ = std::make_shared<Module>();
std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager);
std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
+ std::make_shared<APM_Sys>()->InstallAsService(service_manager);
}
} // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index ce943d829..4cd8132f5 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -74,6 +74,31 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
+
+ LOG_DEBUG(Service_APM, "called");
+}
+
+APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestPerformanceMode"},
+ {1, &APM_Sys::GetPerformanceEvent, "GetPerformanceEvent"},
+ {2, nullptr, "GetThrottlingState"},
+ {3, nullptr, "GetLastThrottlingState"},
+ {4, nullptr, "ClearLastThrottlingState"},
+ {5, nullptr, "LoadAndApplySettings"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ISession>();
+
+ LOG_DEBUG(Service_APM, "called");
}
} // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index fa68c7d93..d14264ad7 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -19,4 +19,12 @@ private:
std::shared_ptr<Module> apm;
};
+class APM_Sys final : public ServiceFramework<APM_Sys> {
+public:
+ explicit APM_Sys();
+
+private:
+ void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
+};
+
} // namespace Service::APM
diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp
index 57b934dd6..bf8d40157 100644
--- a/src/core/hle/service/audio/audout_a.cpp
+++ b/src/core/hle/service/audio/audout_a.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#pragma once
-
#include "core/hle/service/audio/audout_a.h"
namespace Service::Audio {
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index b317027b6..ce709ccf4 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -4,6 +4,8 @@
#include <array>
#include <vector>
+
+#include "audio_core/codec.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
@@ -26,7 +28,7 @@ constexpr int DefaultSampleRate{48000};
class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core)
- : ServiceFramework("IAudioOut"), audio_params(audio_params), audio_core(audio_core) {
+ : ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params) {
static const FunctionInfo functions[] = {
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
@@ -48,7 +50,7 @@ public:
buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
- [=]() { buffer_event->Signal(); });
+ "IAudioOut", [=]() { buffer_event->Signal(); });
}
private:
@@ -111,10 +113,10 @@ private:
std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer));
const u64 tag{rp.Pop<u64>()};
- std::vector<u8> data(audio_buffer.buffer_size);
- Memory::ReadBlock(audio_buffer.buffer, data.data(), data.size());
+ std::vector<s16> samples(audio_buffer.buffer_size / sizeof(s16));
+ Memory::ReadBlock(audio_buffer.buffer, samples.data(), audio_buffer.buffer_size);
- if (!audio_core.QueueBuffer(stream, tag, std::move(data))) {
+ if (!audio_core.QueueBuffer(stream, tag, std::move(samples))) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded));
}
@@ -200,7 +202,7 @@ void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(DefaultSampleRate);
rb.Push<u32>(params.channel_count);
- rb.Push<u32>(static_cast<u32>(PcmFormat::Int16));
+ rb.Push<u32>(static_cast<u32>(AudioCore::Codec::PcmFormat::Int16));
rb.Push<u32>(static_cast<u32>(AudioState::Stopped));
rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface);
}
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index e5c2184d5..fd491f65d 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -38,16 +38,6 @@ private:
void ListAudioOutsImpl(Kernel::HLERequestContext& ctx);
void OpenAudioOutImpl(Kernel::HLERequestContext& ctx);
-
- enum class PcmFormat : u32 {
- Invalid = 0,
- Int8 = 1,
- Int16 = 2,
- Int24 = 3,
- Int32 = 4,
- PcmFloat = 5,
- Adpcm = 6,
- };
};
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 6aed9e2fa..9e75eb3a6 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -15,17 +15,14 @@
namespace Service::Audio {
-/// TODO(bunnei): Find a proper value for the audio_ticks
-constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)};
-
class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
public:
- explicit IAudioRenderer(AudioRendererParameter audren_params)
- : ServiceFramework("IAudioRenderer"), worker_params(audren_params) {
+ explicit IAudioRenderer(AudioCore::AudioRendererParameter audren_params)
+ : ServiceFramework("IAudioRenderer") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetAudioRendererSampleRate"},
- {1, nullptr, "GetAudioRendererSampleCount"},
- {2, nullptr, "GetAudioRendererMixBufferCount"},
+ {0, &IAudioRenderer::GetAudioRendererSampleRate, "GetAudioRendererSampleRate"},
+ {1, &IAudioRenderer::GetAudioRendererSampleCount, "GetAudioRendererSampleCount"},
+ {2, &IAudioRenderer::GetAudioRendererMixBufferCount, "GetAudioRendererMixBufferCount"},
{3, nullptr, "GetAudioRendererState"},
{4, &IAudioRenderer::RequestUpdateAudioRenderer, "RequestUpdateAudioRenderer"},
{5, &IAudioRenderer::StartAudioRenderer, "StartAudioRenderer"},
@@ -39,21 +36,8 @@ public:
RegisterHandlers(functions);
system_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioRenderer:SystemEvent");
-
- // Register event callback to update the Audio Buffer
- audio_event = CoreTiming::RegisterEvent(
- "IAudioRenderer::UpdateAudioCallback", [this](u64 userdata, int cycles_late) {
- UpdateAudioCallback();
- CoreTiming::ScheduleEvent(audio_ticks - cycles_late, audio_event);
- });
-
- // Start the audio event
- CoreTiming::ScheduleEvent(audio_ticks, audio_event);
- voice_status_list.resize(worker_params.voice_count);
- }
- ~IAudioRenderer() {
- CoreTiming::UnscheduleEvent(audio_event, 0);
+ Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
+ renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event);
}
private:
@@ -61,61 +45,31 @@ private:
system_event->Signal();
}
- void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
- UpdateDataHeader config{};
- auto buf = ctx.ReadBuffer();
- std::memcpy(&config, buf.data(), sizeof(UpdateDataHeader));
- u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4);
-
- std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count);
- std::memcpy(mem_pool_info.data(),
- buf.data() + sizeof(UpdateDataHeader) + config.behavior_size,
- memory_pool_count * sizeof(MemoryPoolInfo));
-
- std::vector<VoiceInfo> voice_info(worker_params.voice_count);
- std::memcpy(voice_info.data(),
- buf.data() + sizeof(UpdateDataHeader) + config.behavior_size +
- config.memory_pools_size + config.voice_resource_size,
- worker_params.voice_count * sizeof(VoiceInfo));
-
- UpdateDataHeader response_data{worker_params};
-
- ASSERT(ctx.GetWriteBufferSize() == response_data.total_size);
-
- std::vector<u8> output(response_data.total_size);
- std::memcpy(output.data(), &response_data, sizeof(UpdateDataHeader));
- std::vector<MemoryPoolEntry> memory_pool(memory_pool_count);
- for (unsigned i = 0; i < memory_pool.size(); i++) {
- if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestAttach)
- memory_pool[i].state = MemoryPoolStates::Attached;
- else if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestDetach)
- memory_pool[i].state = MemoryPoolStates::Detached;
- }
- std::memcpy(output.data() + sizeof(UpdateDataHeader), memory_pool.data(),
- response_data.memory_pools_size);
-
- for (unsigned i = 0; i < voice_info.size(); i++) {
- if (voice_info[i].is_new) {
- voice_status_list[i].played_sample_count = 0;
- voice_status_list[i].wave_buffer_consumed = 0;
- } else if (voice_info[i].play_state == (u8)PlayStates::Started) {
- for (u32 buff_idx = 0; buff_idx < voice_info[i].wave_buffer_count; buff_idx++) {
- voice_status_list[i].played_sample_count +=
- (voice_info[i].wave_buffer[buff_idx].end_sample_offset -
- voice_info[i].wave_buffer[buff_idx].start_sample_offset) /
- 2;
- voice_status_list[i].wave_buffer_consumed++;
- }
- }
- }
- std::memcpy(output.data() + sizeof(UpdateDataHeader) + response_data.memory_pools_size,
- voice_status_list.data(), response_data.voices_size);
+ void GetAudioRendererSampleRate(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(renderer->GetSampleRate());
+ LOG_DEBUG(Service_Audio, "called");
+ }
+
+ void GetAudioRendererSampleCount(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(renderer->GetSampleCount());
+ LOG_DEBUG(Service_Audio, "called");
+ }
- ctx.WriteBuffer(output);
+ void GetAudioRendererMixBufferCount(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(renderer->GetMixBufferCount());
+ LOG_DEBUG(Service_Audio, "called");
+ }
+ void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
+ ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer()));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
-
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
@@ -136,8 +90,6 @@ private:
}
void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
- // system_event->Signal();
-
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event);
@@ -145,131 +97,8 @@ private:
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
- enum class MemoryPoolStates : u32 { // Should be LE
- Invalid = 0x0,
- Unknown = 0x1,
- RequestDetach = 0x2,
- Detached = 0x3,
- RequestAttach = 0x4,
- Attached = 0x5,
- Released = 0x6,
- };
-
- enum class PlayStates : u8 {
- Started = 0,
- Stopped = 1,
- };
-
- struct MemoryPoolEntry {
- MemoryPoolStates state;
- u32_le unknown_4;
- u32_le unknown_8;
- u32_le unknown_c;
- };
- static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size");
-
- struct MemoryPoolInfo {
- u64_le pool_address;
- u64_le pool_size;
- MemoryPoolStates pool_state;
- INSERT_PADDING_WORDS(3); // Unknown
- };
- static_assert(sizeof(MemoryPoolInfo) == 0x20, "MemoryPoolInfo has wrong size");
-
- struct UpdateDataHeader {
- UpdateDataHeader() {}
-
- explicit UpdateDataHeader(const AudioRendererParameter& config) {
- revision = Common::MakeMagic('R', 'E', 'V', '4'); // 5.1.0 Revision
- behavior_size = 0xb0;
- memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10;
- voices_size = config.voice_count * 0x10;
- voice_resource_size = 0x0;
- effects_size = config.effect_count * 0x10;
- mixes_size = 0x0;
- sinks_size = config.sink_count * 0x20;
- performance_manager_size = 0x10;
- total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size +
- voices_size + effects_size + sinks_size + performance_manager_size;
- }
-
- u32_le revision;
- u32_le behavior_size;
- u32_le memory_pools_size;
- u32_le voices_size;
- u32_le voice_resource_size;
- u32_le effects_size;
- u32_le mixes_size;
- u32_le sinks_size;
- u32_le performance_manager_size;
- INSERT_PADDING_WORDS(6);
- u32_le total_size;
- };
- static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size");
-
- struct BiquadFilter {
- u8 enable;
- INSERT_PADDING_BYTES(1);
- s16_le numerator[3];
- s16_le denominator[2];
- };
- static_assert(sizeof(BiquadFilter) == 0xc, "BiquadFilter has wrong size");
-
- struct WaveBuffer {
- u64_le buffer_addr;
- u64_le buffer_sz;
- s32_le start_sample_offset;
- s32_le end_sample_offset;
- u8 loop;
- u8 end_of_stream;
- u8 sent_to_server;
- INSERT_PADDING_BYTES(5);
- u64 context_addr;
- u64 context_sz;
- INSERT_PADDING_BYTES(8);
- };
- static_assert(sizeof(WaveBuffer) == 0x38, "WaveBuffer has wrong size");
-
- struct VoiceInfo {
- u32_le id;
- u32_le node_id;
- u8 is_new;
- u8 is_in_use;
- u8 play_state;
- u8 sample_format;
- u32_le sample_rate;
- u32_le priority;
- u32_le sorting_order;
- u32_le channel_count;
- float_le pitch;
- float_le volume;
- BiquadFilter biquad_filter[2];
- u32_le wave_buffer_count;
- u16_le wave_buffer_head;
- INSERT_PADDING_BYTES(6);
- u64_le additional_params_addr;
- u64_le additional_params_sz;
- u32_le mix_id;
- u32_le splitter_info_id;
- WaveBuffer wave_buffer[4];
- u32_le voice_channel_resource_ids[6];
- INSERT_PADDING_BYTES(24);
- };
- static_assert(sizeof(VoiceInfo) == 0x170, "VoiceInfo is wrong size");
-
- struct VoiceOutStatus {
- u64_le played_sample_count;
- u32_le wave_buffer_consumed;
- INSERT_PADDING_WORDS(1);
- };
- static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size");
-
- /// This is used to trigger the audio event callback.
- CoreTiming::EventType* audio_event;
-
Kernel::SharedPtr<Kernel::Event> system_event;
- AudioRendererParameter worker_params;
- std::vector<VoiceOutStatus> voice_status_list;
+ std::unique_ptr<AudioCore::AudioRenderer> renderer;
};
class IAudioDevice final : public ServiceFramework<IAudioDevice> {
@@ -361,14 +190,15 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
{1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"},
{2, &AudRenU::GetAudioDevice, "GetAudioDevice"},
{3, nullptr, "OpenAudioRendererAuto"},
- {4, nullptr, "GetAudioDeviceServiceWithRevisionInfo"},
+ {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo,
+ "GetAudioDeviceServiceWithRevisionInfo"},
};
RegisterHandlers(functions);
}
void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto params = rp.PopRaw<AudioRendererParameter>();
+ auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -379,9 +209,9 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto params = rp.PopRaw<AudioRendererParameter>();
+ auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
- u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40);
+ u64 buffer_sz = Common::AlignUp(4 * params.mix_buffer_count, 0x40);
buffer_sz += params.unknown_c * 1024;
buffer_sz += 0x940 * (params.unknown_c + 1);
buffer_sz += 0x3F0 * params.voice_count;
@@ -389,7 +219,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
buffer_sz +=
Common::AlignUp((0x3C0 * (params.sink_count + params.unknown_c) + 4 * params.sample_count) *
- (params.unknown_8 + 6),
+ (params.mix_buffer_count + 6),
0x40);
if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
@@ -445,6 +275,16 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
}
+void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<Audio::IAudioDevice>();
+
+ LOG_WARNING(Service_Audio, "(STUBBED) called"); // TODO(ogniK): Figure out what is different
+ // based on the current revision
+}
+
bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
switch (feature) {
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index b9b81db4f..8600ac6e4 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -4,6 +4,7 @@
#pragma once
+#include "audio_core/audio_renderer.h"
#include "core/hle/service/service.h"
namespace Kernel {
@@ -12,24 +13,6 @@ class HLERequestContext;
namespace Service::Audio {
-struct AudioRendererParameter {
- u32_le sample_rate;
- u32_le sample_count;
- u32_le unknown_8;
- u32_le unknown_c;
- u32_le voice_count;
- u32_le sink_count;
- u32_le effect_count;
- u32_le unknown_1c;
- u8 unknown_20;
- INSERT_PADDING_BYTES(3);
- u32_le splitter_count;
- u32_le unknown_2c;
- INSERT_PADDING_WORDS(1);
- u32_le revision;
-};
-static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size");
-
class AudRenU final : public ServiceFramework<AudRenU> {
public:
explicit AudRenU();
@@ -39,6 +22,7 @@ private:
void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
void GetAudioDevice(Kernel::HLERequestContext& ctx);
+ void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx);
enum class AudioFeatures : u32 {
Splitter,
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index e17d637e4..5e416cde2 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -59,7 +59,7 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64
ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const {
std::string path(FileUtil::SanitizePath(path_));
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (path == "/" || path == "\\") {
+ if (path.empty()) {
// TODO(DarkLordZach): Why do games call this and what should it do? Works as is but...
return RESULT_SUCCESS;
}
@@ -281,15 +281,15 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
return sdmc_factory->Open();
}
-void RegisterFileSystems() {
+void RegisterFileSystems(const FileSys::VirtualFilesystem& vfs) {
romfs_factory = nullptr;
save_data_factory = nullptr;
sdmc_factory = nullptr;
- auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>(
- FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::ReadWrite);
- auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>(
- FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::ReadWrite);
+ auto nand_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
+ FileSys::Mode::ReadWrite);
+ auto sd_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir),
+ FileSys::Mode::ReadWrite);
auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
save_data_factory = std::move(savedata);
@@ -298,8 +298,8 @@ void RegisterFileSystems() {
sdmc_factory = std::move(sdcard);
}
-void InstallInterfaces(SM::ServiceManager& service_manager) {
- RegisterFileSystems();
+void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs) {
+ RegisterFileSystems(vfs);
std::make_shared<FSP_LDR>()->InstallAsService(service_manager);
std::make_shared<FSP_PR>()->InstallAsService(service_manager);
std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index d4483daa5..462c13f20 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -36,7 +36,7 @@ ResultVal<FileSys::VirtualDir> OpenSDMC();
// ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenBIS();
/// Registers all Filesystem services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager);
+void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs);
// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of
// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index e7ffb6bd1..1470f9017 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -193,13 +193,10 @@ private:
template <typename T>
static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data,
FileSys::EntryType type) {
+ entries.reserve(entries.size() + new_data.size());
+
for (const auto& new_entry : new_data) {
- FileSys::Entry entry;
- entry.filename[0] = '\0';
- std::strncat(entry.filename, new_entry->GetName().c_str(), FileSys::FILENAME_LENGTH - 1);
- entry.type = type;
- entry.file_size = new_entry->GetSize();
- entries.emplace_back(std::move(entry));
+ entries.emplace_back(new_entry->GetName(), type, new_entry->GetSize());
}
}
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index fb4d89068..f2b0e509a 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -9,10 +9,110 @@
namespace Service::Friend {
+class IFriendService final : public ServiceFramework<IFriendService> {
+public:
+ IFriendService() : ServiceFramework("IFriendService") {
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetCompletionEvent"},
+ {1, nullptr, "Cancel"},
+ {10100, nullptr, "GetFriendListIds"},
+ {10101, nullptr, "GetFriendList"},
+ {10102, nullptr, "UpdateFriendInfo"},
+ {10110, nullptr, "GetFriendProfileImage"},
+ {10200, nullptr, "SendFriendRequestForApplication"},
+ {10211, nullptr, "AddFacedFriendRequestForApplication"},
+ {10400, nullptr, "GetBlockedUserListIds"},
+ {10500, nullptr, "GetProfileList"},
+ {10600, nullptr, "DeclareOpenOnlinePlaySession"},
+ {10601, &IFriendService::DeclareCloseOnlinePlaySession,
+ "DeclareCloseOnlinePlaySession"},
+ {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"},
+ {10700, nullptr, "GetPlayHistoryRegistrationKey"},
+ {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
+ {10702, nullptr, "AddPlayHistory"},
+ {11000, nullptr, "GetProfileImageUrl"},
+ {20100, nullptr, "GetFriendCount"},
+ {20101, nullptr, "GetNewlyFriendCount"},
+ {20102, nullptr, "GetFriendDetailedInfo"},
+ {20103, nullptr, "SyncFriendList"},
+ {20104, nullptr, "RequestSyncFriendList"},
+ {20110, nullptr, "LoadFriendSetting"},
+ {20200, nullptr, "GetReceivedFriendRequestCount"},
+ {20201, nullptr, "GetFriendRequestList"},
+ {20300, nullptr, "GetFriendCandidateList"},
+ {20301, nullptr, "GetNintendoNetworkIdInfo"},
+ {20302, nullptr, "GetSnsAccountLinkage"},
+ {20303, nullptr, "GetSnsAccountProfile"},
+ {20304, nullptr, "GetSnsAccountFriendList"},
+ {20400, nullptr, "GetBlockedUserList"},
+ {20401, nullptr, "SyncBlockedUserList"},
+ {20500, nullptr, "GetProfileExtraList"},
+ {20501, nullptr, "GetRelationship"},
+ {20600, nullptr, "GetUserPresenceView"},
+ {20700, nullptr, "GetPlayHistoryList"},
+ {20701, nullptr, "GetPlayHistoryStatistics"},
+ {20800, nullptr, "LoadUserSetting"},
+ {20801, nullptr, "SyncUserSetting"},
+ {20900, nullptr, "RequestListSummaryOverlayNotification"},
+ {21000, nullptr, "GetExternalApplicationCatalog"},
+ {30100, nullptr, "DropFriendNewlyFlags"},
+ {30101, nullptr, "DeleteFriend"},
+ {30110, nullptr, "DropFriendNewlyFlag"},
+ {30120, nullptr, "ChangeFriendFavoriteFlag"},
+ {30121, nullptr, "ChangeFriendOnlineNotificationFlag"},
+ {30200, nullptr, "SendFriendRequest"},
+ {30201, nullptr, "SendFriendRequestWithApplicationInfo"},
+ {30202, nullptr, "CancelFriendRequest"},
+ {30203, nullptr, "AcceptFriendRequest"},
+ {30204, nullptr, "RejectFriendRequest"},
+ {30205, nullptr, "ReadFriendRequest"},
+ {30210, nullptr, "GetFacedFriendRequestRegistrationKey"},
+ {30211, nullptr, "AddFacedFriendRequest"},
+ {30212, nullptr, "CancelFacedFriendRequest"},
+ {30213, nullptr, "GetFacedFriendRequestProfileImage"},
+ {30214, nullptr, "GetFacedFriendRequestProfileImageFromPath"},
+ {30215, nullptr, "SendFriendRequestWithExternalApplicationCatalogId"},
+ {30216, nullptr, "ResendFacedFriendRequest"},
+ {30217, nullptr, "SendFriendRequestWithNintendoNetworkIdInfo"},
+ {30300, nullptr, "GetSnsAccountLinkPageUrl"},
+ {30301, nullptr, "UnlinkSnsAccount"},
+ {30400, nullptr, "BlockUser"},
+ {30401, nullptr, "BlockUserWithApplicationInfo"},
+ {30402, nullptr, "UnblockUser"},
+ {30500, nullptr, "GetProfileExtraFromFriendCode"},
+ {30700, nullptr, "DeletePlayHistory"},
+ {30810, nullptr, "ChangePresencePermission"},
+ {30811, nullptr, "ChangeFriendRequestReception"},
+ {30812, nullptr, "ChangePlayLogPermission"},
+ {30820, nullptr, "IssueFriendCode"},
+ {30830, nullptr, "ClearPlayLog"},
+ {49900, nullptr, "DeleteNetworkServiceAccountCache"},
+ };
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void DeclareCloseOnlinePlaySession(Kernel::HLERequestContext& ctx) {
+ // Stub used by Splatoon 2
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+
+ void UpdateUserPresence(Kernel::HLERequestContext& ctx) {
+ // Stub used by Retro City Rampage
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+};
+
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 2};
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
- LOG_WARNING(Service_Friend, "(STUBBED) called");
+ rb.PushIpcInterface<IFriendService>();
+ LOG_DEBUG(Service_ACC, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ed53f96c5..970942d3f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -291,6 +291,7 @@ private:
class Hid final : public ServiceFramework<Hid> {
public:
Hid() : ServiceFramework("hid") {
+ // clang-format off
static const FunctionInfo functions[] = {
{0, &Hid::CreateAppletResource, "CreateAppletResource"},
{1, &Hid::ActivateDebugPad, "ActivateDebugPad"},
@@ -333,14 +334,13 @@ public:
{102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
{103, &Hid::ActivateNpad, "ActivateNpad"},
{104, nullptr, "DeactivateNpad"},
- {106, &Hid::AcquireNpadStyleSetUpdateEventHandle,
- "AcquireNpadStyleSetUpdateEventHandle"},
- {107, nullptr, "DisconnectNpad"},
+ {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
+ {107, &Hid::DisconnectNpad, "DisconnectNpad"},
{108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
+ {109, nullptr, "ActivateNpadWithRevision"},
{120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
{121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
- {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
- "SetNpadJoyAssignmentModeSingleByDefault"},
+ {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
{123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
{124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
{125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
@@ -397,6 +397,8 @@ public:
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};
+ // clang-format on
+
RegisterHandlers(functions);
event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle");
@@ -456,7 +458,7 @@ private:
}
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 2};
+ IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
// TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
rb.Push(true);
@@ -495,6 +497,12 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+ void DisconnectNpad(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp
index 08f45b78a..7b91bb258 100644
--- a/src/core/hle/service/mm/mm_u.cpp
+++ b/src/core/hle/service/mm/mm_u.cpp
@@ -9,42 +9,63 @@
namespace Service::MM {
-void InstallInterfaces(SM::ServiceManager& service_manager) {
- std::make_shared<MM_U>()->InstallAsService(service_manager);
-}
+class MM_U final : public ServiceFramework<MM_U> {
+public:
+ explicit MM_U() : ServiceFramework{"mm:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &MM_U::Initialize, "InitializeOld"},
+ {1, &MM_U::Finalize, "FinalizeOld"},
+ {2, &MM_U::SetAndWait, "SetAndWaitOld"},
+ {3, &MM_U::Get, "GetOld"},
+ {4, &MM_U::Initialize, "Initialize"},
+ {5, &MM_U::Finalize, "Finalize"},
+ {6, &MM_U::SetAndWait, "SetAndWait"},
+ {7, &MM_U::Get, "Get"},
+ };
+ // clang-format on
-void MM_U::Initialize(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_MM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
+ RegisterHandlers(functions);
+ }
-void MM_U::SetAndWait(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- min = rp.Pop<u32>();
- max = rp.Pop<u32>();
- current = min;
+private:
+ void Initialize(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_MM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
- LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
+ void Finalize(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_MM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
-void MM_U::Get(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_MM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- rb.Push(current);
-}
+ void SetAndWait(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ min = rp.Pop<u32>();
+ max = rp.Pop<u32>();
+ current = min;
-MM_U::MM_U() : ServiceFramework("mm:u") {
- static const FunctionInfo functions[] = {
- {0, nullptr, "InitializeOld"}, {1, nullptr, "FinalizeOld"},
- {2, nullptr, "SetAndWaitOld"}, {3, nullptr, "GetOld"},
- {4, &MM_U::Initialize, "Initialize"}, {5, nullptr, "Finalize"},
- {6, &MM_U::SetAndWait, "SetAndWait"}, {7, &MM_U::Get, "Get"},
- };
- RegisterHandlers(functions);
+ LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+
+ void Get(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_MM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(current);
+ }
+
+ u32 min{0};
+ u32 max{0};
+ u32 current{0};
+};
+
+void InstallInterfaces(SM::ServiceManager& service_manager) {
+ std::make_shared<MM_U>()->InstallAsService(service_manager);
}
} // namespace Service::MM
diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h
index 79eeedf9c..5439fa653 100644
--- a/src/core/hle/service/mm/mm_u.h
+++ b/src/core/hle/service/mm/mm_u.h
@@ -8,21 +8,6 @@
namespace Service::MM {
-class MM_U final : public ServiceFramework<MM_U> {
-public:
- MM_U();
- ~MM_U() = default;
-
-private:
- void Initialize(Kernel::HLERequestContext& ctx);
- void SetAndWait(Kernel::HLERequestContext& ctx);
- void Get(Kernel::HLERequestContext& ctx);
-
- u32 min{0};
- u32 max{0};
- u32 current{0};
-};
-
/// Registers all MM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 2b74e6a33..8bc49935a 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -7,8 +7,8 @@
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
+#include "video_core/gpu.h"
#include "video_core/renderer_base.h"
-#include "video_core/video_core.h"
namespace Service::Nvidia::Devices {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 4b601781f..be2b79256 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -2,14 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
+#include "video_core/memory_manager.h"
+#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
-#include "video_core/video_core.h"
namespace Service::Nvidia::Devices {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 671b092e1..5685eb2be 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -2,6 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstdlib>
+#include <cstring>
+
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 090261a60..6b496e9fe 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -5,8 +5,6 @@
#pragma once
#include <array>
-#include <cstdlib>
-#include <cstring>
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 010072a5b..ae421247d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 5a1123ad2..4cdf7f613 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -2,12 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
-#include <map>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
+#include "core/memory.h"
+#include "video_core/gpu.h"
+#include "video_core/memory_manager.h"
namespace Service::Nvidia::Devices {
@@ -145,7 +147,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
}
params.fence_out.id = 0;
params.fence_out.value = 0;
- std::memcpy(output.data(), &params, output.size());
+ std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
return 0;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index aa8df2e6e..650ed8fbc 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -6,6 +6,7 @@
#include <memory>
#include <vector>
+#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index b51c73ee8..364619e67 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 0192aecdd..6ad74421b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -4,11 +4,9 @@
#pragma once
-#include <array>
-#include <cstdlib>
-#include <cstring>
#include <vector>
#include "common/common_types.h"
+#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service::Nvidia::Devices {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
new file mode 100644
index 000000000..51f01077b
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -0,0 +1,34 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
+
+namespace Service::Nvidia::Devices {
+
+u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+ LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
+ command.raw, input.size(), output.size());
+
+ switch (static_cast<IoctlCommand>(command.raw)) {
+ case IoctlCommand::IocSetNVMAPfdCommand:
+ return SetNVMAPfd(input, output);
+ }
+
+ UNIMPLEMENTED_MSG("Unimplemented ioctl");
+ return 0;
+}
+
+u32 nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlSetNvmapFD params{};
+ std::memcpy(&params, input.data(), input.size());
+ LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
+ nvmap_fd = params.nvmap_fd;
+ return 0;
+}
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
new file mode 100644
index 000000000..2b0eb43ee
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -0,0 +1,36 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "core/hle/service/nvdrv/devices/nvdevice.h"
+
+namespace Service::Nvidia::Devices {
+
+class nvhost_nvjpg final : public nvdevice {
+public:
+ nvhost_nvjpg() = default;
+ ~nvhost_nvjpg() override = default;
+
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+
+private:
+ enum class IoctlCommand : u32_le {
+ IocSetNVMAPfdCommand = 0x40044801,
+ };
+
+ struct IoctlSetNvmapFD {
+ u32_le nvmap_fd;
+ };
+ static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
+
+ u32_le nvmap_fd{};
+
+ u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
+};
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
new file mode 100644
index 000000000..fcb488d50
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -0,0 +1,34 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
+
+namespace Service::Nvidia::Devices {
+
+u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+ LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
+ command.raw, input.size(), output.size());
+
+ switch (static_cast<IoctlCommand>(command.raw)) {
+ case IoctlCommand::IocSetNVMAPfdCommand:
+ return SetNVMAPfd(input, output);
+ }
+
+ UNIMPLEMENTED_MSG("Unimplemented ioctl");
+ return 0;
+}
+
+u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlSetNvmapFD params{};
+ std::memcpy(&params, input.data(), input.size());
+ LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
+ nvmap_fd = params.nvmap_fd;
+ return 0;
+}
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
new file mode 100644
index 000000000..c7d681e52
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -0,0 +1,36 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "core/hle/service/nvdrv/devices/nvdevice.h"
+
+namespace Service::Nvidia::Devices {
+
+class nvhost_vic final : public nvdevice {
+public:
+ nvhost_vic() = default;
+ ~nvhost_vic() override = default;
+
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+
+private:
+ enum class IoctlCommand : u32_le {
+ IocSetNVMAPfdCommand = 0x40044801,
+ };
+
+ struct IoctlSetNvmapFD {
+ u32_le nvmap_fd;
+ };
+ static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
+
+ u32_le nvmap_fd{};
+
+ u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
+};
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 724eeb139..e9305bfb3 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
-#include <cinttypes>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 959b5ba29..1c3529bb6 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -5,7 +5,6 @@
#pragma once
#include <memory>
-#include <string>
#include "core/hle/kernel/event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 1555ea806..2de39822f 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -12,23 +12,24 @@
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
+#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
+#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvmemp.h"
+#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service::Nvidia {
-std::weak_ptr<Module> nvdrv;
-
-void InstallInterfaces(SM::ServiceManager& service_manager) {
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger) {
auto module_ = std::make_shared<Module>();
std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:s")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:t")->InstallAsService(service_manager);
std::make_shared<NVMEMP>()->InstallAsService(service_manager);
- nvdrv = module_;
+ nvflinger.SetNVDrvInstance(module_);
}
Module::Module() {
@@ -40,6 +41,8 @@ Module::Module() {
devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev);
devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>();
devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>();
+ devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>();
+ devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>();
}
u32 Module::Open(const std::string& device_name) {
@@ -54,7 +57,7 @@ u32 Module::Open(const std::string& device_name) {
return fd;
}
-u32 Module::Ioctl(u32 fd, u32_le command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = open_files.find(fd);
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 184f3c9fc..99eb1128a 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -10,6 +10,10 @@
#include "common/common_types.h"
#include "core/hle/service/service.h"
+namespace Service::NVFlinger {
+class NVFlinger;
+}
+
namespace Service::Nvidia {
namespace Devices {
@@ -56,8 +60,6 @@ private:
};
/// Registers all NVDRV services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager);
-
-extern std::weak_ptr<Module> nvdrv;
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger);
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp
index 9ca6e5512..0e8e21bad 100644
--- a/src/core/hle/service/nvdrv/nvmemp.cpp
+++ b/src/core/hle/service/nvdrv/nvmemp.cpp
@@ -4,8 +4,6 @@
#include "common/assert.h"
#include "common/logging/log.h"
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvmemp.h"
namespace Service::Nvidia {
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index adf180509..ef5713a71 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -16,7 +16,7 @@ BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
Kernel::Event::Create(Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
}
-void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
+void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
Buffer buffer{};
buffer.slot = slot;
buffer.igbp_buffer = igbp_buffer;
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 004170538..db2e17c0c 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -6,6 +6,7 @@
#include <vector>
#include <boost/optional.hpp>
+#include "common/common_funcs.h"
#include "common/math_util.h"
#include "common/swap.h"
#include "core/hle/kernel/event.h"
@@ -72,7 +73,7 @@ public:
MathUtil::Rectangle<int> crop_rect;
};
- void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
+ void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
boost::optional<u32> DequeueBuffer(u32 width, u32 height);
const IGBPBuffer& RequestBuffer(u32 slot) const;
void QueueBuffer(u32 slot, BufferTransformFlags transform,
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 0bf51062c..a26a5f812 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -3,8 +3,11 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <boost/optional.hpp>
#include "common/alignment.h"
+#include "common/assert.h"
+#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "core/core.h"
@@ -31,7 +34,7 @@ NVFlinger::NVFlinger() {
// Schedule the screen composition events
composition_event =
- CoreTiming::RegisterEvent("ScreenCompositioin", [this](u64 userdata, int cycles_late) {
+ CoreTiming::RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
Compose();
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, composition_event);
});
@@ -43,7 +46,11 @@ NVFlinger::~NVFlinger() {
CoreTiming::UnscheduleEvent(composition_event, 0);
}
-u64 NVFlinger::OpenDisplay(const std::string& name) {
+void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
+ nvdrv = std::move(instance);
+}
+
+u64 NVFlinger::OpenDisplay(std::string_view name) {
LOG_WARNING(Service, "Opening display {}", name);
// TODO(Subv): Currently we only support the Default display.
@@ -138,9 +145,6 @@ void NVFlinger::Compose() {
auto& igbp_buffer = buffer->igbp_buffer;
// Now send the buffer to the GPU for drawing.
- auto nvdrv = Nvidia::nvdrv.lock();
- ASSERT(nvdrv);
-
// TODO(Subv): Support more than just disp0. The display device selection is probably based
// on which display we're drawing (Default, Internal, External, etc)
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 2c908297b..f7112949f 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -5,13 +5,21 @@
#pragma once
#include <memory>
-#include <boost/optional.hpp>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include "common/common_types.h"
#include "core/hle/kernel/event.h"
namespace CoreTiming {
struct EventType;
}
+namespace Service::Nvidia {
+class Module;
+}
+
namespace Service::NVFlinger {
class BufferQueue;
@@ -40,8 +48,11 @@ public:
NVFlinger();
~NVFlinger();
+ /// Sets the NVDrv module instance to use to send buffers to the GPU.
+ void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
+
/// Opens the specified display and returns the id.
- u64 OpenDisplay(const std::string& name);
+ u64 OpenDisplay(std::string_view name);
/// Creates a layer on the specified display and returns the layer id.
u64 CreateLayer(u64 display_id);
@@ -66,6 +77,8 @@ private:
/// Returns the layer identified by the specified id in the desired display.
Layer& GetLayer(u64 display_id, u64 layer_id);
+ std::shared_ptr<Nvidia::Module> nvdrv;
+
std::vector<Display> displays;
std::vector<std::shared_ptr<BufferQueue>> buffer_queues;
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 31ea79773..11951adaf 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -63,6 +63,7 @@
#include "core/hle/service/spl/module.h"
#include "core/hle/service/ssl/ssl.h"
#include "core/hle/service/time/time.h"
+#include "core/hle/service/usb/usb.h"
#include "core/hle/service/vi/vi.h"
#include "core/hle/service/wlan/wlan.h"
@@ -197,7 +198,7 @@ void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
}
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm) {
+void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesystem& rfs) {
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
// here and pass it into the respective InstallInterfaces functions.
auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
@@ -220,7 +221,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
EUPLD::InstallInterfaces(*sm);
Fatal::InstallInterfaces(*sm);
FGM::InstallInterfaces(*sm);
- FileSystem::InstallInterfaces(*sm);
+ FileSystem::InstallInterfaces(*sm, rfs);
Friend::InstallInterfaces(*sm);
GRC::InstallInterfaces(*sm);
HID::InstallInterfaces(*sm);
@@ -237,7 +238,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
NIFM::InstallInterfaces(*sm);
NIM::InstallInterfaces(*sm);
NS::InstallInterfaces(*sm);
- Nvidia::InstallInterfaces(*sm);
+ Nvidia::InstallInterfaces(*sm, *nv_flinger);
PCIe::InstallInterfaces(*sm);
PCTL::InstallInterfaces(*sm);
PCV::InstallInterfaces(*sm);
@@ -249,6 +250,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
SPL::InstallInterfaces(*sm);
SSL::InstallInterfaces(*sm);
Time::InstallInterfaces(*sm);
+ USB::InstallInterfaces(*sm);
VI::InstallInterfaces(*sm, nv_flinger);
WLAN::InstallInterfaces(*sm);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 046c5e18d..cd9c74f3d 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -22,6 +22,10 @@ class ServerSession;
class HLERequestContext;
} // namespace Kernel
+namespace FileSys {
+class VfsFilesystem;
+}
+
namespace Service {
namespace SM {
@@ -177,7 +181,8 @@ private:
};
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm);
+void Init(std::shared_ptr<SM::ServiceManager>& sm,
+ const std::shared_ptr<FileSys::VfsFilesystem>& vfs);
/// Shutdown ServiceManager
void Shutdown();
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 37b58bb77..2172c681b 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -80,8 +80,8 @@ public:
{5, nullptr, "GetTimeZoneRuleVersion"},
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
- {200, nullptr, "ToPosixTime"},
- {201, nullptr, "ToPosixTimeWithMyRule"},
+ {201, nullptr, "ToPosixTime"},
+ {202, nullptr, "ToPosixTimeWithMyRule"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
new file mode 100644
index 000000000..e7fb5a419
--- /dev/null
+++ b/src/core/hle/service/usb/usb.cpp
@@ -0,0 +1,238 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/usb/usb.h"
+
+namespace Service::USB {
+
+class IDsInterface final : public ServiceFramework<IDsInterface> {
+public:
+ explicit IDsInterface() : ServiceFramework{"IDsInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetDsEndpoint"},
+ {1, nullptr, "GetSetupEvent"},
+ {2, nullptr, "Unknown"},
+ {3, nullptr, "EnableInterface"},
+ {4, nullptr, "DisableInterface"},
+ {5, nullptr, "CtrlInPostBufferAsync"},
+ {6, nullptr, "CtrlOutPostBufferAsync"},
+ {7, nullptr, "GetCtrlInCompletionEvent"},
+ {8, nullptr, "GetCtrlInReportData"},
+ {9, nullptr, "GetCtrlOutCompletionEvent"},
+ {10, nullptr, "GetCtrlOutReportData"},
+ {11, nullptr, "StallCtrl"},
+ {12, nullptr, "AppendConfigurationData"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_DS final : public ServiceFramework<USB_DS> {
+public:
+ explicit USB_DS() : ServiceFramework{"usb:ds"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "BindDevice"},
+ {1, nullptr, "BindClientProcess"},
+ {2, nullptr, "GetDsInterface"},
+ {3, nullptr, "GetStateChangeEvent"},
+ {4, nullptr, "GetState"},
+ {5, nullptr, "ClearDeviceData"},
+ {6, nullptr, "AddUsbStringDescriptor"},
+ {7, nullptr, "DeleteUsbStringDescriptor"},
+ {8, nullptr, "SetUsbDeviceDescriptor"},
+ {9, nullptr, "SetBinaryObjectStore"},
+ {10, nullptr, "Enable"},
+ {11, nullptr, "Disable"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IClientEpSession final : public ServiceFramework<IClientEpSession> {
+public:
+ explicit IClientEpSession() : ServiceFramework{"IClientEpSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "PostBufferAsync"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "Unknown8"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IClientIfSession final : public ServiceFramework<IClientIfSession> {
+public:
+ explicit IClientIfSession() : ServiceFramework{"IClientIfSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "CtrlXferAsync"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "GetCtrlXferReport"},
+ {8, nullptr, "Unknown7"},
+ {9, nullptr, "GetClientEpSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_HS final : public ServiceFramework<USB_HS> {
+public:
+ explicit USB_HS() : ServiceFramework{"usb:hs"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "BindClientProcess"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "GetInterfaceStateChangeEvent"},
+ {7, nullptr, "GetClientIfSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IPdSession final : public ServiceFramework<IPdSession> {
+public:
+ explicit IPdSession() : ServiceFramework{"IPdSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "BindNoticeEvent"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "GetStatus"},
+ {3, nullptr, "GetNotice"},
+ {4, nullptr, "Unknown2"},
+ {5, nullptr, "Unknown3"},
+ {6, nullptr, "ReplyPowerRequest"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_PD final : public ServiceFramework<USB_PD> {
+public:
+ explicit USB_PD() : ServiceFramework{"usb:pd"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &USB_PD::GetPdSession, "GetPdSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetPdSession(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IPdSession>();
+
+ LOG_DEBUG(Service_USB, "called");
+ }
+};
+
+class IPdCradleSession final : public ServiceFramework<IPdCradleSession> {
+public:
+ explicit IPdCradleSession() : ServiceFramework{"IPdCradleSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "VdmUserWrite"},
+ {1, nullptr, "VdmUserRead"},
+ {2, nullptr, "Vdm20Init"},
+ {3, nullptr, "GetFwType"},
+ {4, nullptr, "GetFwRevision"},
+ {5, nullptr, "GetManufacturerId"},
+ {6, nullptr, "GetDeviceId"},
+ {7, nullptr, "Unknown1"},
+ {8, nullptr, "Unknown2"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_PD_C final : public ServiceFramework<USB_PD_C> {
+public:
+ explicit USB_PD_C() : ServiceFramework{"usb:pd:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetPdCradleSession(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IPdCradleSession>();
+
+ LOG_DEBUG(Service_USB, "called");
+ }
+};
+
+class USB_PM final : public ServiceFramework<USB_PM> {
+public:
+ explicit USB_PM() : ServiceFramework{"usb:pm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<USB_DS>()->InstallAsService(sm);
+ std::make_shared<USB_HS>()->InstallAsService(sm);
+ std::make_shared<USB_PD>()->InstallAsService(sm);
+ std::make_shared<USB_PD_C>()->InstallAsService(sm);
+ std::make_shared<USB_PM>()->InstallAsService(sm);
+}
+
+} // namespace Service::USB
diff --git a/src/core/hle/service/usb/usb.h b/src/core/hle/service/usb/usb.h
new file mode 100644
index 000000000..970a11fe8
--- /dev/null
+++ b/src/core/hle/service/usb/usb.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::USB {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::USB
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index b0277a875..de05f21d8 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -7,6 +7,7 @@
#include "common/file_util.h"
#include "common/logging/log.h"
#include "core/file_sys/content_archive.h"
+#include "core/file_sys/control_metadata.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
@@ -17,8 +18,54 @@
namespace Loader {
-AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
- : AppLoader(std::move(file)) {}
+AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_)
+ : AppLoader(std::move(file_)) {
+ const auto dir = file->GetContainingDirectory();
+
+ // Icon
+ FileSys::VirtualFile icon_file = nullptr;
+ for (const auto& language : FileSys::LANGUAGE_NAMES) {
+ icon_file = dir->GetFile("icon_" + std::string(language) + ".dat");
+ if (icon_file != nullptr) {
+ icon_data = icon_file->ReadAllBytes();
+ break;
+ }
+ }
+
+ if (icon_data.empty()) {
+ // Any png, jpeg, or bmp file
+ const auto& files = dir->GetFiles();
+ const auto icon_iter =
+ std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
+ return file->GetExtension() == "png" || file->GetExtension() == "jpg" ||
+ file->GetExtension() == "bmp" || file->GetExtension() == "jpeg";
+ });
+ if (icon_iter != files.end())
+ icon_data = (*icon_iter)->ReadAllBytes();
+ }
+
+ // Metadata
+ FileSys::VirtualFile nacp_file = dir->GetFile("control.nacp");
+ if (nacp_file == nullptr) {
+ const auto& files = dir->GetFiles();
+ const auto nacp_iter =
+ std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
+ return file->GetExtension() == "nacp";
+ });
+ if (nacp_iter != files.end())
+ nacp_file = *nacp_iter;
+ }
+
+ if (nacp_file != nullptr) {
+ FileSys::NACP nacp(nacp_file);
+ title_id = nacp.GetTitleId();
+ name = nacp.GetApplicationName();
+ }
+}
+
+AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
+ FileSys::VirtualDir directory)
+ : AppLoader(directory->GetFile("main")), dir(std::move(directory)) {}
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) {
if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) {
@@ -34,10 +81,15 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
return ResultStatus::ErrorAlreadyLoaded;
}
- const FileSys::VirtualDir dir = file->GetContainingDirectory();
+ if (dir == nullptr) {
+ if (file == nullptr)
+ return ResultStatus::ErrorNullFile;
+ dir = file->GetContainingDirectory();
+ }
+
const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
if (npdm == nullptr)
- return ResultStatus::ErrorInvalidFormat;
+ return ResultStatus::ErrorMissingNPDM;
ResultStatus result = metadata.Load(npdm);
if (result != ResultStatus::Success) {
@@ -47,7 +99,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) {
- return ResultStatus::ErrorUnsupportedArch;
+ return ResultStatus::Error32BitISA;
}
// Load NSO modules
@@ -91,9 +143,30 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) {
if (romfs == nullptr)
- return ResultStatus::ErrorNotUsed;
+ return ResultStatus::ErrorNoRomFS;
dir = romfs;
return ResultStatus::Success;
}
+ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector<u8>& buffer) {
+ if (icon_data.empty())
+ return ResultStatus::ErrorNoIcon;
+ buffer = icon_data;
+ return ResultStatus::Success;
+}
+
+ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program_id) {
+ if (name.empty())
+ return ResultStatus::ErrorNoControl;
+ out_program_id = title_id;
+ return ResultStatus::Success;
+}
+
+ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& title) {
+ if (name.empty())
+ return ResultStatus::ErrorNoControl;
+ title = name;
+ return ResultStatus::Success;
+}
+
} // namespace Loader
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 7319ba6ea..b20804f75 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -22,6 +22,9 @@ class AppLoader_DeconstructedRomDirectory final : public AppLoader {
public:
explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file);
+ // Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
+ explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory);
+
/**
* Returns the type of the file
* @param file std::shared_ptr<VfsFile> open file
@@ -36,10 +39,18 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
+ ResultStatus ReadIcon(std::vector<u8>& buffer) override;
+ ResultStatus ReadProgramId(u64& out_program_id) override;
+ ResultStatus ReadTitle(std::string& title) override;
private:
FileSys::ProgramMetadata metadata;
FileSys::VirtualFile romfs;
+ FileSys::VirtualDir dir;
+
+ std::vector<u8> icon_data;
+ std::string name;
+ u64 title_id{};
};
} // namespace Loader
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index a7133f5a6..401cad3ab 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -390,7 +390,7 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
std::vector<u8> buffer = file->ReadAllBytes();
if (buffer.size() != file->GetSize())
- return ResultStatus::Error;
+ return ResultStatus::ErrorIncorrectELFFileSize;
ElfReader elf_reader(&buffer[0]);
SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 57e6c0365..1f2f31535 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -43,10 +43,6 @@ FileType IdentifyFile(FileSys::VirtualFile file) {
return FileType::Unknown;
}
-FileType IdentifyFile(const std::string& file_name) {
- return IdentifyFile(std::make_shared<FileSys::RealVfsFile>(file_name));
-}
-
FileType GuessFromFilename(const std::string& name) {
if (name == "main")
return FileType::DeconstructedRomDirectory;
@@ -68,7 +64,7 @@ FileType GuessFromFilename(const std::string& name) {
return FileType::Unknown;
}
-const char* GetFileTypeString(FileType type) {
+std::string GetFileTypeString(FileType type) {
switch (type) {
case FileType::ELF:
return "ELF";
@@ -90,6 +86,55 @@ const char* GetFileTypeString(FileType type) {
return "unknown";
}
+constexpr std::array<const char*, 36> RESULT_MESSAGES{
+ "The operation completed successfully.",
+ "The loader requested to load is already loaded.",
+ "The operation is not implemented.",
+ "The loader is not initialized properly.",
+ "The NPDM file has a bad header.",
+ "The NPDM has a bad ACID header.",
+ "The NPDM has a bad ACI header,",
+ "The NPDM file has a bad file access control.",
+ "The NPDM has a bad file access header.",
+ "The PFS/HFS partition has a bad header.",
+ "The PFS/HFS partition has incorrect size as determined by the header.",
+ "The NCA file has a bad header.",
+ "The general keyfile could not be found.",
+ "The NCA Header key could not be found.",
+ "The NCA Header key is incorrect or the header is invalid.",
+ "Support for NCA2-type NCAs is not implemented.",
+ "Support for NCA0-type NCAs is not implemented.",
+ "The titlekey for this Rights ID could not be found.",
+ "The titlekek for this crypto revision could not be found.",
+ "The Rights ID in the header is invalid.",
+ "The key area key for this application type and crypto revision could not be found.",
+ "The key area key is incorrect or the section header is invalid.",
+ "The titlekey and/or titlekek is incorrect or the section header is invalid.",
+ "The XCI file is missing a Program-type NCA.",
+ "The NCA file is not an application.",
+ "The ExeFS partition could not be found.",
+ "The XCI file has a bad header.",
+ "The XCI file is missing a partition.",
+ "The file could not be found or does not exist.",
+ "The game is missing a program metadata file (main.npdm).",
+ "The game uses the currently-unimplemented 32-bit architecture.",
+ "The RomFS could not be found.",
+ "The ELF file has incorrect size as determined by the header.",
+ "There was a general error loading the NRO into emulated memory.",
+ "There is no icon available.",
+ "There is no control data available.",
+};
+
+std::string GetMessageForResultStatus(ResultStatus status) {
+ return GetMessageForResultStatus(static_cast<u16>(status));
+}
+
+std::string GetMessageForResultStatus(u16 status) {
+ if (status >= 36)
+ return "";
+ return RESULT_MESSAGES[status];
+}
+
/**
* Get a loader for a file with a specific type
* @param file The file to load
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index e69ab85ef..285363549 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -43,14 +43,6 @@ enum class FileType {
FileType IdentifyFile(FileSys::VirtualFile file);
/**
- * Identifies the type of a bootable file based on the magic value in its header.
- * @param file_name path to file
- * @return FileType of file. Note: this will return FileType::Unknown if it is unable to determine
- * a filetype, and will never return FileType::Error.
- */
-FileType IdentifyFile(const std::string& file_name);
-
-/**
* Guess the type of a bootable file from its name
* @param name String name of bootable file
* @return FileType of file. Note: this will return FileType::Unknown if it is unable to determine
@@ -61,23 +53,51 @@ FileType GuessFromFilename(const std::string& name);
/**
* Convert a FileType into a string which can be displayed to the user.
*/
-const char* GetFileTypeString(FileType type);
+std::string GetFileTypeString(FileType type);
/// Return type for functions in Loader namespace
-enum class ResultStatus {
+enum class ResultStatus : u16 {
Success,
- Error,
- ErrorInvalidFormat,
- ErrorNotImplemented,
- ErrorNotLoaded,
- ErrorNotUsed,
ErrorAlreadyLoaded,
- ErrorMemoryAllocationFailed,
- ErrorMissingKeys,
- ErrorDecrypting,
- ErrorUnsupportedArch,
+ ErrorNotImplemented,
+ ErrorNotInitialized,
+ ErrorBadNPDMHeader,
+ ErrorBadACIDHeader,
+ ErrorBadACIHeader,
+ ErrorBadFileAccessControl,
+ ErrorBadFileAccessHeader,
+ ErrorBadPFSHeader,
+ ErrorIncorrectPFSFileSize,
+ ErrorBadNCAHeader,
+ ErrorMissingProductionKeyFile,
+ ErrorMissingHeaderKey,
+ ErrorIncorrectHeaderKey,
+ ErrorNCA2,
+ ErrorNCA0,
+ ErrorMissingTitlekey,
+ ErrorMissingTitlekek,
+ ErrorInvalidRightsID,
+ ErrorMissingKeyAreaKey,
+ ErrorIncorrectKeyAreaKey,
+ ErrorIncorrectTitlekeyOrTitlekek,
+ ErrorXCIMissingProgramNCA,
+ ErrorNCANotProgram,
+ ErrorNoExeFS,
+ ErrorBadXCIHeader,
+ ErrorXCIMissingPartition,
+ ErrorNullFile,
+ ErrorMissingNPDM,
+ Error32BitISA,
+ ErrorNoRomFS,
+ ErrorIncorrectELFFileSize,
+ ErrorLoadingNRO,
+ ErrorNoIcon,
+ ErrorNoControl,
};
+std::string GetMessageForResultStatus(ResultStatus status);
+std::string GetMessageForResultStatus(u16 status);
+
/// Interface for loading an application
class AppLoader : NonCopyable {
public:
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index a1f8235d1..8498cc94b 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -22,7 +22,8 @@
namespace Loader {
-AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
+AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file_)
+ : AppLoader(std::move(file_)), nca(std::make_unique<FileSys::NCA>(file)) {}
FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
FileSys::NCA nca(file);
@@ -39,53 +40,24 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
return ResultStatus::ErrorAlreadyLoaded;
}
- nca = std::make_unique<FileSys::NCA>(file);
- ResultStatus result = nca->GetStatus();
+ const auto result = nca->GetStatus();
if (result != ResultStatus::Success) {
return result;
}
if (nca->GetType() != FileSys::NCAContentType::Program)
- return ResultStatus::ErrorInvalidFormat;
+ return ResultStatus::ErrorNCANotProgram;
- auto exefs = nca->GetExeFS();
+ const auto exefs = nca->GetExeFS();
if (exefs == nullptr)
- return ResultStatus::ErrorInvalidFormat;
+ return ResultStatus::ErrorNoExeFS;
- result = metadata.Load(exefs->GetFile("main.npdm"));
- if (result != ResultStatus::Success) {
- return result;
- }
- metadata.Print();
-
- const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
- if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) {
- return ResultStatus::ErrorUnsupportedArch;
- }
-
- VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
- for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
- "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
- const VAddr load_addr = next_load_addr;
-
- next_load_addr = AppLoader_NSO::LoadModule(exefs->GetFile(module), load_addr);
- if (next_load_addr) {
- LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
- // Register module with GDBStub
- GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
- } else {
- next_load_addr = load_addr;
- }
- }
+ directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs);
- process->program_id = metadata.GetTitleID();
- process->svc_access_mask.set();
- process->address_mappings = default_address_mappings;
- process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
- process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),
- metadata.GetMainThreadStackSize());
+ const auto load_result = directory_loader->Load(process);
+ if (load_result != ResultStatus::Success)
+ return load_result;
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0)
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
@@ -97,16 +69,16 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
if (nca == nullptr)
- return ResultStatus::ErrorNotLoaded;
+ return ResultStatus::ErrorNotInitialized;
if (nca->GetRomFS() == nullptr || nca->GetRomFS()->GetSize() == 0)
- return ResultStatus::ErrorNotUsed;
+ return ResultStatus::ErrorNoRomFS;
dir = nca->GetRomFS();
return ResultStatus::Success;
}
ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
- if (nca == nullptr)
- return ResultStatus::ErrorNotLoaded;
+ if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
+ return ResultStatus::ErrorNotInitialized;
out_program_id = nca->GetTitleId();
return ResultStatus::Success;
}
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index e14d618b3..7f7d8ea0b 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -10,6 +10,7 @@
#include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/object.h"
#include "core/loader/loader.h"
+#include "deconstructed_rom_directory.h"
namespace Loader {
@@ -32,7 +33,6 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
-
ResultStatus ReadProgramId(u64& out_program_id) override;
~AppLoader_NCA();
@@ -40,7 +40,9 @@ public:
private:
FileSys::ProgramMetadata metadata;
+ FileSys::NCAHeader header;
std::unique_ptr<FileSys::NCA> nca;
+ std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader;
};
} // namespace Loader
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index dc053cdad..908d91eab 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -182,7 +182,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
static constexpr VAddr base_addr{Memory::PROCESS_IMAGE_VADDR};
if (!LoadNro(file, base_addr)) {
- return ResultStatus::ErrorInvalidFormat;
+ return ResultStatus::ErrorLoadingNRO;
}
process->svc_access_mask.set();
@@ -197,7 +197,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {
if (icon_data.empty()) {
- return ResultStatus::ErrorNotUsed;
+ return ResultStatus::ErrorNoIcon;
}
buffer = icon_data;
@@ -206,7 +206,7 @@ ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {
ResultStatus AppLoader_NRO::ReadProgramId(u64& out_program_id) {
if (nacp == nullptr) {
- return ResultStatus::ErrorNotUsed;
+ return ResultStatus::ErrorNoControl;
}
out_program_id = nacp->GetTitleId();
@@ -215,7 +215,7 @@ ResultStatus AppLoader_NRO::ReadProgramId(u64& out_program_id) {
ResultStatus AppLoader_NRO::ReadRomFS(FileSys::VirtualFile& dir) {
if (romfs == nullptr) {
- return ResultStatus::ErrorNotUsed;
+ return ResultStatus::ErrorNoRomFS;
}
dir = romfs;
@@ -224,7 +224,7 @@ ResultStatus AppLoader_NRO::ReadRomFS(FileSys::VirtualFile& dir) {
ResultStatus AppLoader_NRO::ReadTitle(std::string& title) {
if (nacp == nullptr) {
- return ResultStatus::ErrorNotUsed;
+ return ResultStatus::ErrorNoControl;
}
title = nacp->GetApplicationName();
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index eb4dee2c2..5d67fb186 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -26,7 +26,25 @@ namespace Loader {
AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
: AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
nca_loader(std::make_unique<AppLoader_NCA>(
- xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {}
+ xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {
+ if (xci->GetStatus() != ResultStatus::Success)
+ return;
+ const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
+ if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
+ return;
+ const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
+ if (romfs == nullptr)
+ return;
+ for (const auto& language : FileSys::LANGUAGE_NAMES) {
+ icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
+ if (icon_file != nullptr)
+ break;
+ }
+ const auto nacp_raw = romfs->GetFile("control.nacp");
+ if (nacp_raw == nullptr)
+ return;
+ nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
+}
AppLoader_XCI::~AppLoader_XCI() = default;
@@ -48,10 +66,13 @@ ResultStatus AppLoader_XCI::Load(Kernel::SharedPtr<Kernel::Process>& process) {
return ResultStatus::ErrorAlreadyLoaded;
}
+ if (xci->GetStatus() != ResultStatus::Success)
+ return xci->GetStatus();
+
if (xci->GetNCAFileByType(FileSys::NCAContentType::Program) == nullptr) {
if (!Core::Crypto::KeyManager::KeyFileExists(false))
- return ResultStatus::ErrorMissingKeys;
- return ResultStatus::ErrorDecrypting;
+ return ResultStatus::ErrorMissingProductionKeyFile;
+ return ResultStatus::ErrorXCIMissingProgramNCA;
}
auto result = nca_loader->Load(process);
@@ -71,4 +92,17 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
return nca_loader->ReadProgramId(out_program_id);
}
+ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) {
+ if (icon_file == nullptr)
+ return ResultStatus::ErrorNoControl;
+ buffer = icon_file->ReadAllBytes();
+ return ResultStatus::Success;
+}
+
+ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
+ if (nacp_file == nullptr)
+ return ResultStatus::ErrorNoControl;
+ title = nacp_file->GetApplicationName();
+ return ResultStatus::Success;
+}
} // namespace Loader
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 0dbcfbdf8..973833050 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -33,12 +33,17 @@ public:
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
+ ResultStatus ReadIcon(std::vector<u8>& buffer) override;
+ ResultStatus ReadTitle(std::string& title) override;
private:
FileSys::ProgramMetadata metadata;
std::unique_ptr<FileSys::XCI> xci;
std::unique_ptr<AppLoader_NCA> nca_loader;
+
+ FileSys::VirtualFile icon_file;
+ std::shared_ptr<FileSys::NACP> nacp_file;
};
} // namespace Loader
diff --git a/src/core/memory.h b/src/core/memory.h
index b5d885b8a..b7fb3b9ed 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -140,10 +140,10 @@ void SetCurrentPageTable(PageTable* page_table);
PageTable* GetCurrentPageTable();
/// Determines if the given VAddr is valid for the specified process.
-bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr);
-bool IsValidVirtualAddress(const VAddr addr);
+bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
+bool IsValidVirtualAddress(VAddr vaddr);
/// Determines if the given VAddr is a kernel address
-bool IsKernelVirtualAddress(const VAddr addr);
+bool IsKernelVirtualAddress(VAddr vaddr);
u8 Read8(VAddr addr);
u16 Read16(VAddr addr);
@@ -155,18 +155,17 @@ void Write16(VAddr addr, u16 data);
void Write32(VAddr addr, u32 data);
void Write64(VAddr addr, u64 data);
-void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
- size_t size);
-void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size);
-void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer,
+void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, size_t size);
+void ReadBlock(VAddr src_addr, void* dest_buffer, size_t size);
+void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
size_t size);
-void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size);
-void ZeroBlock(const VAddr dest_addr, const size_t size);
+void WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size);
+void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, size_t size);
void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size);
-u8* GetPointer(VAddr virtual_address);
+u8* GetPointer(VAddr vaddr);
-std::string ReadCString(VAddr virtual_address, std::size_t max_length);
+std::string ReadCString(VAddr vaddr, std::size_t max_length);
enum class FlushMode {
/// Write back modified surfaces to RAM
@@ -180,7 +179,7 @@ enum class FlushMode {
/**
* Mark each page touching the region as cached.
*/
-void RasterizerMarkRegionCached(Tegra::GPUVAddr start, u64 size, bool cached);
+void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached);
/**
* Flushes and invalidates any externally cached rasterizer resources touching the given virtual
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index 5f53b16d3..8e09b9b63 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -40,22 +40,21 @@ void PerfStats::EndGameFrame() {
game_frames += 1;
}
-PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) {
+PerfStats::Results PerfStats::GetAndResetStats(microseconds current_system_time_us) {
std::lock_guard<std::mutex> lock(object_mutex);
- auto now = Clock::now();
+ const auto now = Clock::now();
// Walltime elapsed since stats were reset
- auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
+ const auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
- auto system_us_per_second =
- static_cast<double>(current_system_time_us - reset_point_system_us) / interval;
+ const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval;
Results results{};
results.system_fps = static_cast<double>(system_frames) / interval;
results.game_fps = static_cast<double>(game_frames) / interval;
results.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
static_cast<double>(system_frames);
- results.emulation_speed = system_us_per_second / 1'000'000.0;
+ results.emulation_speed = system_us_per_second.count() / 1'000'000.0;
// Reset counters
reset_point = now;
@@ -74,10 +73,10 @@ double PerfStats::GetLastFrameTimeScale() {
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
}
-void FrameLimiter::DoFrameLimiting(u64 current_system_time_us) {
+void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) {
// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher
// values increase the time needed to recover and limit framerate again after spikes.
- constexpr microseconds MAX_LAG_TIME_US = 25ms;
+ constexpr microseconds MAX_LAG_TIME_US = 25us;
if (!Settings::values.toggle_framelimit) {
return;
@@ -85,7 +84,7 @@ void FrameLimiter::DoFrameLimiting(u64 current_system_time_us) {
auto now = Clock::now();
- frame_limiting_delta_err += microseconds(current_system_time_us - previous_system_time_us);
+ frame_limiting_delta_err += current_system_time_us - previous_system_time_us;
frame_limiting_delta_err -= duration_cast<microseconds>(now - previous_walltime);
frame_limiting_delta_err =
std::clamp(frame_limiting_delta_err, -MAX_LAG_TIME_US, MAX_LAG_TIME_US);
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h
index 362b205c8..6e4619701 100644
--- a/src/core/perf_stats.h
+++ b/src/core/perf_stats.h
@@ -33,7 +33,7 @@ public:
void EndSystemFrame();
void EndGameFrame();
- Results GetAndResetStats(u64 current_system_time_us);
+ Results GetAndResetStats(std::chrono::microseconds current_system_time_us);
/**
* Gets the ratio between walltime and the emulated time of the previous system frame. This is
@@ -47,7 +47,7 @@ private:
/// Point when the cumulative counters were reset
Clock::time_point reset_point = Clock::now();
/// System time when the cumulative counters were reset
- u64 reset_point_system_us = 0;
+ std::chrono::microseconds reset_point_system_us{0};
/// Cumulative duration (excluding v-sync/frame-limiting) of frames since last reset
Clock::duration accumulated_frametime = Clock::duration::zero();
@@ -68,11 +68,11 @@ class FrameLimiter {
public:
using Clock = std::chrono::high_resolution_clock;
- void DoFrameLimiting(u64 current_system_time_us);
+ void DoFrameLimiting(std::chrono::microseconds current_system_time_us);
private:
/// Emulated system time (in microseconds) at the last limiter invocation
- u64 previous_system_time_us = 0;
+ std::chrono::microseconds previous_system_time_us{0};
/// Walltime at the last limiter invocation
Clock::time_point previous_walltime = Clock::now();
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index a4623223d..0da159559 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -7,22 +7,18 @@
#include "core/hle/service/hid/hid.h"
#include "core/settings.h"
#include "video_core/renderer_base.h"
-#include "video_core/video_core.h"
namespace Settings {
Values values = {};
void Apply() {
-
GDBStub::SetServerPort(values.gdbstub_port);
GDBStub::ToggleServer(values.use_gdbstub);
- VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit;
-
auto& system_instance = Core::System::GetInstance();
if (system_instance.IsPoweredOn()) {
- system_instance.Renderer().UpdateCurrentFramebufferLayout();
+ system_instance.Renderer().RefreshBaseSettings();
}
Service::HID::ReloadInputDevices();
diff --git a/src/tests/common/param_package.cpp b/src/tests/common/param_package.cpp
index 19d372236..4c0f9654f 100644
--- a/src/tests/common/param_package.cpp
+++ b/src/tests/common/param_package.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <catch.hpp>
+#include <catch2/catch.hpp>
#include <math.h>
#include "common/param_package.h"
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index fcaa30990..2242c14cf 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include <catch.hpp>
+#include <catch2/catch.hpp>
#include <array>
#include <bitset>
diff --git a/src/tests/glad.cpp b/src/tests/glad.cpp
index b0b016440..1797c0e3d 100644
--- a/src/tests/glad.cpp
+++ b/src/tests/glad.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <catch.hpp>
+#include <catch2/catch.hpp>
#include <glad/glad.h>
// This is not an actual test, but a work-around for issue #2183.
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index 73978676f..275b430d9 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#define CATCH_CONFIG_MAIN
-#include <catch.hpp>
+#include <catch2/catch.hpp>
// Catch provides the main function since we've given it the
// CATCH_CONFIG_MAIN preprocessor directive.
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 31ea3adad..dc485e811 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -29,10 +29,10 @@ enum class BufferMethods {
};
void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) {
- LOG_WARNING(HW_GPU,
- "Processing method {:08X} on subchannel {} value "
- "{:08X} remaining params {}",
- method, subchannel, value, remaining_params);
+ LOG_TRACE(HW_GPU,
+ "Processing method {:08X} on subchannel {} value "
+ "{:08X} remaining params {}",
+ method, subchannel, value, remaining_params);
if (method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id.
diff --git a/src/video_core/command_processor.h b/src/video_core/command_processor.h
index f7214ffec..a01153e0b 100644
--- a/src/video_core/command_processor.h
+++ b/src/video_core/command_processor.h
@@ -30,8 +30,7 @@ union CommandHeader {
BitField<29, 3, SubmissionMode> mode;
};
-static_assert(std::is_standard_layout<CommandHeader>::value == true,
- "CommandHeader does not use standard layout");
+static_assert(std::is_standard_layout_v<CommandHeader>, "CommandHeader is not standard layout");
static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!");
} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index a235b543e..a46ed4bd7 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -23,12 +23,17 @@ Maxwell3D::Maxwell3D(VideoCore::RasterizerInterface& rasterizer, MemoryManager&
: memory_manager(memory_manager), rasterizer{rasterizer}, macro_interpreter(*this) {}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
- auto macro_code = uploaded_macros.find(method);
+ // Reset the current macro.
+ executing_macro = 0;
+
// The requested macro must have been uploaded already.
- ASSERT_MSG(macro_code != uploaded_macros.end(), "Macro %08X was not uploaded", method);
+ auto macro_code = uploaded_macros.find(method);
+ if (macro_code == uploaded_macros.end()) {
+ LOG_ERROR(HW_GPU, "Macro {:04X} was not uploaded", method);
+ return;
+ }
- // Reset the current macro and execute it.
- executing_macro = 0;
+ // Execute the current macro.
macro_interpreter.Execute(macro_code->second, std::move(parameters));
}
@@ -238,6 +243,8 @@ void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
auto& buffer = shader.const_buffers[bind_data.index];
+ ASSERT(bind_data.index < Regs::MaxConstBuffers);
+
buffer.enabled = bind_data.valid.Value() != 0;
buffer.index = bind_data.index;
buffer.address = regs.const_buffer.BufferAddress();
@@ -285,8 +292,6 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
// TODO(Subv): Different data types for separate components are not supported
ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
- // TODO(Subv): Only UNORM formats are supported for now.
- ASSERT(r_type == Texture::ComponentType::UNORM);
return tic_entry;
}
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 4d0ff96a5..1b30ce018 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -44,7 +44,7 @@ public:
static constexpr size_t MaxShaderProgram = 6;
static constexpr size_t MaxShaderStage = 5;
// Maximum number of const buffers per shader stage.
- static constexpr size_t MaxConstBuffers = 16;
+ static constexpr size_t MaxConstBuffers = 18;
enum class QueryMode : u32 {
Write = 0,
@@ -93,6 +93,7 @@ public:
struct VertexAttribute {
enum class Size : u32 {
+ Invalid = 0x0,
Size_32_32_32_32 = 0x01,
Size_32_32_32 = 0x02,
Size_16_16_16_16 = 0x03,
@@ -257,6 +258,10 @@ public:
bool IsNormalized() const {
return (type == Type::SignedNorm) || (type == Type::UnsignedNorm);
}
+
+ bool IsValid() const {
+ return size != Size::Invalid;
+ }
};
enum class PrimitiveTopology : u32 {
@@ -352,6 +357,27 @@ public:
OneMinusConstantColor = 0x62,
ConstantAlpha = 0x63,
OneMinusConstantAlpha = 0x64,
+
+ // These values are used by Nouveau and some games.
+ ZeroGL = 0x4000,
+ OneGL = 0x4001,
+ SourceColorGL = 0x4300,
+ OneMinusSourceColorGL = 0x4301,
+ SourceAlphaGL = 0x4302,
+ OneMinusSourceAlphaGL = 0x4303,
+ DestAlphaGL = 0x4304,
+ OneMinusDestAlphaGL = 0x4305,
+ DestColorGL = 0x4306,
+ OneMinusDestColorGL = 0x4307,
+ SourceAlphaSaturateGL = 0x4308,
+ ConstantColorGL = 0xc001,
+ OneMinusConstantColorGL = 0xc002,
+ ConstantAlphaGL = 0xc003,
+ OneMinusConstantAlphaGL = 0xc004,
+ Source1ColorGL = 0xc900,
+ OneMinusSource1ColorGL = 0xc901,
+ Source1AlphaGL = 0xc902,
+ OneMinusSource1AlphaGL = 0xc903,
};
u32 separate_alpha;
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index c7e3fb4b1..2526ebf28 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -74,6 +74,7 @@ union Attribute {
enum class Index : u64 {
Position = 7,
Attribute_0 = 8,
+ Attribute_31 = 39,
// This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
// shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
// shader.
@@ -199,6 +200,14 @@ enum class IMinMaxExchange : u64 {
XHi = 3,
};
+enum class XmadMode : u64 {
+ None = 0,
+ CLo = 1,
+ CHi = 2,
+ CSfu = 3,
+ CBcc = 4,
+};
+
enum class FlowCondition : u64 {
Always = 0xF,
Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
@@ -254,20 +263,15 @@ union Instruction {
BitField<56, 1, u64> invert_b;
} lop32i;
- float GetImm20_19() const {
- float result{};
+ u32 GetImm20_19() const {
u32 imm{static_cast<u32>(imm20_19)};
imm <<= 12;
imm |= negate_imm ? 0x80000000 : 0;
- std::memcpy(&result, &imm, sizeof(imm));
- return result;
+ return imm;
}
- float GetImm20_32() const {
- float result{};
- s32 imm{static_cast<s32>(imm20_32)};
- std::memcpy(&result, &imm, sizeof(imm));
- return result;
+ u32 GetImm20_32() const {
+ return static_cast<u32>(imm20_32);
}
s32 GetSignedImm20_20() const {
@@ -461,6 +465,18 @@ union Instruction {
} bra;
union {
+ BitField<20, 16, u64> imm20_16;
+ BitField<36, 1, u64> product_shift_left;
+ BitField<37, 1, u64> merge_37;
+ BitField<48, 1, u64> sign_a;
+ BitField<49, 1, u64> sign_b;
+ BitField<50, 3, XmadMode> mode;
+ BitField<52, 1, u64> high_b;
+ BitField<53, 1, u64> high_a;
+ BitField<56, 1, u64> merge_56;
+ } xmad;
+
+ union {
BitField<20, 14, u64> offset;
BitField<34, 5, u64> index;
} cbuf34;
@@ -480,8 +496,7 @@ union Instruction {
u64 value;
};
static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size");
-static_assert(std::is_standard_layout<Instruction>::value,
- "Structure does not have standard layout");
+static_assert(std::is_standard_layout_v<Instruction>, "Instruction is not standard layout");
class OpCode {
public:
@@ -598,9 +613,17 @@ public:
IntegerSetPredicate,
PredicateSetPredicate,
Conversion,
+ Xmad,
Unknown,
};
+ /// Returns whether an opcode has an execution predicate field or not (ie, whether it can be
+ /// conditionally executed).
+ static bool IsPredicatedInstruction(Id opcode) {
+ // TODO(Subv): Add the rest of unpredicated instructions.
+ return opcode != Id::SSY;
+ }
+
class Matcher {
public:
Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type)
@@ -780,10 +803,10 @@ private:
INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"),
INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
- INST("0011011-00------", Id::XMAD_IMM, Type::Arithmetic, "XMAD_IMM"),
- INST("0100111---------", Id::XMAD_CR, Type::Arithmetic, "XMAD_CR"),
- INST("010100010-------", Id::XMAD_RC, Type::Arithmetic, "XMAD_RC"),
- INST("0101101100------", Id::XMAD_RR, Type::Arithmetic, "XMAD_RR"),
+ INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
+ INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
+ INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"),
+ INST("0101101100------", Id::XMAD_RR, Type::Xmad, "XMAD_RR"),
};
#undef INST
std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) {
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index b2a83ce0b..5a593c1f7 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/assert.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/maxwell_compute.h"
@@ -11,6 +12,15 @@
namespace Tegra {
+u32 FramebufferConfig::BytesPerPixel(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::ABGR8:
+ return 4;
+ }
+
+ UNREACHABLE();
+}
+
GPU::GPU(VideoCore::RasterizerInterface& rasterizer) {
memory_manager = std::make_unique<MemoryManager>();
maxwell_3d = std::make_unique<Engines::Maxwell3D>(rasterizer, *memory_manager);
@@ -34,18 +44,59 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
switch (format) {
case RenderTargetFormat::RGBA32_FLOAT:
+ case RenderTargetFormat::RGBA32_UINT:
return 16;
+ case RenderTargetFormat::RGBA16_UINT:
+ case RenderTargetFormat::RGBA16_UNORM:
case RenderTargetFormat::RGBA16_FLOAT:
case RenderTargetFormat::RG32_FLOAT:
+ case RenderTargetFormat::RG32_UINT:
return 8;
case RenderTargetFormat::RGBA8_UNORM:
+ case RenderTargetFormat::RGBA8_SNORM:
+ case RenderTargetFormat::RGBA8_SRGB:
case RenderTargetFormat::RGB10_A2_UNORM:
case RenderTargetFormat::BGRA8_UNORM:
+ case RenderTargetFormat::RG16_UNORM:
+ case RenderTargetFormat::RG16_SNORM:
+ case RenderTargetFormat::RG16_UINT:
+ case RenderTargetFormat::RG16_SINT:
+ case RenderTargetFormat::RG16_FLOAT:
case RenderTargetFormat::R32_FLOAT:
+ case RenderTargetFormat::R11G11B10_FLOAT:
+ case RenderTargetFormat::R32_UINT:
return 4;
+ case RenderTargetFormat::R16_UNORM:
+ case RenderTargetFormat::R16_SNORM:
+ case RenderTargetFormat::R16_UINT:
+ case RenderTargetFormat::R16_SINT:
+ case RenderTargetFormat::R16_FLOAT:
+ case RenderTargetFormat::RG8_UNORM:
+ case RenderTargetFormat::RG8_SNORM:
+ return 2;
+ case RenderTargetFormat::R8_UNORM:
+ case RenderTargetFormat::R8_UINT:
+ return 1;
default:
UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format));
}
}
+u32 DepthFormatBytesPerPixel(DepthFormat format) {
+ switch (format) {
+ case DepthFormat::Z32_S8_X24_FLOAT:
+ return 8;
+ case DepthFormat::Z32_FLOAT:
+ case DepthFormat::S8_Z24_UNORM:
+ case DepthFormat::Z24_X8_UNORM:
+ case DepthFormat::Z24_S8_UNORM:
+ case DepthFormat::Z24_C8_UNORM:
+ return 4;
+ case DepthFormat::Z16_UNORM:
+ return 2;
+ default:
+ UNIMPLEMENTED_MSG("Unimplemented Depth format {}", static_cast<u32>(format));
+ }
+}
+
} // namespace Tegra
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 440505c9d..97dcccb92 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -6,7 +6,6 @@
#include <memory>
#include <unordered_map>
-#include <vector>
#include "common/common_types.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
#include "video_core/memory_manager.h"
@@ -21,21 +20,34 @@ enum class RenderTargetFormat : u32 {
NONE = 0x0,
RGBA32_FLOAT = 0xC0,
RGBA32_UINT = 0xC2,
+ RGBA16_UNORM = 0xC6,
+ RGBA16_UINT = 0xC9,
RGBA16_FLOAT = 0xCA,
RG32_FLOAT = 0xCB,
+ RG32_UINT = 0xCD,
BGRA8_UNORM = 0xCF,
RGB10_A2_UNORM = 0xD1,
RGBA8_UNORM = 0xD5,
RGBA8_SRGB = 0xD6,
+ RGBA8_SNORM = 0xD7,
RG16_UNORM = 0xDA,
RG16_SNORM = 0xDB,
RG16_SINT = 0xDC,
RG16_UINT = 0xDD,
RG16_FLOAT = 0xDE,
R11G11B10_FLOAT = 0xE0,
+ R32_UINT = 0xE4,
R32_FLOAT = 0xE5,
+ B5G6R5_UNORM = 0xE8,
+ RG8_UNORM = 0xEA,
+ RG8_SNORM = 0xEB,
+ R16_UNORM = 0xEE,
+ R16_SNORM = 0xEF,
+ R16_SINT = 0xF0,
+ R16_UINT = 0xF1,
R16_FLOAT = 0xF2,
R8_UNORM = 0xF3,
+ R8_UINT = 0xF6,
};
enum class DepthFormat : u32 {
@@ -51,6 +63,9 @@ enum class DepthFormat : u32 {
/// Returns the number of bytes per pixel of each rendertarget format.
u32 RenderTargetBytesPerPixel(RenderTargetFormat format);
+/// Returns the number of bytes per pixel of each depth format.
+u32 DepthFormatBytesPerPixel(DepthFormat format);
+
class DebugContext;
/**
@@ -64,14 +79,7 @@ struct FramebufferConfig {
/**
* Returns the number of bytes per pixel.
*/
- static u32 BytesPerPixel(PixelFormat format) {
- switch (format) {
- case PixelFormat::ABGR8:
- return 4;
- }
-
- UNREACHABLE();
- }
+ static u32 BytesPerPixel(PixelFormat format);
VAddr address;
u32 offset;
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index 3ca350243..afd86a83a 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -4,18 +4,23 @@
#include <memory>
#include "core/frontend/emu_window.h"
+#include "core/settings.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
namespace VideoCore {
-RendererBase::RendererBase(EmuWindow& window) : render_window{window} {}
+RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} {
+ RefreshBaseSettings();
+}
+
RendererBase::~RendererBase() = default;
-void RendererBase::UpdateCurrentFramebufferLayout() {
- const Layout::FramebufferLayout& layout = render_window.GetFramebufferLayout();
+void RendererBase::RefreshBaseSettings() {
+ RefreshRasterizerSetting();
+ UpdateCurrentFramebufferLayout();
- render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
+ renderer_settings.use_framelimiter = Settings::values.toggle_framelimit;
}
void RendererBase::RefreshRasterizerSetting() {
@@ -24,4 +29,10 @@ void RendererBase::RefreshRasterizerSetting() {
}
}
+void RendererBase::UpdateCurrentFramebufferLayout() {
+ const Layout::FramebufferLayout& layout = render_window.GetFramebufferLayout();
+
+ render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
+}
+
} // namespace VideoCore
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 235de23a1..d9f16b8e6 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -4,23 +4,26 @@
#pragma once
+#include <atomic>
#include <memory>
#include <boost/optional.hpp>
-#include "common/assert.h"
#include "common/common_types.h"
#include "video_core/gpu.h"
#include "video_core/rasterizer_interface.h"
+namespace Core::Frontend {
class EmuWindow;
+}
namespace VideoCore {
+struct RendererSettings {
+ std::atomic_bool use_framelimiter{false};
+};
+
class RendererBase : NonCopyable {
public:
- /// Used to reference a framebuffer
- enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture };
-
- explicit RendererBase(EmuWindow& window);
+ explicit RendererBase(Core::Frontend::EmuWindow& window);
virtual ~RendererBase();
/// Swap buffers (render frame)
@@ -32,9 +35,6 @@ public:
/// Shutdown the renderer
virtual void ShutDown() = 0;
- /// Updates the framebuffer layout of the contained render window handle.
- void UpdateCurrentFramebufferLayout();
-
// Getter/setter functions:
// ------------------------
@@ -54,13 +54,23 @@ public:
return *rasterizer;
}
- void RefreshRasterizerSetting();
+ /// Refreshes the settings common to all renderers
+ void RefreshBaseSettings();
protected:
- EmuWindow& render_window; ///< Reference to the render window handle.
+ /// Refreshes settings specific to the rasterizer.
+ void RefreshRasterizerSetting();
+
+ Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
std::unique_ptr<RasterizerInterface> rasterizer;
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
int m_current_frame = 0; ///< Current frame, should be set by the renderer
+
+ RendererSettings renderer_settings;
+
+private:
+ /// Updates the framebuffer layout of the contained render window handle.
+ void UpdateCurrentFramebufferLayout();
};
} // namespace VideoCore
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index c2a931469..52a649e2f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -36,30 +36,21 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
-RasterizerOpenGL::RasterizerOpenGL(EmuWindow& window) : emu_window{window} {
+RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window)
+ : emu_window{window}, stream_buffer(GL_ARRAY_BUFFER, STREAM_BUFFER_SIZE) {
// Create sampler objects
for (size_t i = 0; i < texture_samplers.size(); ++i) {
texture_samplers[i].Create();
state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
}
- // Create SSBOs
- for (size_t stage = 0; stage < ssbos.size(); ++stage) {
- for (size_t buffer = 0; buffer < ssbos[stage].size(); ++buffer) {
- ssbos[stage][buffer].Create();
- state.draw.const_buffers[stage][buffer].ssbo = ssbos[stage][buffer].handle;
- }
- }
-
GLint ext_num;
glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num);
for (GLint i = 0; i < ext_num; i++) {
const std::string_view extension{
reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))};
- if (extension == "GL_ARB_buffer_storage") {
- has_ARB_buffer_storage = true;
- } else if (extension == "GL_ARB_direct_state_access") {
+ if (extension == "GL_ARB_direct_state_access") {
has_ARB_direct_state_access = true;
} else if (extension == "GL_ARB_separate_shader_objects") {
has_ARB_separate_shader_objects = true;
@@ -86,47 +77,31 @@ RasterizerOpenGL::RasterizerOpenGL(EmuWindow& window) : emu_window{window} {
hw_vao.Create();
- stream_buffer = OGLStreamBuffer::MakeBuffer(has_ARB_buffer_storage, GL_ARRAY_BUFFER);
- stream_buffer->Create(STREAM_BUFFER_SIZE, STREAM_BUFFER_SIZE / 2);
- state.draw.vertex_buffer = stream_buffer->GetHandle();
+ state.draw.vertex_buffer = stream_buffer.GetHandle();
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
state.draw.shader_program = 0;
state.draw.vertex_array = hw_vao.handle;
state.Apply();
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle());
-
- for (unsigned index = 0; index < uniform_buffers.size(); ++index) {
- auto& buffer = uniform_buffers[index];
- buffer.Create();
- glBindBuffer(GL_UNIFORM_BUFFER, buffer.handle);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(GLShader::MaxwellUniformData), nullptr,
- GL_STREAM_COPY);
- glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.handle);
- }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer.GetHandle());
glEnable(GL_BLEND);
+ glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
+
LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
}
-RasterizerOpenGL::~RasterizerOpenGL() {
- if (stream_buffer != nullptr) {
- state.draw.vertex_buffer = stream_buffer->GetHandle();
- state.Apply();
- stream_buffer->Release();
- }
-}
+RasterizerOpenGL::~RasterizerOpenGL() {}
std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
GLintptr buffer_offset) {
MICROPROFILE_SCOPE(OpenGL_VAO);
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
- const auto& memory_manager = Core::System::GetInstance().GPU().memory_manager;
state.draw.vertex_array = hw_vao.handle;
- state.draw.vertex_buffer = stream_buffer->GetHandle();
+ state.draw.vertex_buffer = stream_buffer.GetHandle();
state.Apply();
// Upload all guest vertex arrays sequentially to our buffer
@@ -141,16 +116,15 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
ASSERT(end > start);
u64 size = end - start + 1;
- // Copy vertex array data
- Memory::ReadBlock(*memory_manager->GpuToCpuAddress(start), array_ptr, size);
+ GLintptr vertex_buffer_offset;
+ std::tie(array_ptr, buffer_offset, vertex_buffer_offset) =
+ UploadMemory(array_ptr, buffer_offset, start, size);
// Bind the vertex array to the buffer at the current offset.
- glBindVertexBuffer(index, stream_buffer->GetHandle(), buffer_offset, vertex_array.stride);
+ glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset,
+ vertex_array.stride);
ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented");
-
- array_ptr += size;
- buffer_offset += size;
}
// Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
@@ -161,11 +135,16 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
// assume every shader uses them all.
for (unsigned index = 0; index < 16; ++index) {
auto& attrib = regs.vertex_attrib_format[index];
- LOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
+
+ // Ignore invalid attributes.
+ if (!attrib.IsValid())
+ continue;
+
+ auto& buffer = regs.vertex_array[attrib.buffer];
+ LOG_TRACE(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
attrib.offset.Value(), attrib.IsNormalized());
- auto& buffer = regs.vertex_array[attrib.buffer];
ASSERT(buffer.IsEnabled());
glEnableVertexAttribArray(index);
@@ -196,22 +175,12 @@ static GLShader::ProgramCode GetShaderProgramCode(Maxwell::ShaderProgram program
return program_code;
}
-void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
- // Helper function for uploading uniform data
- const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
- if (has_ARB_direct_state_access) {
- glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size);
- } else {
- glBindBuffer(GL_COPY_WRITE_BUFFER, handle);
- glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size);
- }
- };
-
+std::pair<u8*, GLintptr> RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
// Next available bindpoints to use when uploading the const buffers and textures to the GLSL
// shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
- u32 current_constbuffer_bindpoint = uniform_buffers.size();
+ u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
u32 current_texture_bindpoint = 0;
for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
@@ -223,22 +192,21 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
continue;
}
+ std::tie(buffer_ptr, buffer_offset) =
+ AlignBuffer(buffer_ptr, buffer_offset, static_cast<size_t>(uniform_buffer_alignment));
+
const size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5
GLShader::MaxwellUniformData ubo{};
ubo.SetFromRegs(gpu.state.shader_stages[stage]);
std::memcpy(buffer_ptr, &ubo, sizeof(ubo));
- // Flush the buffer so that the GPU can see the data we just wrote.
- glFlushMappedBufferRange(GL_ARRAY_BUFFER, buffer_offset, sizeof(ubo));
+ // Bind the buffer
+ glBindBufferRange(GL_UNIFORM_BUFFER, stage, stream_buffer.GetHandle(), buffer_offset,
+ sizeof(ubo));
- // Upload uniform data as one UBO per stage
- const GLintptr ubo_offset = buffer_offset;
- copy_buffer(uniform_buffers[stage].handle, ubo_offset,
- sizeof(GLShader::MaxwellUniformData));
-
- buffer_ptr += sizeof(GLShader::MaxwellUniformData);
- buffer_offset += sizeof(GLShader::MaxwellUniformData);
+ buffer_ptr += sizeof(ubo);
+ buffer_offset += sizeof(ubo);
GLShader::ShaderSetup setup{GetShaderProgramCode(program)};
GLShader::ShaderEntries shader_resources;
@@ -277,9 +245,9 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
static_cast<Maxwell::ShaderStage>(stage));
// Configure the const buffers for this shader stage.
- current_constbuffer_bindpoint =
- SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), gl_stage_program,
- current_constbuffer_bindpoint, shader_resources.const_buffer_entries);
+ std::tie(buffer_ptr, buffer_offset, current_constbuffer_bindpoint) = SetupConstBuffers(
+ buffer_ptr, buffer_offset, static_cast<Maxwell::ShaderStage>(stage), gl_stage_program,
+ current_constbuffer_bindpoint, shader_resources.const_buffer_entries);
// Configure the textures for this shader stage.
current_texture_bindpoint =
@@ -294,6 +262,8 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
}
shader_program_manager->UseTrivialGeometryShader();
+
+ return {buffer_ptr, buffer_offset};
}
size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
@@ -324,11 +294,14 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c
bool using_depth_fb) {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+ if (regs.rt[0].format == Tegra::RenderTargetFormat::NONE) {
+ LOG_ERROR(HW_GPU, "RenderTargetFormat is not configured");
+ using_color_fb = false;
+ }
+
// TODO(bunnei): Implement this
const bool has_stencil = false;
- const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
-
const bool write_color_fb =
state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
@@ -341,9 +314,10 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c
Surface depth_surface;
MathUtil::Rectangle<u32> surfaces_rect;
std::tie(color_surface, depth_surface, surfaces_rect) =
- res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect);
+ res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb);
- MathUtil::Rectangle<u32> draw_rect{
+ const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
+ const MathUtil::Rectangle<u32> draw_rect{
static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left,
surfaces_rect.left, surfaces_rect.right)), // Left
static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top,
@@ -423,6 +397,31 @@ void RasterizerOpenGL::Clear() {
}
}
+std::pair<u8*, GLintptr> RasterizerOpenGL::AlignBuffer(u8* buffer_ptr, GLintptr buffer_offset,
+ size_t alignment) {
+ // Align the offset, not the mapped pointer
+ GLintptr offset_aligned =
+ static_cast<GLintptr>(Common::AlignUp(static_cast<size_t>(buffer_offset), alignment));
+ return {buffer_ptr + (offset_aligned - buffer_offset), offset_aligned};
+}
+
+std::tuple<u8*, GLintptr, GLintptr> RasterizerOpenGL::UploadMemory(u8* buffer_ptr,
+ GLintptr buffer_offset,
+ Tegra::GPUVAddr gpu_addr,
+ size_t size, size_t alignment) {
+ std::tie(buffer_ptr, buffer_offset) = AlignBuffer(buffer_ptr, buffer_offset, alignment);
+ GLintptr uploaded_offset = buffer_offset;
+
+ const auto& memory_manager = Core::System::GetInstance().GPU().memory_manager;
+ const boost::optional<VAddr> cpu_addr{memory_manager->GpuToCpuAddress(gpu_addr)};
+ Memory::ReadBlock(*cpu_addr, buffer_ptr, size);
+
+ buffer_ptr += size;
+ buffer_offset += size;
+
+ return {buffer_ptr, buffer_offset, uploaded_offset};
+}
+
void RasterizerOpenGL::DrawArrays() {
if (accelerate_draw == AccelDraw::Disabled)
return;
@@ -447,7 +446,7 @@ void RasterizerOpenGL::DrawArrays() {
const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
- state.draw.vertex_buffer = stream_buffer->GetHandle();
+ state.draw.vertex_buffer = stream_buffer.GetHandle();
state.Apply();
size_t buffer_size = CalculateVertexArraysSize();
@@ -457,41 +456,31 @@ void RasterizerOpenGL::DrawArrays() {
}
// Uniform space for the 5 shader stages
- buffer_size = Common::AlignUp<size_t>(buffer_size, 4) +
- sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage;
+ buffer_size =
+ Common::AlignUp<size_t>(buffer_size, 4) +
+ (sizeof(GLShader::MaxwellUniformData) + uniform_buffer_alignment) * Maxwell::MaxShaderStage;
+
+ // Add space for at least 18 constant buffers
+ buffer_size += Maxwell::MaxConstBuffers * (MaxConstbufferSize + uniform_buffer_alignment);
u8* buffer_ptr;
GLintptr buffer_offset;
- std::tie(buffer_ptr, buffer_offset) =
- stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4);
+ std::tie(buffer_ptr, buffer_offset, std::ignore) =
+ stream_buffer.Map(static_cast<GLsizeiptr>(buffer_size), 4);
+ u8* buffer_ptr_base = buffer_ptr;
- u8* offseted_buffer;
- std::tie(offseted_buffer, buffer_offset) = SetupVertexArrays(buffer_ptr, buffer_offset);
-
- offseted_buffer =
- reinterpret_cast<u8*>(Common::AlignUp(reinterpret_cast<size_t>(offseted_buffer), 4));
- buffer_offset = Common::AlignUp<size_t>(buffer_offset, 4);
+ std::tie(buffer_ptr, buffer_offset) = SetupVertexArrays(buffer_ptr, buffer_offset);
// If indexed mode, copy the index buffer
GLintptr index_buffer_offset = 0;
if (is_indexed) {
- const auto& memory_manager = Core::System::GetInstance().GPU().memory_manager;
- const boost::optional<VAddr> index_data_addr{
- memory_manager->GpuToCpuAddress(regs.index_array.StartAddress())};
- Memory::ReadBlock(*index_data_addr, offseted_buffer, index_buffer_size);
-
- index_buffer_offset = buffer_offset;
- offseted_buffer += index_buffer_size;
- buffer_offset += index_buffer_size;
+ std::tie(buffer_ptr, buffer_offset, index_buffer_offset) = UploadMemory(
+ buffer_ptr, buffer_offset, regs.index_array.StartAddress(), index_buffer_size);
}
- offseted_buffer =
- reinterpret_cast<u8*>(Common::AlignUp(reinterpret_cast<size_t>(offseted_buffer), 4));
- buffer_offset = Common::AlignUp<size_t>(buffer_offset, 4);
-
- SetupShaders(offseted_buffer, buffer_offset);
+ std::tie(buffer_ptr, buffer_offset) = SetupShaders(buffer_ptr, buffer_offset);
- stream_buffer->Unmap();
+ stream_buffer.Unmap(buffer_ptr - buffer_ptr_base);
shader_program_manager->ApplyTo(state);
state.Apply();
@@ -638,32 +627,22 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
}
}
-u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint program,
- u32 current_bindpoint,
- const std::vector<GLShader::ConstBufferEntry>& entries) {
+std::tuple<u8*, GLintptr, u32> RasterizerOpenGL::SetupConstBuffers(
+ u8* buffer_ptr, GLintptr buffer_offset, Maxwell::ShaderStage stage, GLuint program,
+ u32 current_bindpoint, const std::vector<GLShader::ConstBufferEntry>& entries) {
const auto& gpu = Core::System::GetInstance().GPU();
const auto& maxwell3d = gpu.Maxwell3D();
- // Reset all buffer draw state for this stage.
- for (auto& buffer : state.draw.const_buffers[static_cast<size_t>(stage)]) {
- buffer.bindpoint = 0;
- buffer.enabled = false;
- }
-
// Upload only the enabled buffers from the 16 constbuffers of each shader stage
const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<size_t>(stage)];
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& used_buffer = entries[bindpoint];
const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()];
- auto& buffer_draw_state =
- state.draw.const_buffers[static_cast<size_t>(stage)][used_buffer.GetIndex()];
-
- ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer");
- buffer_draw_state.enabled = true;
- buffer_draw_state.bindpoint = current_bindpoint + bindpoint;
- boost::optional<VAddr> addr = gpu.memory_manager->GpuToCpuAddress(buffer.address);
+ if (!buffer.enabled) {
+ continue;
+ }
size_t size = 0;
@@ -686,25 +665,26 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr
size = Common::AlignUp(size, sizeof(GLvec4));
ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big");
- std::vector<u8> data(size);
- Memory::ReadBlock(*addr, data.data(), data.size());
+ GLintptr const_buffer_offset;
+ std::tie(buffer_ptr, buffer_offset, const_buffer_offset) =
+ UploadMemory(buffer_ptr, buffer_offset, buffer.address, size,
+ static_cast<size_t>(uniform_buffer_alignment));
- glBindBuffer(GL_UNIFORM_BUFFER, buffer_draw_state.ssbo);
- glBufferData(GL_UNIFORM_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ glBindBufferRange(GL_UNIFORM_BUFFER, current_bindpoint + bindpoint,
+ stream_buffer.GetHandle(), const_buffer_offset, size);
// Now configure the bindpoint of the buffer inside the shader
const std::string buffer_name = used_buffer.GetName();
const GLuint index =
glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, buffer_name.c_str());
if (index != GL_INVALID_INDEX) {
- glUniformBlockBinding(program, index, buffer_draw_state.bindpoint);
+ glUniformBlockBinding(program, index, current_bindpoint + bindpoint);
}
}
state.Apply();
- return current_bindpoint + static_cast<u32>(entries.size());
+ return {buffer_ptr, buffer_offset, current_bindpoint + static_cast<u32>(entries.size())};
}
u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, GLuint program, u32 current_unit,
@@ -804,9 +784,7 @@ void RasterizerOpenGL::SyncClipCoef() {
void RasterizerOpenGL::SyncCullMode() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
- // TODO(bunnei): Enable the below once more things work - until then, this may hide regressions
- // state.cull.enabled = regs.cull.enabled != 0;
- state.cull.enabled = false;
+ state.cull.enabled = regs.cull.enabled != 0;
if (state.cull.enabled) {
state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 6d6d85cc1..74307f626 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -7,6 +7,7 @@
#include <array>
#include <cstddef>
#include <memory>
+#include <tuple>
#include <utility>
#include <vector>
#include <glad/glad.h>
@@ -21,12 +22,15 @@
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
-class EmuWindow;
struct ScreenInfo;
+namespace Core::Frontend {
+class EmuWindow;
+}
+
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
- explicit RasterizerOpenGL(EmuWindow& renderer);
+ explicit RasterizerOpenGL(Core::Frontend::EmuWindow& renderer);
~RasterizerOpenGL() override;
void DrawArrays() override;
@@ -97,9 +101,10 @@ private:
* @param entries Vector describing the buffers that are actually used in the guest shader.
* @returns The next available bindpoint for use in the next shader stage.
*/
- u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, GLuint program,
- u32 current_bindpoint,
- const std::vector<GLShader::ConstBufferEntry>& entries);
+ std::tuple<u8*, GLintptr, u32> SetupConstBuffers(
+ u8* buffer_ptr, GLintptr buffer_offset, Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
+ GLuint program, u32 current_bindpoint,
+ const std::vector<GLShader::ConstBufferEntry>& entries);
/*
* Configures the current textures to use for the draw command.
@@ -136,7 +141,6 @@ private:
/// Syncs the blend state to match the guest state
void SyncBlendState();
- bool has_ARB_buffer_storage = false;
bool has_ARB_direct_state_access = false;
bool has_ARB_separate_shader_objects = false;
bool has_ARB_vertex_attrib_binding = false;
@@ -145,29 +149,31 @@ private:
RasterizerCacheOpenGL res_cache;
- EmuWindow& emu_window;
+ Core::Frontend::EmuWindow& emu_window;
std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
OGLVertexArray sw_vao;
OGLVertexArray hw_vao;
std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers;
- std::array<std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers>,
- Tegra::Engines::Maxwell3D::Regs::MaxShaderStage>
- ssbos;
static constexpr size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
- std::unique_ptr<OGLStreamBuffer> stream_buffer;
+ OGLStreamBuffer stream_buffer;
OGLBuffer uniform_buffer;
OGLFramebuffer framebuffer;
+ GLint uniform_buffer_alignment;
size_t CalculateVertexArraysSize() const;
std::pair<u8*, GLintptr> SetupVertexArrays(u8* array_ptr, GLintptr buffer_offset);
- std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
+ std::pair<u8*, GLintptr> SetupShaders(u8* buffer_ptr, GLintptr buffer_offset);
+
+ std::pair<u8*, GLintptr> AlignBuffer(u8* buffer_ptr, GLintptr buffer_offset, size_t alignment);
- void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset);
+ std::tuple<u8*, GLintptr, GLintptr> UploadMemory(u8* buffer_ptr, GLintptr buffer_offset,
+ Tegra::GPUVAddr gpu_addr, size_t size,
+ size_t alignment = 4);
enum class AccelDraw { Disabled, Arrays, Indexed };
AccelDraw accelerate_draw = AccelDraw::Disabled;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index c8f0c4e28..5d58ebd4f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -46,6 +46,8 @@ struct FormatTuple {
params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
params.unaligned_height = config.tic.Height();
params.size_in_bytes = params.SizeInBytes();
+ params.cache_width = Common::AlignUp(params.width, 16);
+ params.cache_height = Common::AlignUp(params.height, 16);
return params;
}
@@ -63,6 +65,8 @@ struct FormatTuple {
params.height = config.height;
params.unaligned_height = config.height;
params.size_in_bytes = params.SizeInBytes();
+ params.cache_width = Common::AlignUp(params.width, 16);
+ params.cache_height = Common::AlignUp(params.height, 16);
return params;
}
@@ -82,17 +86,23 @@ struct FormatTuple {
params.height = zeta_height;
params.unaligned_height = zeta_height;
params.size_in_bytes = params.SizeInBytes();
+ params.cache_width = Common::AlignUp(params.width, 16);
+ params.cache_height = Common::AlignUp(params.height, 16);
return params;
}
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
- {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8
+ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8U
+ {GL_RGBA8, GL_RGBA, GL_BYTE, ComponentType::SNorm, false}, // ABGR8S
{GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, ComponentType::UNorm, false}, // B5G6R5
{GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, ComponentType::UNorm,
false}, // A2B10G10R10
{GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ComponentType::UNorm, false}, // A1B5G5R5
{GL_R8, GL_RED, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // R8
+ {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // R8UI
{GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBA16F
+ {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RGBA16U
+ {GL_RGBA16UI, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI
{GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, ComponentType::Float,
false}, // R11FG11FB10F
{GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RGBA32UI
@@ -103,7 +113,10 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
true}, // DXT45
{GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, true}, // DXN1
- {GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
+ {GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
+ true}, // DXN2UNORM
+ {GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_INT, ComponentType::SNorm, true}, // DXN2SNORM
+ {GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
true}, // BC7U
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
{GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8
@@ -113,6 +126,9 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
{GL_R32F, GL_RED, GL_FLOAT, ComponentType::Float, false}, // R32F
{GL_R16F, GL_RED, GL_HALF_FLOAT, ComponentType::Float, false}, // R16F
{GL_R16, GL_RED, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // R16UNORM
+ {GL_R16_SNORM, GL_RED, GL_SHORT, ComponentType::SNorm, false}, // R16S
+ {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // R16UI
+ {GL_R16I, GL_RED_INTEGER, GL_SHORT, ComponentType::SInt, false}, // R16I
{GL_RG16, GL_RG, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RG16
{GL_RG16F, GL_RG, GL_HALF_FLOAT, ComponentType::Float, false}, // RG16F
{GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RG16UI
@@ -120,6 +136,10 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
{GL_RG16_SNORM, GL_RG, GL_SHORT, ComponentType::SNorm, false}, // RG16S
{GL_RGB32F, GL_RGB, GL_FLOAT, ComponentType::Float, false}, // RGB32F
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // SRGBA8
+ {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // RG8U
+ {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S
+ {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RG32UI
+ {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // R32UI
// DepthStencil formats
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm,
@@ -174,69 +194,121 @@ MathUtil::Rectangle<u32> SurfaceParams::GetRect() const {
return {0, actual_height, width, 0};
}
+/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
+static bool IsFormatBCn(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::DXT1:
+ case PixelFormat::DXT23:
+ case PixelFormat::DXT45:
+ case PixelFormat::DXN1:
+ case PixelFormat::DXN2SNORM:
+ case PixelFormat::DXN2UNORM:
+ case PixelFormat::BC7U:
+ return true;
+ }
+ return false;
+}
+
template <bool morton_to_gl, PixelFormat format>
-void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::GPUVAddr addr) {
+void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_buffer,
+ Tegra::GPUVAddr addr) {
constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT;
constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
const auto& gpu = Core::System::GetInstance().GPU();
if (morton_to_gl) {
- if (SurfaceParams::GetFormatType(format) == SurfaceType::ColorTexture) {
- auto data = Tegra::Texture::UnswizzleTexture(
- *gpu.memory_manager->GpuToCpuAddress(addr),
- SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
- std::memcpy(gl_buffer, data.data(), data.size());
- } else {
- auto data = Tegra::Texture::UnswizzleDepthTexture(
- *gpu.memory_manager->GpuToCpuAddress(addr),
- SurfaceParams::DepthFormatFromPixelFormat(format), stride, height, block_height);
- std::memcpy(gl_buffer, data.data(), data.size());
- }
+ // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
+ // pixel values.
+ const u32 tile_size{IsFormatBCn(format) ? 4U : 1U};
+ const std::vector<u8> data =
+ Tegra::Texture::UnswizzleTexture(*gpu.memory_manager->GpuToCpuAddress(addr), tile_size,
+ bytes_per_pixel, stride, height, block_height);
+ const size_t size_to_copy{std::min(gl_buffer.size(), data.size())};
+ gl_buffer.assign(data.begin(), data.begin() + size_to_copy);
} else {
// TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should
// check the configuration for this and perform more generic un/swizzle
LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
VideoCore::MortonCopyPixels128(
stride, height, bytes_per_pixel, gl_bytes_per_pixel,
- Memory::GetPointer(*gpu.memory_manager->GpuToCpuAddress(addr)), gl_buffer,
+ Memory::GetPointer(*gpu.memory_manager->GpuToCpuAddress(addr)), gl_buffer.data(),
morton_to_gl);
}
}
-static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
+static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPUVAddr),
SurfaceParams::MaxPixelFormat>
morton_to_gl_fns = {
- MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
- MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::A1B5G5R5>,
- MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::RGBA16F>,
- MortonCopy<true, PixelFormat::R11FG11FB10F>, MortonCopy<true, PixelFormat::RGBA32UI>,
- MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
- MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>,
- MortonCopy<true, PixelFormat::BC7U>, MortonCopy<true, PixelFormat::ASTC_2D_4X4>,
- MortonCopy<true, PixelFormat::G8R8>, MortonCopy<true, PixelFormat::BGRA8>,
- MortonCopy<true, PixelFormat::RGBA32F>, MortonCopy<true, PixelFormat::RG32F>,
- MortonCopy<true, PixelFormat::R32F>, MortonCopy<true, PixelFormat::R16F>,
- MortonCopy<true, PixelFormat::R16UNORM>, MortonCopy<true, PixelFormat::RG16>,
- MortonCopy<true, PixelFormat::RG16F>, MortonCopy<true, PixelFormat::RG16UI>,
- MortonCopy<true, PixelFormat::RG16I>, MortonCopy<true, PixelFormat::RG16S>,
- MortonCopy<true, PixelFormat::RGB32F>, MortonCopy<true, PixelFormat::SRGBA8>,
- MortonCopy<true, PixelFormat::Z24S8>, MortonCopy<true, PixelFormat::S8Z24>,
- MortonCopy<true, PixelFormat::Z32F>, MortonCopy<true, PixelFormat::Z16>,
+ // clang-format off
+ MortonCopy<true, PixelFormat::ABGR8U>,
+ MortonCopy<true, PixelFormat::ABGR8S>,
+ MortonCopy<true, PixelFormat::B5G6R5>,
+ MortonCopy<true, PixelFormat::A2B10G10R10>,
+ MortonCopy<true, PixelFormat::A1B5G5R5>,
+ MortonCopy<true, PixelFormat::R8>,
+ MortonCopy<true, PixelFormat::R8UI>,
+ MortonCopy<true, PixelFormat::RGBA16F>,
+ MortonCopy<true, PixelFormat::RGBA16U>,
+ MortonCopy<true, PixelFormat::RGBA16UI>,
+ MortonCopy<true, PixelFormat::R11FG11FB10F>,
+ MortonCopy<true, PixelFormat::RGBA32UI>,
+ MortonCopy<true, PixelFormat::DXT1>,
+ MortonCopy<true, PixelFormat::DXT23>,
+ MortonCopy<true, PixelFormat::DXT45>,
+ MortonCopy<true, PixelFormat::DXN1>,
+ MortonCopy<true, PixelFormat::DXN2UNORM>,
+ MortonCopy<true, PixelFormat::DXN2SNORM>,
+ MortonCopy<true, PixelFormat::BC7U>,
+ MortonCopy<true, PixelFormat::ASTC_2D_4X4>,
+ MortonCopy<true, PixelFormat::G8R8>,
+ MortonCopy<true, PixelFormat::BGRA8>,
+ MortonCopy<true, PixelFormat::RGBA32F>,
+ MortonCopy<true, PixelFormat::RG32F>,
+ MortonCopy<true, PixelFormat::R32F>,
+ MortonCopy<true, PixelFormat::R16F>,
+ MortonCopy<true, PixelFormat::R16UNORM>,
+ MortonCopy<true, PixelFormat::R16S>,
+ MortonCopy<true, PixelFormat::R16UI>,
+ MortonCopy<true, PixelFormat::R16I>,
+ MortonCopy<true, PixelFormat::RG16>,
+ MortonCopy<true, PixelFormat::RG16F>,
+ MortonCopy<true, PixelFormat::RG16UI>,
+ MortonCopy<true, PixelFormat::RG16I>,
+ MortonCopy<true, PixelFormat::RG16S>,
+ MortonCopy<true, PixelFormat::RGB32F>,
+ MortonCopy<true, PixelFormat::SRGBA8>,
+ MortonCopy<true, PixelFormat::RG8U>,
+ MortonCopy<true, PixelFormat::RG8S>,
+ MortonCopy<true, PixelFormat::RG32UI>,
+ MortonCopy<true, PixelFormat::R32UI>,
+ MortonCopy<true, PixelFormat::Z24S8>,
+ MortonCopy<true, PixelFormat::S8Z24>,
+ MortonCopy<true, PixelFormat::Z32F>,
+ MortonCopy<true, PixelFormat::Z16>,
MortonCopy<true, PixelFormat::Z32FS8>,
+ // clang-format on
};
-static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
+static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, Tegra::GPUVAddr),
SurfaceParams::MaxPixelFormat>
gl_to_morton_fns = {
- MortonCopy<false, PixelFormat::ABGR8>,
+ // clang-format off
+ MortonCopy<false, PixelFormat::ABGR8U>,
+ MortonCopy<false, PixelFormat::ABGR8S>,
MortonCopy<false, PixelFormat::B5G6R5>,
MortonCopy<false, PixelFormat::A2B10G10R10>,
MortonCopy<false, PixelFormat::A1B5G5R5>,
MortonCopy<false, PixelFormat::R8>,
+ MortonCopy<false, PixelFormat::R8UI>,
MortonCopy<false, PixelFormat::RGBA16F>,
+ MortonCopy<false, PixelFormat::RGBA16U>,
+ MortonCopy<false, PixelFormat::RGBA16UI>,
MortonCopy<false, PixelFormat::R11FG11FB10F>,
MortonCopy<false, PixelFormat::RGBA32UI>,
- // TODO(Subv): Swizzling DXT1/DXT23/DXT45/DXN1/BC7U/ASTC_2D_4X4 formats is not supported
+ // TODO(Subv): Swizzling DXT1/DXT23/DXT45/DXN1/DXN2/BC7U/ASTC_2D_4X4 formats is not
+ // supported
+ nullptr,
+ nullptr,
nullptr,
nullptr,
nullptr,
@@ -250,6 +322,9 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
MortonCopy<false, PixelFormat::R32F>,
MortonCopy<false, PixelFormat::R16F>,
MortonCopy<false, PixelFormat::R16UNORM>,
+ MortonCopy<false, PixelFormat::R16S>,
+ MortonCopy<false, PixelFormat::R16UI>,
+ MortonCopy<false, PixelFormat::R16I>,
MortonCopy<false, PixelFormat::RG16>,
MortonCopy<false, PixelFormat::RG16F>,
MortonCopy<false, PixelFormat::RG16UI>,
@@ -257,11 +332,16 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
MortonCopy<false, PixelFormat::RG16S>,
MortonCopy<false, PixelFormat::RGB32F>,
MortonCopy<false, PixelFormat::SRGBA8>,
+ MortonCopy<false, PixelFormat::RG8U>,
+ MortonCopy<false, PixelFormat::RG8S>,
+ MortonCopy<false, PixelFormat::RG32UI>,
+ MortonCopy<false, PixelFormat::R32UI>,
MortonCopy<false, PixelFormat::Z24S8>,
MortonCopy<false, PixelFormat::S8Z24>,
MortonCopy<false, PixelFormat::Z32F>,
MortonCopy<false, PixelFormat::Z16>,
MortonCopy<false, PixelFormat::Z32FS8>,
+ // clang-format on
};
// Allocate an uninitialized texture of appropriate size and format for the surface
@@ -441,22 +521,24 @@ MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64
void CachedSurface::LoadGLBuffer() {
ASSERT(params.type != SurfaceType::Fill);
- u8* const texture_src_data = Memory::GetPointer(params.GetCpuAddr());
+ const u8* const texture_src_data = Memory::GetPointer(params.GetCpuAddr());
ASSERT(texture_src_data);
- gl_buffer.resize(params.width * params.height * GetGLBytesPerPixel(params.pixel_format));
+ const u32 bytes_per_pixel = GetGLBytesPerPixel(params.pixel_format);
+ const u32 copy_size = params.width * params.height * bytes_per_pixel;
MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
- if (!params.is_tiled) {
- const u32 bytes_per_pixel{params.GetFormatBpp() >> 3};
+ if (params.is_tiled) {
+ gl_buffer.resize(copy_size);
- std::memcpy(gl_buffer.data(), texture_src_data,
- bytes_per_pixel * params.width * params.height);
- } else {
morton_to_gl_fns[static_cast<size_t>(params.pixel_format)](
- params.width, params.block_height, params.height, gl_buffer.data(), params.addr);
+ params.width, params.block_height, params.height, gl_buffer, params.addr);
+ } else {
+ const u8* const texture_src_data_end = texture_src_data + copy_size;
+
+ gl_buffer.assign(texture_src_data, texture_src_data_end);
}
ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer, params.pixel_format, params.width, params.height);
@@ -479,7 +561,7 @@ void CachedSurface::FlushGLBuffer() {
std::memcpy(dst_buffer, gl_buffer.data(), params.size_in_bytes);
} else {
gl_to_morton_fns[static_cast<size_t>(params.pixel_format)](
- params.width, params.block_height, params.height, gl_buffer.data(), params.addr);
+ params.width, params.block_height, params.height, gl_buffer, params.addr);
}
}
@@ -594,8 +676,8 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
return GetSurface(SurfaceParams::CreateForTexture(config));
}
-SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
- bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport) {
+SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool using_color_fb,
+ bool using_depth_fb) {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
// TODO(bunnei): This is hard corded to use just the first render buffer
@@ -680,12 +762,12 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
// If use_accurate_framebuffers is enabled, always load from memory
FlushSurface(surface);
UnregisterSurface(surface);
- } else if (surface->GetSurfaceParams() != params) {
- // If surface parameters changed, recreate the surface from the old one
- return RecreateSurface(surface, params);
- } else {
+ } else if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
// Use the cached surface as-is
return surface;
+ } else {
+ // If surface parameters changed, recreate the surface from the old one
+ return RecreateSurface(surface, params);
}
}
@@ -751,10 +833,12 @@ void RasterizerCacheOpenGL::FlushRegion(Tegra::GPUVAddr /*addr*/, size_t /*size*
}
void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, size_t size) {
- for (const auto& pair : surface_cache) {
- const auto& surface{pair.second};
+ for (auto iter = surface_cache.cbegin(); iter != surface_cache.cend();) {
+ const auto& surface{iter->second};
const auto& params{surface->GetSurfaceParams()};
+ ++iter;
+
if (params.IsOverlappingRegion(addr, size)) {
UnregisterSurface(surface);
}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 4e1e18d9c..36a41522b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -9,6 +9,7 @@
#include <memory>
#include <vector>
#include <boost/icl/interval_map.hpp>
+
#include "common/common_types.h"
#include "common/math_util.h"
#include "video_core/engines/maxwell_3d.h"
@@ -22,43 +23,56 @@ using PageMap = boost::icl::interval_map<u64, int>;
struct SurfaceParams {
enum class PixelFormat {
- ABGR8 = 0,
- B5G6R5 = 1,
- A2B10G10R10 = 2,
- A1B5G5R5 = 3,
- R8 = 4,
- RGBA16F = 5,
- R11FG11FB10F = 6,
- RGBA32UI = 7,
- DXT1 = 8,
- DXT23 = 9,
- DXT45 = 10,
- DXN1 = 11, // This is also known as BC4
- BC7U = 12,
- ASTC_2D_4X4 = 13,
- G8R8 = 14,
- BGRA8 = 15,
- RGBA32F = 16,
- RG32F = 17,
- R32F = 18,
- R16F = 19,
- R16UNORM = 20,
- RG16 = 21,
- RG16F = 22,
- RG16UI = 23,
- RG16I = 24,
- RG16S = 25,
- RGB32F = 26,
- SRGBA8 = 27,
+ ABGR8U = 0,
+ ABGR8S = 1,
+ B5G6R5 = 2,
+ A2B10G10R10 = 3,
+ A1B5G5R5 = 4,
+ R8 = 5,
+ R8UI = 6,
+ RGBA16F = 7,
+ RGBA16U = 8,
+ RGBA16UI = 9,
+ R11FG11FB10F = 10,
+ RGBA32UI = 11,
+ DXT1 = 12,
+ DXT23 = 13,
+ DXT45 = 14,
+ DXN1 = 15, // This is also known as BC4
+ DXN2UNORM = 16,
+ DXN2SNORM = 17,
+ BC7U = 18,
+ ASTC_2D_4X4 = 19,
+ G8R8 = 20,
+ BGRA8 = 21,
+ RGBA32F = 22,
+ RG32F = 23,
+ R32F = 24,
+ R16F = 25,
+ R16UNORM = 26,
+ R16S = 27,
+ R16UI = 28,
+ R16I = 29,
+ RG16 = 30,
+ RG16F = 31,
+ RG16UI = 32,
+ RG16I = 33,
+ RG16S = 34,
+ RGB32F = 35,
+ SRGBA8 = 36,
+ RG8U = 37,
+ RG8S = 38,
+ RG32UI = 39,
+ R32UI = 40,
MaxColorFormat,
// DepthStencil formats
- Z24S8 = 28,
- S8Z24 = 29,
- Z32F = 30,
- Z16 = 31,
- Z32FS8 = 32,
+ Z24S8 = 41,
+ S8Z24 = 42,
+ Z32F = 43,
+ Z16 = 44,
+ Z32FS8 = 45,
MaxDepthStencilFormat,
@@ -96,18 +110,24 @@ struct SurfaceParams {
return 0;
constexpr std::array<u32, MaxPixelFormat> compression_factor_table = {{
- 1, // ABGR8
+ 1, // ABGR8U
+ 1, // ABGR8S
1, // B5G6R5
1, // A2B10G10R10
1, // A1B5G5R5
1, // R8
+ 1, // R8UI
1, // RGBA16F
+ 1, // RGBA16U
+ 1, // RGBA16UI
1, // R11FG11FB10F
1, // RGBA32UI
4, // DXT1
4, // DXT23
4, // DXT45
4, // DXN1
+ 4, // DXN2UNORM
+ 4, // DXN2SNORM
4, // BC7U
4, // ASTC_2D_4X4
1, // G8R8
@@ -117,6 +137,9 @@ struct SurfaceParams {
1, // R32F
1, // R16F
1, // R16UNORM
+ 1, // R16S
+ 1, // R16UI
+ 1, // R16I
1, // RG16
1, // RG16F
1, // RG16UI
@@ -124,6 +147,10 @@ struct SurfaceParams {
1, // RG16S
1, // RGB32F
1, // SRGBA8
+ 1, // RG8U
+ 1, // RG8S
+ 1, // RG32UI
+ 1, // R32UI
1, // Z24S8
1, // S8Z24
1, // Z32F
@@ -140,18 +167,24 @@ struct SurfaceParams {
return 0;
constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
- 32, // ABGR8
+ 32, // ABGR8U
+ 32, // ABGR8S
16, // B5G6R5
32, // A2B10G10R10
16, // A1B5G5R5
8, // R8
+ 8, // R8UI
64, // RGBA16F
+ 64, // RGBA16U
+ 64, // RGBA16UI
32, // R11FG11FB10F
128, // RGBA32UI
64, // DXT1
128, // DXT23
128, // DXT45
64, // DXN1
+ 128, // DXN2UNORM
+ 128, // DXN2SNORM
128, // BC7U
32, // ASTC_2D_4X4
16, // G8R8
@@ -161,6 +194,9 @@ struct SurfaceParams {
32, // R32F
16, // R16F
16, // R16UNORM
+ 16, // R16S
+ 16, // R16UI
+ 16, // R16I
32, // RG16
32, // RG16F
32, // RG16UI
@@ -168,6 +204,10 @@ struct SurfaceParams {
32, // RG16S
96, // RGB32F
32, // SRGBA8
+ 16, // RG8U
+ 16, // RG8S
+ 64, // RG32UI
+ 32, // R32UI
32, // Z24S8
32, // S8Z24
32, // Z32F
@@ -203,26 +243,37 @@ struct SurfaceParams {
static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
switch (format) {
+ // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the
+ // gamma.
case Tegra::RenderTargetFormat::RGBA8_SRGB:
- return PixelFormat::SRGBA8;
case Tegra::RenderTargetFormat::RGBA8_UNORM:
- return PixelFormat::ABGR8;
+ return PixelFormat::ABGR8U;
+ case Tegra::RenderTargetFormat::RGBA8_SNORM:
+ return PixelFormat::ABGR8S;
case Tegra::RenderTargetFormat::BGRA8_UNORM:
return PixelFormat::BGRA8;
case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
return PixelFormat::A2B10G10R10;
case Tegra::RenderTargetFormat::RGBA16_FLOAT:
return PixelFormat::RGBA16F;
+ case Tegra::RenderTargetFormat::RGBA16_UNORM:
+ return PixelFormat::RGBA16U;
+ case Tegra::RenderTargetFormat::RGBA16_UINT:
+ return PixelFormat::RGBA16UI;
case Tegra::RenderTargetFormat::RGBA32_FLOAT:
return PixelFormat::RGBA32F;
case Tegra::RenderTargetFormat::RG32_FLOAT:
return PixelFormat::RG32F;
case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
return PixelFormat::R11FG11FB10F;
+ case Tegra::RenderTargetFormat::B5G6R5_UNORM:
+ return PixelFormat::B5G6R5;
case Tegra::RenderTargetFormat::RGBA32_UINT:
return PixelFormat::RGBA32UI;
case Tegra::RenderTargetFormat::R8_UNORM:
return PixelFormat::R8;
+ case Tegra::RenderTargetFormat::R8_UINT:
+ return PixelFormat::R8UI;
case Tegra::RenderTargetFormat::RG16_FLOAT:
return PixelFormat::RG16F;
case Tegra::RenderTargetFormat::RG16_UINT:
@@ -233,10 +284,26 @@ struct SurfaceParams {
return PixelFormat::RG16;
case Tegra::RenderTargetFormat::RG16_SNORM:
return PixelFormat::RG16S;
+ case Tegra::RenderTargetFormat::RG8_UNORM:
+ return PixelFormat::RG8U;
+ case Tegra::RenderTargetFormat::RG8_SNORM:
+ return PixelFormat::RG8S;
case Tegra::RenderTargetFormat::R16_FLOAT:
return PixelFormat::R16F;
+ case Tegra::RenderTargetFormat::R16_UNORM:
+ return PixelFormat::R16UNORM;
+ case Tegra::RenderTargetFormat::R16_SNORM:
+ return PixelFormat::R16S;
+ case Tegra::RenderTargetFormat::R16_UINT:
+ return PixelFormat::R16UI;
+ case Tegra::RenderTargetFormat::R16_SINT:
+ return PixelFormat::R16I;
case Tegra::RenderTargetFormat::R32_FLOAT:
return PixelFormat::R32F;
+ case Tegra::RenderTargetFormat::R32_UINT:
+ return PixelFormat::R32UI;
+ case Tegra::RenderTargetFormat::RG32_UINT:
+ return PixelFormat::RG32UI;
default:
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
UNREACHABLE();
@@ -248,7 +315,15 @@ struct SurfaceParams {
// TODO(Subv): Properly implement this
switch (format) {
case Tegra::Texture::TextureFormat::A8R8G8B8:
- return PixelFormat::ABGR8;
+ switch (component_type) {
+ case Tegra::Texture::ComponentType::UNORM:
+ return PixelFormat::ABGR8U;
+ case Tegra::Texture::ComponentType::SNORM:
+ return PixelFormat::ABGR8S;
+ }
+ LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
+ static_cast<u32>(component_type));
+ UNREACHABLE();
case Tegra::Texture::TextureFormat::B5G6R5:
return PixelFormat::B5G6R5;
case Tegra::Texture::TextureFormat::A2B10G10R10:
@@ -256,7 +331,15 @@ struct SurfaceParams {
case Tegra::Texture::TextureFormat::A1B5G5R5:
return PixelFormat::A1B5G5R5;
case Tegra::Texture::TextureFormat::R8:
- return PixelFormat::R8;
+ switch (component_type) {
+ case Tegra::Texture::ComponentType::UNORM:
+ return PixelFormat::R8;
+ case Tegra::Texture::ComponentType::UINT:
+ return PixelFormat::R8UI;
+ }
+ LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
+ static_cast<u32>(component_type));
+ UNREACHABLE();
case Tegra::Texture::TextureFormat::G8R8:
return PixelFormat::G8R8;
case Tegra::Texture::TextureFormat::R16_G16_B16_A16:
@@ -274,7 +357,15 @@ struct SurfaceParams {
static_cast<u32>(component_type));
UNREACHABLE();
case Tegra::Texture::TextureFormat::R32_G32:
- return PixelFormat::RG32F;
+ switch (component_type) {
+ case Tegra::Texture::ComponentType::FLOAT:
+ return PixelFormat::RG32F;
+ case Tegra::Texture::ComponentType::UINT:
+ return PixelFormat::RG32UI;
+ }
+ LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
+ static_cast<u32>(component_type));
+ UNREACHABLE();
case Tegra::Texture::TextureFormat::R32_G32_B32:
return PixelFormat::RGB32F;
case Tegra::Texture::TextureFormat::R16:
@@ -283,12 +374,26 @@ struct SurfaceParams {
return PixelFormat::R16F;
case Tegra::Texture::ComponentType::UNORM:
return PixelFormat::R16UNORM;
+ case Tegra::Texture::ComponentType::SNORM:
+ return PixelFormat::R16S;
+ case Tegra::Texture::ComponentType::UINT:
+ return PixelFormat::R16UI;
+ case Tegra::Texture::ComponentType::SINT:
+ return PixelFormat::R16I;
}
LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
static_cast<u32>(component_type));
UNREACHABLE();
case Tegra::Texture::TextureFormat::R32:
- return PixelFormat::R32F;
+ switch (component_type) {
+ case Tegra::Texture::ComponentType::FLOAT:
+ return PixelFormat::R32F;
+ case Tegra::Texture::ComponentType::UINT:
+ return PixelFormat::R32UI;
+ }
+ LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
+ static_cast<u32>(component_type));
+ UNREACHABLE();
case Tegra::Texture::TextureFormat::ZF32:
return PixelFormat::Z32F;
case Tegra::Texture::TextureFormat::Z24S8:
@@ -301,6 +406,16 @@ struct SurfaceParams {
return PixelFormat::DXT45;
case Tegra::Texture::TextureFormat::DXN1:
return PixelFormat::DXN1;
+ case Tegra::Texture::TextureFormat::DXN2:
+ switch (component_type) {
+ case Tegra::Texture::ComponentType::UNORM:
+ return PixelFormat::DXN2UNORM;
+ case Tegra::Texture::ComponentType::SNORM:
+ return PixelFormat::DXN2SNORM;
+ }
+ LOG_CRITICAL(HW_GPU, "Unimplemented component_type={}",
+ static_cast<u32>(component_type));
+ UNREACHABLE();
case Tegra::Texture::TextureFormat::BC7U:
return PixelFormat::BC7U;
case Tegra::Texture::TextureFormat::ASTC_2D_4X4:
@@ -328,89 +443,6 @@ struct SurfaceParams {
}
}
- static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) {
- // TODO(Subv): Properly implement this
- switch (format) {
- case PixelFormat::ABGR8:
- case PixelFormat::SRGBA8:
- return Tegra::Texture::TextureFormat::A8R8G8B8;
- case PixelFormat::B5G6R5:
- return Tegra::Texture::TextureFormat::B5G6R5;
- case PixelFormat::A2B10G10R10:
- return Tegra::Texture::TextureFormat::A2B10G10R10;
- case PixelFormat::A1B5G5R5:
- return Tegra::Texture::TextureFormat::A1B5G5R5;
- case PixelFormat::R8:
- return Tegra::Texture::TextureFormat::R8;
- case PixelFormat::G8R8:
- return Tegra::Texture::TextureFormat::G8R8;
- case PixelFormat::RGBA16F:
- return Tegra::Texture::TextureFormat::R16_G16_B16_A16;
- case PixelFormat::R11FG11FB10F:
- return Tegra::Texture::TextureFormat::BF10GF11RF11;
- case PixelFormat::RGBA32UI:
- return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
- case PixelFormat::DXT1:
- return Tegra::Texture::TextureFormat::DXT1;
- case PixelFormat::DXT23:
- return Tegra::Texture::TextureFormat::DXT23;
- case PixelFormat::DXT45:
- return Tegra::Texture::TextureFormat::DXT45;
- case PixelFormat::DXN1:
- return Tegra::Texture::TextureFormat::DXN1;
- case PixelFormat::BC7U:
- return Tegra::Texture::TextureFormat::BC7U;
- case PixelFormat::ASTC_2D_4X4:
- return Tegra::Texture::TextureFormat::ASTC_2D_4X4;
- case PixelFormat::BGRA8:
- // TODO(bunnei): This is fine for unswizzling (since we just need the right component
- // sizes), but could be a bug if we used this function in different ways.
- return Tegra::Texture::TextureFormat::A8R8G8B8;
- case PixelFormat::RGBA32F:
- return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
- case PixelFormat::RGB32F:
- return Tegra::Texture::TextureFormat::R32_G32_B32;
- case PixelFormat::RG32F:
- return Tegra::Texture::TextureFormat::R32_G32;
- case PixelFormat::R32F:
- return Tegra::Texture::TextureFormat::R32;
- case PixelFormat::R16F:
- case PixelFormat::R16UNORM:
- return Tegra::Texture::TextureFormat::R16;
- case PixelFormat::Z32F:
- return Tegra::Texture::TextureFormat::ZF32;
- case PixelFormat::Z24S8:
- return Tegra::Texture::TextureFormat::Z24S8;
- case PixelFormat::RG16F:
- case PixelFormat::RG16:
- case PixelFormat::RG16UI:
- case PixelFormat::RG16I:
- case PixelFormat::RG16S:
- return Tegra::Texture::TextureFormat::R16_G16;
- default:
- LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
- UNREACHABLE();
- }
- }
-
- static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) {
- switch (format) {
- case PixelFormat::S8Z24:
- return Tegra::DepthFormat::S8_Z24_UNORM;
- case PixelFormat::Z24S8:
- return Tegra::DepthFormat::Z24_S8_UNORM;
- case PixelFormat::Z32F:
- return Tegra::DepthFormat::Z32_FLOAT;
- case PixelFormat::Z16:
- return Tegra::DepthFormat::Z16_UNORM;
- case PixelFormat::Z32FS8:
- return Tegra::DepthFormat::Z32_S8_X24_FLOAT;
- default:
- LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
- UNREACHABLE();
- }
- }
-
static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
// TODO(Subv): Implement more component types
switch (type) {
@@ -439,8 +471,15 @@ struct SurfaceParams {
case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
case Tegra::RenderTargetFormat::R8_UNORM:
case Tegra::RenderTargetFormat::RG16_UNORM:
+ case Tegra::RenderTargetFormat::R16_UNORM:
+ case Tegra::RenderTargetFormat::B5G6R5_UNORM:
+ case Tegra::RenderTargetFormat::RG8_UNORM:
+ case Tegra::RenderTargetFormat::RGBA16_UNORM:
return ComponentType::UNorm;
+ case Tegra::RenderTargetFormat::RGBA8_SNORM:
case Tegra::RenderTargetFormat::RG16_SNORM:
+ case Tegra::RenderTargetFormat::R16_SNORM:
+ case Tegra::RenderTargetFormat::RG8_SNORM:
return ComponentType::SNorm;
case Tegra::RenderTargetFormat::RGBA16_FLOAT:
case Tegra::RenderTargetFormat::R11G11B10_FLOAT:
@@ -451,9 +490,15 @@ struct SurfaceParams {
case Tegra::RenderTargetFormat::R32_FLOAT:
return ComponentType::Float;
case Tegra::RenderTargetFormat::RGBA32_UINT:
+ case Tegra::RenderTargetFormat::RGBA16_UINT:
case Tegra::RenderTargetFormat::RG16_UINT:
+ case Tegra::RenderTargetFormat::R8_UINT:
+ case Tegra::RenderTargetFormat::R16_UINT:
+ case Tegra::RenderTargetFormat::RG32_UINT:
+ case Tegra::RenderTargetFormat::R32_UINT:
return ComponentType::UInt;
case Tegra::RenderTargetFormat::RG16_SINT:
+ case Tegra::RenderTargetFormat::R16_SINT:
return ComponentType::SInt;
default:
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
@@ -464,7 +509,7 @@ struct SurfaceParams {
static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
switch (format) {
case Tegra::FramebufferConfig::PixelFormat::ABGR8:
- return PixelFormat::ABGR8;
+ return PixelFormat::ABGR8U;
default:
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
UNREACHABLE();
@@ -546,6 +591,12 @@ struct SurfaceParams {
return !operator==(other);
}
+ /// Checks if surfaces are compatible for caching
+ bool IsCompatibleSurface(const SurfaceParams& other) const {
+ return std::tie(pixel_format, type, cache_width, cache_height) ==
+ std::tie(other.pixel_format, other.type, other.cache_width, other.cache_height);
+ }
+
Tegra::GPUVAddr addr;
bool is_tiled;
u32 block_height;
@@ -556,6 +607,10 @@ struct SurfaceParams {
u32 height;
u32 unaligned_height;
size_t size_in_bytes;
+
+ // Parameters used for caching only
+ u32 cache_width;
+ u32 cache_height;
};
class CachedSurface final {
@@ -600,8 +655,7 @@ public:
Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config);
/// Get the color and depth surfaces based on the framebuffer configuration
- SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
- const MathUtil::Rectangle<s32>& viewport);
+ SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb);
/// Flushes the surface to Switch memory
void FlushSurface(const Surface& surface);
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index e3217db81..6834d7085 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -141,6 +141,15 @@ private:
ExitMethod jmp = Scan(target, end, labels);
return exit_method = ParallelExit(no_jmp, jmp);
}
+ case OpCode::Id::SSY: {
+ // The SSY instruction uses a similar encoding as the BRA instruction.
+ ASSERT_MSG(instr.bra.constant_buffer == 0,
+ "Constant buffer SSY is not supported");
+ u32 target = offset + instr.bra.GetBranchTarget();
+ labels.insert(target);
+ // Continue scanning for an exit method.
+ break;
+ }
}
}
}
@@ -347,9 +356,14 @@ public:
* @param reg The register to use as the source value.
*/
void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) {
- std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem);
+ std::string dest = GetOutputAttribute(attribute);
std::string src = GetRegisterAsFloat(reg);
- shader.AddLine(dest + " = " + src + ';');
+
+ if (!dest.empty()) {
+ // Can happen with unknown/unimplemented output attributes, in which case we ignore the
+ // instruction for now.
+ shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';');
+ }
}
/// Generates code representing a uniform (C buffer) register, interpreted as the input type.
@@ -362,6 +376,8 @@ public:
return value;
} else if (type == GLSLRegister::Type::Integer) {
return "floatBitsToInt(" + value + ')';
+ } else if (type == GLSLRegister::Type::UnsignedInteger) {
+ return "floatBitsToUint(" + value + ')';
} else {
UNREACHABLE();
}
@@ -507,6 +523,8 @@ private:
/// Build the GLSL register list.
void BuildRegisterList() {
+ regs.reserve(Register::NumRegisters);
+
for (size_t index = 0; index < Register::NumRegisters; ++index) {
regs.emplace_back(index, suffix);
}
@@ -526,14 +544,17 @@ private:
default:
const u32 index{static_cast<u32>(attribute) -
static_cast<u32>(Attribute::Index::Attribute_0)};
- if (attribute >= Attribute::Index::Attribute_0) {
+ if (attribute >= Attribute::Index::Attribute_0 &&
+ attribute <= Attribute::Index::Attribute_31) {
declr_input_attribute.insert(attribute);
return "input_attribute_" + std::to_string(index);
}
- LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", index);
+ LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", static_cast<u32>(attribute));
UNREACHABLE();
}
+
+ return "vec4(0, 0, 0, 0)";
}
/// Generates code representing an output attribute register.
@@ -551,6 +572,7 @@ private:
LOG_CRITICAL(HW_GPU, "Unhandled output attribute: {}", index);
UNREACHABLE();
+ return {};
}
}
@@ -602,12 +624,12 @@ private:
/// Generates code representing a 19-bit immediate value
static std::string GetImmediate19(const Instruction& instr) {
- return std::to_string(instr.alu.GetImm20_19());
+ return fmt::format("uintBitsToFloat({})", instr.alu.GetImm20_19());
}
/// Generates code representing a 32-bit immediate value
static std::string GetImmediate32(const Instruction& instr) {
- return std::to_string(instr.alu.GetImm20_32());
+ return fmt::format("uintBitsToFloat({})", instr.alu.GetImm20_32());
}
/// Generates code representing a texture sampler.
@@ -650,16 +672,17 @@ private:
* @param instr Instruction to generate the if condition for.
* @returns string containing the predicate condition.
*/
- std::string GetPredicateCondition(u64 index, bool negate) const {
+ std::string GetPredicateCondition(u64 index, bool negate) {
using Tegra::Shader::Pred;
std::string variable;
// Index 7 is used as an 'Always True' condition.
- if (index == static_cast<u64>(Pred::UnusedIndex))
+ if (index == static_cast<u64>(Pred::UnusedIndex)) {
variable = "true";
- else
+ } else {
variable = 'p' + std::to_string(index) + '_' + suffix;
-
+ declr_predicates.insert(variable);
+ }
if (negate) {
return "!(" + variable + ')';
}
@@ -818,7 +841,11 @@ private:
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
"NeverExecute predicate not implemented");
- if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
+ // Some instructions (like SSY) don't have a predicate field, they are always
+ // unconditionally executed.
+ bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->GetId());
+
+ if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
shader.AddLine("if (" +
GetPredicateCondition(instr.pred.pred_index, instr.negate_pred != 0) +
')');
@@ -1605,6 +1632,99 @@ private:
}
break;
}
+ case OpCode::Type::Xmad: {
+ ASSERT_MSG(!instr.xmad.sign_a, "Unimplemented");
+ ASSERT_MSG(!instr.xmad.sign_b, "Unimplemented");
+
+ std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)};
+ std::string op_b;
+ std::string op_c;
+
+ // TODO(bunnei): Needs to be fixed once op_a or op_b is signed
+ ASSERT_MSG(instr.xmad.sign_a == instr.xmad.sign_b, "Unimplemented");
+ const bool is_signed{instr.xmad.sign_a == 1};
+
+ bool is_merge{};
+ switch (opcode->GetId()) {
+ case OpCode::Id::XMAD_CR: {
+ is_merge = instr.xmad.merge_56;
+ op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
+ instr.xmad.sign_b ? GLSLRegister::Type::Integer
+ : GLSLRegister::Type::UnsignedInteger);
+ op_c += regs.GetRegisterAsInteger(instr.gpr39, 0, is_signed);
+ break;
+ }
+ case OpCode::Id::XMAD_RR: {
+ is_merge = instr.xmad.merge_37;
+ op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.xmad.sign_b);
+ op_c += regs.GetRegisterAsInteger(instr.gpr39, 0, is_signed);
+ break;
+ }
+ case OpCode::Id::XMAD_RC: {
+ op_b += regs.GetRegisterAsInteger(instr.gpr39, 0, instr.xmad.sign_b);
+ op_c += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
+ is_signed ? GLSLRegister::Type::Integer
+ : GLSLRegister::Type::UnsignedInteger);
+ break;
+ }
+ case OpCode::Id::XMAD_IMM: {
+ is_merge = instr.xmad.merge_37;
+ op_b += std::to_string(instr.xmad.imm20_16);
+ op_c += regs.GetRegisterAsInteger(instr.gpr39, 0, is_signed);
+ break;
+ }
+ default: {
+ LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->GetName());
+ UNREACHABLE();
+ }
+ }
+
+ // TODO(bunnei): Ensure this is right with signed operands
+ if (instr.xmad.high_a) {
+ op_a = "((" + op_a + ") >> 16)";
+ } else {
+ op_a = "((" + op_a + ") & 0xFFFF)";
+ }
+
+ std::string src2 = '(' + op_b + ')'; // Preserve original source 2
+ if (instr.xmad.high_b) {
+ op_b = '(' + src2 + " >> 16)";
+ } else {
+ op_b = '(' + src2 + " & 0xFFFF)";
+ }
+
+ std::string product = '(' + op_a + " * " + op_b + ')';
+ if (instr.xmad.product_shift_left) {
+ product = '(' + product + " << 16)";
+ }
+
+ switch (instr.xmad.mode) {
+ case Tegra::Shader::XmadMode::None:
+ break;
+ case Tegra::Shader::XmadMode::CLo:
+ op_c = "((" + op_c + ") & 0xFFFF)";
+ break;
+ case Tegra::Shader::XmadMode::CHi:
+ op_c = "((" + op_c + ") >> 16)";
+ break;
+ case Tegra::Shader::XmadMode::CBcc:
+ op_c = "((" + op_c + ") + (" + src2 + "<< 16))";
+ break;
+ default: {
+ LOG_CRITICAL(HW_GPU, "Unhandled XMAD mode: {}",
+ static_cast<u32>(instr.xmad.mode.Value()));
+ UNREACHABLE();
+ }
+ }
+
+ std::string sum{'(' + product + " + " + op_c + ')'};
+ if (is_merge) {
+ sum = "((" + sum + " & 0xFFFF) | (" + src2 + "<< 16))";
+ }
+
+ regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1);
+ break;
+ }
default: {
switch (opcode->GetId()) {
case OpCode::Id::EXIT: {
@@ -1642,7 +1762,15 @@ private:
}
case OpCode::Id::KIL: {
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
+
+ // Enclose "discard" in a conditional, so that GLSL compilation does not complain
+ // about unexecuted instructions that may follow this.
+ shader.AddLine("if (true) {");
+ ++shader.scope;
shader.AddLine("discard;");
+ --shader.scope;
+ shader.AddLine("}");
+
break;
}
case OpCode::Id::BRA: {
@@ -1658,16 +1786,25 @@ private:
break;
}
case OpCode::Id::SSY: {
- // The SSY opcode tells the GPU where to re-converge divergent execution paths, we
- // can ignore this when generating GLSL code.
+ // The SSY opcode tells the GPU where to re-converge divergent execution paths, it
+ // sets the target of the jump that the SYNC instruction will make. The SSY opcode
+ // has a similar structure to the BRA opcode.
+ ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported");
+
+ u32 target = offset + instr.bra.GetBranchTarget();
+ shader.AddLine("ssy_target = " + std::to_string(target) + "u;");
break;
}
- case OpCode::Id::SYNC:
+ case OpCode::Id::SYNC: {
+ // The SYNC opcode jumps to the address previously set by the SSY opcode
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
+ shader.AddLine("{ jmp_to = ssy_target; break; }");
+ break;
+ }
case OpCode::Id::DEPBAR: {
- // TODO(Subv): Find out if we actually have to care about these instructions or if
+ // TODO(Subv): Find out if we actually have to care about this instruction or if
// the GLSL compiler takes care of that for us.
- LOG_WARNING(HW_GPU, "DEPBAR/SYNC instruction is stubbed");
+ LOG_WARNING(HW_GPU, "DEPBAR instruction is stubbed");
break;
}
default: {
@@ -1681,7 +1818,7 @@ private:
}
// Close the predicate condition scope.
- if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
+ if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
--shader.scope;
shader.AddLine('}');
}
@@ -1732,6 +1869,7 @@ private:
} else {
labels.insert(subroutine.begin);
shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
+ shader.AddLine("uint ssy_target = 0u;");
shader.AddLine("while (true) {");
++shader.scope;
@@ -1747,7 +1885,7 @@ private:
u32 compile_end = CompileRange(label, next_label);
if (compile_end > next_label && compile_end != PROGRAM_END) {
// This happens only when there is a label inside a IF/LOOP block
- shader.AddLine("{ jmp_to = " + std::to_string(compile_end) + "u; break; }");
+ shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }");
labels.emplace(compile_end);
}
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 68bacd4c5..1d1975179 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -203,21 +203,6 @@ void OpenGLState::Apply() const {
}
}
- // Constbuffers
- for (std::size_t stage = 0; stage < draw.const_buffers.size(); ++stage) {
- for (std::size_t buffer_id = 0; buffer_id < draw.const_buffers[stage].size(); ++buffer_id) {
- const auto& current = cur_state.draw.const_buffers[stage][buffer_id];
- const auto& new_state = draw.const_buffers[stage][buffer_id];
-
- if (current.enabled != new_state.enabled || current.bindpoint != new_state.bindpoint ||
- current.ssbo != new_state.ssbo) {
- if (new_state.enabled) {
- glBindBufferBase(GL_UNIFORM_BUFFER, new_state.bindpoint, new_state.ssbo);
- }
- }
- }
- }
-
// Framebuffer
if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 24b1d956b..bdb02ba25 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -7,6 +7,10 @@
#include <array>
#include <glad/glad.h>
+#include "video_core/engines/maxwell_3d.h"
+
+using Regs = Tegra::Engines::Maxwell3D::Regs;
+
namespace TextureUnits {
struct TextureUnit {
@@ -115,12 +119,6 @@ public:
GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING
GLuint shader_program; // GL_CURRENT_PROGRAM
GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
- struct ConstBufferConfig {
- bool enabled = false;
- GLuint bindpoint;
- GLuint ssbo;
- };
- std::array<std::array<ConstBufferConfig, 16>, 5> const_buffers{};
} draw;
struct {
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index a2713e9f0..03a8ed8b7 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -9,174 +9,91 @@
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
-class OrphanBuffer : public OGLStreamBuffer {
-public:
- explicit OrphanBuffer(GLenum target) : OGLStreamBuffer(target) {}
- ~OrphanBuffer() override;
-
-private:
- void Create(size_t size, size_t sync_subdivide) override;
- void Release() override;
-
- std::pair<u8*, GLintptr> Map(size_t size, size_t alignment) override;
- void Unmap() override;
-
- std::vector<u8> data;
-};
-
-class StorageBuffer : public OGLStreamBuffer {
-public:
- explicit StorageBuffer(GLenum target) : OGLStreamBuffer(target) {}
- ~StorageBuffer() override;
-
-private:
- void Create(size_t size, size_t sync_subdivide) override;
- void Release() override;
-
- std::pair<u8*, GLintptr> Map(size_t size, size_t alignment) override;
- void Unmap() override;
-
- struct Fence {
- OGLSync sync;
- size_t offset;
- };
- std::deque<Fence> head;
- std::deque<Fence> tail;
-
- u8* mapped_ptr;
-};
-
-OGLStreamBuffer::OGLStreamBuffer(GLenum target) {
- gl_target = target;
-}
-
-GLuint OGLStreamBuffer::GetHandle() const {
- return gl_buffer.handle;
-}
+OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent)
+ : gl_target(target), buffer_size(size) {
+ gl_buffer.Create();
+ glBindBuffer(gl_target, gl_buffer.handle);
-std::unique_ptr<OGLStreamBuffer> OGLStreamBuffer::MakeBuffer(bool storage_buffer, GLenum target) {
- if (storage_buffer) {
- return std::make_unique<StorageBuffer>(target);
+ GLsizeiptr allocate_size = size;
+ if (target == GL_ARRAY_BUFFER) {
+ // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer
+ // read position is near the end and is an out-of-bound access to the vertex buffer. This is
+ // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the
+ // vertex array. Doubling the allocation size for the vertex buffer seems to avoid the
+ // crash.
+ allocate_size *= 2;
}
- return std::make_unique<OrphanBuffer>(target);
-}
-OrphanBuffer::~OrphanBuffer() {
- Release();
+ if (GLAD_GL_ARB_buffer_storage) {
+ persistent = true;
+ coherent = prefer_coherent;
+ GLbitfield flags =
+ GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0);
+ glBufferStorage(gl_target, allocate_size, nullptr, flags);
+ mapped_ptr = static_cast<u8*>(glMapBufferRange(
+ gl_target, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)));
+ } else {
+ glBufferData(gl_target, allocate_size, nullptr, GL_STREAM_DRAW);
+ }
}
-void OrphanBuffer::Create(size_t size, size_t /*sync_subdivide*/) {
- buffer_pos = 0;
- buffer_size = size;
- data.resize(buffer_size);
-
- if (gl_buffer.handle == 0) {
- gl_buffer.Create();
+OGLStreamBuffer::~OGLStreamBuffer() {
+ if (persistent) {
glBindBuffer(gl_target, gl_buffer.handle);
+ glUnmapBuffer(gl_target);
}
-
- glBufferData(gl_target, static_cast<GLsizeiptr>(buffer_size), nullptr, GL_STREAM_DRAW);
-}
-
-void OrphanBuffer::Release() {
gl_buffer.Release();
}
-std::pair<u8*, GLintptr> OrphanBuffer::Map(size_t size, size_t alignment) {
- buffer_pos = Common::AlignUp(buffer_pos, alignment);
-
- if (buffer_pos + size > buffer_size) {
- Create(std::max(buffer_size, size), 0);
- }
-
- mapped_size = size;
- return std::make_pair(&data[buffer_pos], static_cast<GLintptr>(buffer_pos));
-}
-
-void OrphanBuffer::Unmap() {
- glBufferSubData(gl_target, static_cast<GLintptr>(buffer_pos),
- static_cast<GLsizeiptr>(mapped_size), &data[buffer_pos]);
- buffer_pos += mapped_size;
-}
-
-StorageBuffer::~StorageBuffer() {
- Release();
+GLuint OGLStreamBuffer::GetHandle() const {
+ return gl_buffer.handle;
}
-void StorageBuffer::Create(size_t size, size_t sync_subdivide) {
- if (gl_buffer.handle != 0)
- return;
-
- buffer_pos = 0;
- buffer_size = size;
- buffer_sync_subdivide = std::max<size_t>(sync_subdivide, 1);
-
- gl_buffer.Create();
- glBindBuffer(gl_target, gl_buffer.handle);
-
- glBufferStorage(gl_target, static_cast<GLsizeiptr>(buffer_size), nullptr,
- GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
- mapped_ptr = reinterpret_cast<u8*>(
- glMapBufferRange(gl_target, 0, static_cast<GLsizeiptr>(buffer_size),
- GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_FLUSH_EXPLICIT_BIT));
+GLsizeiptr OGLStreamBuffer::GetSize() const {
+ return buffer_size;
}
-void StorageBuffer::Release() {
- if (gl_buffer.handle == 0)
- return;
-
- glUnmapBuffer(gl_target);
-
- gl_buffer.Release();
- head.clear();
- tail.clear();
-}
-
-std::pair<u8*, GLintptr> StorageBuffer::Map(size_t size, size_t alignment) {
+std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr alignment) {
ASSERT(size <= buffer_size);
+ ASSERT(alignment <= buffer_size);
+ mapped_size = size;
- OGLSync sync;
-
- buffer_pos = Common::AlignUp(buffer_pos, alignment);
- size_t effective_offset = Common::AlignDown(buffer_pos, buffer_sync_subdivide);
-
- if (!head.empty() &&
- (effective_offset > head.back().offset || buffer_pos + size > buffer_size)) {
- ASSERT(head.back().sync.handle == 0);
- head.back().sync.Create();
+ if (alignment > 0) {
+ buffer_pos = Common::AlignUp<size_t>(buffer_pos, alignment);
}
+ bool invalidate = false;
if (buffer_pos + size > buffer_size) {
- if (!tail.empty()) {
- std::swap(sync, tail.back().sync);
- tail.clear();
- }
- std::swap(tail, head);
buffer_pos = 0;
- effective_offset = 0;
- }
+ invalidate = true;
- while (!tail.empty() && buffer_pos + size > tail.front().offset) {
- std::swap(sync, tail.front().sync);
- tail.pop_front();
+ if (persistent) {
+ glUnmapBuffer(gl_target);
+ }
}
- if (sync.handle != 0) {
- glClientWaitSync(sync.handle, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
- sync.Release();
+ if (invalidate | !persistent) {
+ GLbitfield flags = GL_MAP_WRITE_BIT | (persistent ? GL_MAP_PERSISTENT_BIT : 0) |
+ (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) |
+ (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT);
+ mapped_ptr = static_cast<u8*>(
+ glMapBufferRange(gl_target, buffer_pos, buffer_size - buffer_pos, flags));
+ mapped_offset = buffer_pos;
}
- if (head.empty() || effective_offset > head.back().offset) {
- head.emplace_back();
- head.back().offset = effective_offset;
+ return std::make_tuple(mapped_ptr + buffer_pos - mapped_offset, buffer_pos, invalidate);
+}
+
+void OGLStreamBuffer::Unmap(GLsizeiptr size) {
+ ASSERT(size <= mapped_size);
+
+ if (!coherent && size > 0) {
+ glFlushMappedBufferRange(gl_target, buffer_pos - mapped_offset, size);
}
- mapped_size = size;
- return std::make_pair(&mapped_ptr[buffer_pos], static_cast<GLintptr>(buffer_pos));
-}
+ if (!persistent) {
+ glUnmapBuffer(gl_target);
+ }
-void StorageBuffer::Unmap() {
- glFlushMappedBufferRange(gl_target, static_cast<GLintptr>(buffer_pos),
- static_cast<GLsizeiptr>(mapped_size));
- buffer_pos += mapped_size;
+ buffer_pos += size;
}
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h
index e78dc5784..45592daaf 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.h
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.h
@@ -2,35 +2,41 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#pragma once
-
-#include <memory>
+#include <tuple>
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
class OGLStreamBuffer : private NonCopyable {
public:
- explicit OGLStreamBuffer(GLenum target);
- virtual ~OGLStreamBuffer() = default;
-
-public:
- static std::unique_ptr<OGLStreamBuffer> MakeBuffer(bool storage_buffer, GLenum target);
-
- virtual void Create(size_t size, size_t sync_subdivide) = 0;
- virtual void Release() {}
+ explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false);
+ ~OGLStreamBuffer();
GLuint GetHandle() const;
+ GLsizeiptr GetSize() const;
+
+ /*
+ * Allocates a linear chunk of memory in the GPU buffer with at least "size" bytes
+ * and the optional alignment requirement.
+ * If the buffer is full, the whole buffer is reallocated which invalidates old chunks.
+ * The return values are the pointer to the new chunk, the offset within the buffer,
+ * and the invalidation flag for previous chunks.
+ * The actual used size must be specified on unmapping the chunk.
+ */
+ std::tuple<u8*, GLintptr, bool> Map(GLsizeiptr size, GLintptr alignment = 0);
- virtual std::pair<u8*, GLintptr> Map(size_t size, size_t alignment) = 0;
- virtual void Unmap() = 0;
+ void Unmap(GLsizeiptr size);
-protected:
+private:
OGLBuffer gl_buffer;
GLenum gl_target;
- size_t buffer_pos = 0;
- size_t buffer_size = 0;
- size_t buffer_sync_subdivide = 0;
- size_t mapped_size = 0;
+ bool coherent = false;
+ bool persistent = false;
+
+ GLintptr buffer_pos = 0;
+ GLsizeiptr buffer_size = 0;
+ GLintptr mapped_offset = 0;
+ GLsizeiptr mapped_size = 0;
+ u8* mapped_ptr = nullptr;
};
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 16b1bd606..83ea0cfc0 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -27,9 +27,12 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
case Maxwell::VertexAttribute::Type::UnsignedNorm: {
switch (attrib.size) {
+ case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_8_8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return GL_UNSIGNED_BYTE;
case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return GL_UNSIGNED_SHORT;
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return GL_UNSIGNED_INT_2_10_10_10_REV;
@@ -43,6 +46,9 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
case Maxwell::VertexAttribute::Type::SignedNorm: {
switch (attrib.size) {
+ case Maxwell::VertexAttribute::Size::Size_32_32_32:
+ return GL_INT;
+ case Maxwell::VertexAttribute::Size::Size_8_8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return GL_BYTE;
case Maxwell::VertexAttribute::Size::Size_16_16:
@@ -84,6 +90,10 @@ inline GLenum IndexFormat(Maxwell::IndexFormat index_format) {
inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
switch (topology) {
+ case Maxwell::PrimitiveTopology::Points:
+ return GL_POINTS;
+ case Maxwell::PrimitiveTopology::LineStrip:
+ return GL_LINE_STRIP;
case Maxwell::PrimitiveTopology::Triangles:
return GL_TRIANGLES;
case Maxwell::PrimitiveTopology::TriangleStrip:
@@ -149,42 +159,61 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
switch (factor) {
case Maxwell::Blend::Factor::Zero:
+ case Maxwell::Blend::Factor::ZeroGL:
return GL_ZERO;
case Maxwell::Blend::Factor::One:
+ case Maxwell::Blend::Factor::OneGL:
return GL_ONE;
case Maxwell::Blend::Factor::SourceColor:
+ case Maxwell::Blend::Factor::SourceColorGL:
return GL_SRC_COLOR;
case Maxwell::Blend::Factor::OneMinusSourceColor:
+ case Maxwell::Blend::Factor::OneMinusSourceColorGL:
return GL_ONE_MINUS_SRC_COLOR;
case Maxwell::Blend::Factor::SourceAlpha:
+ case Maxwell::Blend::Factor::SourceAlphaGL:
return GL_SRC_ALPHA;
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
+ case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
return GL_ONE_MINUS_SRC_ALPHA;
case Maxwell::Blend::Factor::DestAlpha:
+ case Maxwell::Blend::Factor::DestAlphaGL:
return GL_DST_ALPHA;
case Maxwell::Blend::Factor::OneMinusDestAlpha:
+ case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
return GL_ONE_MINUS_DST_ALPHA;
case Maxwell::Blend::Factor::DestColor:
+ case Maxwell::Blend::Factor::DestColorGL:
return GL_DST_COLOR;
case Maxwell::Blend::Factor::OneMinusDestColor:
+ case Maxwell::Blend::Factor::OneMinusDestColorGL:
return GL_ONE_MINUS_DST_COLOR;
case Maxwell::Blend::Factor::SourceAlphaSaturate:
+ case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
return GL_SRC_ALPHA_SATURATE;
case Maxwell::Blend::Factor::Source1Color:
+ case Maxwell::Blend::Factor::Source1ColorGL:
return GL_SRC1_COLOR;
case Maxwell::Blend::Factor::OneMinusSource1Color:
+ case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
return GL_ONE_MINUS_SRC1_COLOR;
case Maxwell::Blend::Factor::Source1Alpha:
+ case Maxwell::Blend::Factor::Source1AlphaGL:
return GL_SRC1_ALPHA;
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
+ case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
return GL_ONE_MINUS_SRC1_ALPHA;
case Maxwell::Blend::Factor::ConstantColor:
+ case Maxwell::Blend::Factor::ConstantColorGL:
return GL_CONSTANT_COLOR;
case Maxwell::Blend::Factor::OneMinusConstantColor:
+ case Maxwell::Blend::Factor::OneMinusConstantColorGL:
return GL_ONE_MINUS_CONSTANT_COLOR;
case Maxwell::Blend::Factor::ConstantAlpha:
+ case Maxwell::Blend::Factor::ConstantAlphaGL:
return GL_CONSTANT_ALPHA;
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
+ case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
return GL_ONE_MINUS_CONSTANT_ALPHA;
}
LOG_CRITICAL(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index bf9131193..95f1aa0fe 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -18,7 +18,6 @@
#include "core/tracer/recorder.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
#include "video_core/utils.h"
-#include "video_core/video_core.h"
static const char vertex_shader[] = R"(
#version 150 core
@@ -92,7 +91,8 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
return matrix;
}
-ScopeAcquireGLContext::ScopeAcquireGLContext(EmuWindow& emu_window_) : emu_window{emu_window_} {
+ScopeAcquireGLContext::ScopeAcquireGLContext(Core::Frontend::EmuWindow& emu_window_)
+ : emu_window{emu_window_} {
if (Settings::values.use_multi_core) {
emu_window.MakeCurrent();
}
@@ -103,7 +103,9 @@ ScopeAcquireGLContext::~ScopeAcquireGLContext() {
}
}
-RendererOpenGL::RendererOpenGL(EmuWindow& window) : VideoCore::RendererBase{window} {}
+RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window)
+ : VideoCore::RendererBase{window} {}
+
RendererOpenGL::~RendererOpenGL() = default;
/// Swap buffers (render frame)
@@ -430,7 +432,7 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
case GL_DEBUG_SEVERITY_LOW:
- LOG_DEBUG(Render_OpenGL, format, str_source, str_type, id, message);
+ LOG_TRACE(Render_OpenGL, format, str_source, str_type, id, message);
break;
}
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 428afa3b7..a5eab6997 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -12,7 +12,9 @@
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_state.h"
+namespace Core::Frontend {
class EmuWindow;
+}
/// Structure used for storing information about the textures for the Switch screen
struct TextureInfo {
@@ -34,16 +36,16 @@ struct ScreenInfo {
/// Helper class to acquire/release OpenGL context within a given scope
class ScopeAcquireGLContext : NonCopyable {
public:
- explicit ScopeAcquireGLContext(EmuWindow& window);
+ explicit ScopeAcquireGLContext(Core::Frontend::EmuWindow& window);
~ScopeAcquireGLContext();
private:
- EmuWindow& emu_window;
+ Core::Frontend::EmuWindow& emu_window;
};
class RendererOpenGL : public VideoCore::RendererBase {
public:
- explicit RendererOpenGL(EmuWindow& window);
+ explicit RendererOpenGL(Core::Frontend::EmuWindow& window);
~RendererOpenGL() override;
/// Swap buffers (render frame)
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 65db84ad3..70746a34e 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -54,6 +54,7 @@ u32 BytesPerPixel(TextureFormat format) {
return 8;
case TextureFormat::DXT23:
case TextureFormat::DXT45:
+ case TextureFormat::DXN2:
case TextureFormat::BC7U:
// In this case a 'pixel' actually refers to a 4x4 tile.
return 16;
@@ -85,87 +86,11 @@ u32 BytesPerPixel(TextureFormat format) {
}
}
-static u32 DepthBytesPerPixel(DepthFormat format) {
- switch (format) {
- case DepthFormat::Z16_UNORM:
- return 2;
- case DepthFormat::S8_Z24_UNORM:
- case DepthFormat::Z24_S8_UNORM:
- case DepthFormat::Z32_FLOAT:
- return 4;
- case DepthFormat::Z32_S8_X24_FLOAT:
- return 8;
- default:
- UNIMPLEMENTED_MSG("Format not implemented");
- break;
- }
-}
-
-std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
- u32 block_height) {
- u8* data = Memory::GetPointer(address);
- u32 bytes_per_pixel = BytesPerPixel(format);
-
+std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
+ u32 height, u32 block_height) {
std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
-
- switch (format) {
- case TextureFormat::DXT1:
- case TextureFormat::DXT23:
- case TextureFormat::DXT45:
- case TextureFormat::DXN1:
- case TextureFormat::BC7U:
- // In the DXT and DXN formats, each 4x4 tile is swizzled instead of just individual pixel
- // values.
- CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
- unswizzled_data.data(), true, block_height);
- break;
- case TextureFormat::A8R8G8B8:
- case TextureFormat::A2B10G10R10:
- case TextureFormat::A1B5G5R5:
- case TextureFormat::B5G6R5:
- case TextureFormat::R8:
- case TextureFormat::G8R8:
- case TextureFormat::R16_G16_B16_A16:
- case TextureFormat::R32_G32_B32_A32:
- case TextureFormat::R32_G32:
- case TextureFormat::R32:
- case TextureFormat::R16:
- case TextureFormat::R16_G16:
- case TextureFormat::BF10GF11RF11:
- case TextureFormat::ASTC_2D_4X4:
- case TextureFormat::R32_G32_B32:
- CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
- unswizzled_data.data(), true, block_height);
- break;
- default:
- UNIMPLEMENTED_MSG("Format not implemented");
- break;
- }
-
- return unswizzled_data;
-}
-
-std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height,
- u32 block_height) {
- u8* data = Memory::GetPointer(address);
- u32 bytes_per_pixel = DepthBytesPerPixel(format);
-
- std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
-
- switch (format) {
- case DepthFormat::Z16_UNORM:
- case DepthFormat::S8_Z24_UNORM:
- case DepthFormat::Z24_S8_UNORM:
- case DepthFormat::Z32_FLOAT:
- case DepthFormat::Z32_S8_X24_FLOAT:
- CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
- unswizzled_data.data(), true, block_height);
- break;
- default:
- UNIMPLEMENTED_MSG("Format not implemented");
- break;
- }
-
+ CopySwizzledData(width / tile_size, height / tile_size, bytes_per_pixel, bytes_per_pixel,
+ Memory::GetPointer(address), unswizzled_data.data(), true, block_height);
return unswizzled_data;
}
@@ -179,6 +104,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
case TextureFormat::DXT23:
case TextureFormat::DXT45:
case TextureFormat::DXN1:
+ case TextureFormat::DXN2:
case TextureFormat::BC7U:
case TextureFormat::ASTC_2D_4X4:
case TextureFormat::A8R8G8B8:
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 73a4924d1..1f7b731be 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -13,8 +13,8 @@ namespace Tegra::Texture {
/**
* Unswizzles a swizzled texture without changing its format.
*/
-std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
- u32 block_height = TICEntry::DefaultBlockHeight);
+std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
+ u32 height, u32 block_height = TICEntry::DefaultBlockHeight);
/**
* Unswizzles a swizzled depth texture without changing its format.
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 5085ef96b..6780d1c16 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -9,9 +9,7 @@
namespace VideoCore {
-std::atomic<bool> g_toggle_framelimit_enabled;
-
-std::unique_ptr<RendererBase> CreateRenderer(EmuWindow& emu_window) {
+std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window) {
return std::make_unique<RendererOpenGL>(emu_window);
}
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h
index 7c01c0b8d..f79f85dfe 100644
--- a/src/video_core/video_core.h
+++ b/src/video_core/video_core.h
@@ -4,27 +4,22 @@
#pragma once
-#include <atomic>
#include <memory>
+namespace Core::Frontend {
class EmuWindow;
+}
namespace VideoCore {
class RendererBase;
-enum class Renderer { Software, OpenGL };
-
-// TODO: Wrap these in a user settings struct along with any other graphics settings (often set from
-// qt ui)
-extern std::atomic<bool> g_toggle_framelimit_enabled;
-
/**
* Creates a renderer instance.
*
* @note The returned renderer instance is simply allocated. Its Init()
* function still needs to be called to fully complete its setup.
*/
-std::unique_ptr<RendererBase> CreateRenderer(EmuWindow& emu_window);
+std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window);
} // namespace VideoCore
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 475556806..46ed232d8 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -17,6 +17,8 @@ add_executable(yuzu
configuration/configure_debug.h
configuration/configure_dialog.cpp
configuration/configure_dialog.h
+ configuration/configure_gamelist.cpp
+ configuration/configure_gamelist.h
configuration/configure_general.cpp
configuration/configure_general.h
configuration/configure_graphics.cpp
@@ -59,6 +61,7 @@ set(UIS
configuration/configure.ui
configuration/configure_audio.ui
configuration/configure_debug.ui
+ configuration/configure_gamelist.ui
configuration/configure_general.ui
configuration/configure_graphics.ui
configuration/configure_input.ui
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp
index 39ed3bccf..a81ad2888 100644
--- a/src/yuzu/about_dialog.cpp
+++ b/src/yuzu/about_dialog.cpp
@@ -15,4 +15,4 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDia
Common::g_scm_desc, QString(Common::g_build_date).left(10)));
}
-AboutDialog::~AboutDialog() {}
+AboutDialog::~AboutDialog() = default;
diff --git a/src/yuzu/about_dialog.h b/src/yuzu/about_dialog.h
index 2eb6e28f5..18e8c11a7 100644
--- a/src/yuzu/about_dialog.h
+++ b/src/yuzu/about_dialog.h
@@ -16,7 +16,7 @@ class AboutDialog : public QDialog {
public:
explicit AboutDialog(QWidget* parent);
- ~AboutDialog();
+ ~AboutDialog() override;
private:
std::unique_ptr<Ui::AboutDialog> ui;
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 130bc613b..f133bfadf 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -101,12 +101,12 @@ signals:
void ErrorThrown(Core::System::ResultStatus, std::string);
};
-class GRenderWindow : public QWidget, public EmuWindow {
+class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
Q_OBJECT
public:
GRenderWindow(QWidget* parent, EmuThread* emu_thread);
- ~GRenderWindow();
+ ~GRenderWindow() override;
// EmuWindow implementation
void SwapBuffers() override;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index bf469ee73..0bd46dbac 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -122,6 +122,13 @@ void Config::ReadValues() {
qt_config->beginGroup("UI");
UISettings::values.theme = qt_config->value("theme", UISettings::themes[0].second).toString();
+ qt_config->beginGroup("UIGameList");
+ UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
+ UISettings::values.icon_size = qt_config->value("icon_size", 48).toUInt();
+ UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 0).toUInt();
+ UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 3).toUInt();
+ qt_config->endGroup();
+
qt_config->beginGroup("UILayout");
UISettings::values.geometry = qt_config->value("geometry").toByteArray();
UISettings::values.state = qt_config->value("state").toByteArray();
@@ -234,6 +241,13 @@ void Config::SaveValues() {
qt_config->beginGroup("UI");
qt_config->setValue("theme", UISettings::values.theme);
+ qt_config->beginGroup("UIGameList");
+ qt_config->setValue("show_unknown", UISettings::values.show_unknown);
+ qt_config->setValue("icon_size", UISettings::values.icon_size);
+ qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id);
+ qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id);
+ qt_config->endGroup();
+
qt_config->beginGroup("UILayout");
qt_config->setValue("geometry", UISettings::values.geometry);
qt_config->setValue("state", UISettings::values.state);
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui
index c8e0b88af..20f120134 100644
--- a/src/yuzu/configuration/configure.ui
+++ b/src/yuzu/configuration/configure.ui
@@ -24,6 +24,11 @@
<string>General</string>
</attribute>
</widget>
+ <widget class="ConfigureGameList" name="gameListTab">
+ <attribute name="title">
+ <string>Game List</string>
+ </attribute>
+ </widget>
<widget class="ConfigureSystem" name="systemTab">
<attribute name="title">
<string>System</string>
@@ -67,6 +72,12 @@
<header>configuration/configure_general.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>ConfigureGameList</class>
+ <extends>QWidget</extends>
+ <header>configuration/configure_gamelist.h</header>
+ <container>1</container>
+ </customwidget>
<customwidget>
<class>ConfigureSystem</class>
<extends>QWidget</extends>
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 7fd07539a..45d84f19a 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -24,7 +24,7 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::Co
});
}
-ConfigureDebug::~ConfigureDebug() {}
+ConfigureDebug::~ConfigureDebug() = default;
void ConfigureDebug::setConfiguration() {
ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub);
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 118e91cf1..5ae7276bd 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -23,13 +23,6 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
- <widget class="QLabel" name="label_1">
- <property name="text">
- <string>The GDB Stub only works correctly when the CPU JIT is off.</string>
- </property>
- </widget>
- </item>
- <item>
<layout class="QHBoxLayout" name="horizontalLayout_1">
<item>
<widget class="QCheckBox" name="toggle_gdbstub">
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index f66abf870..daa4cc0d9 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -6,18 +6,22 @@
#include "ui_configure.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_dialog.h"
+#include "yuzu/hotkeys.h"
-ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) {
+ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry)
+ : QDialog(parent), ui(new Ui::ConfigureDialog) {
ui->setupUi(this);
+ ui->generalTab->PopulateHotkeyList(registry);
this->setConfiguration();
}
-ConfigureDialog::~ConfigureDialog() {}
+ConfigureDialog::~ConfigureDialog() = default;
void ConfigureDialog::setConfiguration() {}
void ConfigureDialog::applyConfiguration() {
ui->generalTab->applyConfiguration();
+ ui->gameListTab->applyConfiguration();
ui->systemTab->applyConfiguration();
ui->inputTab->applyConfiguration();
ui->graphicsTab->applyConfiguration();
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 21fa1f501..bbbdacc29 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -7,6 +7,8 @@
#include <memory>
#include <QDialog>
+class HotkeyRegistry;
+
namespace Ui {
class ConfigureDialog;
}
@@ -15,7 +17,7 @@ class ConfigureDialog : public QDialog {
Q_OBJECT
public:
- explicit ConfigureDialog(QWidget* parent);
+ explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry);
~ConfigureDialog();
void applyConfiguration();
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
new file mode 100644
index 000000000..1ae3423cf
--- /dev/null
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -0,0 +1,63 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/core.h"
+#include "core/settings.h"
+#include "ui_configure_gamelist.h"
+#include "ui_settings.h"
+#include "yuzu/configuration/configure_gamelist.h"
+
+ConfigureGameList::ConfigureGameList(QWidget* parent)
+ : QWidget(parent), ui(new Ui::ConfigureGameList) {
+ ui->setupUi(this);
+
+ static const std::vector<std::pair<u32, std::string>> default_icon_sizes{
+ std::make_pair(0, "None"), std::make_pair(32, "Small"),
+ std::make_pair(64, "Standard"), std::make_pair(128, "Large"),
+ std::make_pair(256, "Full Size"),
+ };
+
+ for (const auto& size : default_icon_sizes) {
+ ui->icon_size_combobox->addItem(QString::fromStdString(size.second + " (" +
+ std::to_string(size.first) + "x" +
+ std::to_string(size.first) + ")"),
+ size.first);
+ }
+
+ static const std::vector<std::string> row_text_names{
+ "Filename",
+ "Filetype",
+ "Title ID",
+ "Title Name",
+ };
+
+ for (size_t i = 0; i < row_text_names.size(); ++i) {
+ ui->row_1_text_combobox->addItem(QString::fromStdString(row_text_names[i]),
+ QVariant::fromValue(i));
+ ui->row_2_text_combobox->addItem(QString::fromStdString(row_text_names[i]),
+ QVariant::fromValue(i));
+ }
+
+ this->setConfiguration();
+}
+
+ConfigureGameList::~ConfigureGameList() {}
+
+void ConfigureGameList::setConfiguration() {
+ ui->show_unknown->setChecked(UISettings::values.show_unknown);
+ ui->icon_size_combobox->setCurrentIndex(
+ ui->icon_size_combobox->findData(UISettings::values.icon_size));
+ ui->row_1_text_combobox->setCurrentIndex(
+ ui->row_1_text_combobox->findData(UISettings::values.row_1_text_id));
+ ui->row_2_text_combobox->setCurrentIndex(
+ ui->row_2_text_combobox->findData(UISettings::values.row_2_text_id));
+}
+
+void ConfigureGameList::applyConfiguration() {
+ UISettings::values.show_unknown = ui->show_unknown->isChecked();
+ UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
+ UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
+ UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
+ Settings::Apply();
+}
diff --git a/src/yuzu/configuration/configure_gamelist.h b/src/yuzu/configuration/configure_gamelist.h
new file mode 100644
index 000000000..94fba6373
--- /dev/null
+++ b/src/yuzu/configuration/configure_gamelist.h
@@ -0,0 +1,28 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <QWidget>
+
+namespace Ui {
+class ConfigureGameList;
+}
+
+class ConfigureGameList : public QWidget {
+ Q_OBJECT
+
+public:
+ explicit ConfigureGameList(QWidget* parent = nullptr);
+ ~ConfigureGameList();
+
+ void applyConfiguration();
+
+private:
+ void setConfiguration();
+
+private:
+ std::unique_ptr<Ui::ConfigureGameList> ui;
+};
diff --git a/src/yuzu/configuration/configure_gamelist.ui b/src/yuzu/configuration/configure_gamelist.ui
new file mode 100644
index 000000000..7471fdb60
--- /dev/null
+++ b/src/yuzu/configuration/configure_gamelist.ui
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigureGameList</class>
+ <widget class="QWidget" name="ConfigureGeneral">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>377</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="HorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="VerticalLayout">
+ <item>
+ <widget class="QGroupBox" name="GeneralGroupBox">
+ <property name="title">
+ <string>General</string>
+ </property>
+ <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="GeneralVerticalLayout">
+ <item>
+ <widget class="QCheckBox" name="show_unknown">
+ <property name="text">
+ <string>Show files with type 'Unknown'</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="IconSizeGroupBox">
+ <property name="title">
+ <string>Icon Size</string>
+ </property>
+ <layout class="QHBoxLayout" name="icon_size_qhbox_layout">
+ <item>
+ <layout class="QVBoxLayout" name="icon_size_qvbox_layout">
+ <item>
+ <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
+ <item>
+ <widget class="QLabel" name="icon_size_label">
+ <property name="text">
+ <string>Icon Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="icon_size_combobox"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="RowGroupBox">
+ <property name="title">
+ <string>Row Text</string>
+ </property>
+ <layout class="QHBoxLayout" name="RowHorizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="RowVerticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="row_1_qhbox_layout">
+ <item>
+ <widget class="QLabel" name="row_1_label">
+ <property name="text">
+ <string>Row 1 Text:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="row_1_text_combobox"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="row_2_qhbox_layout">
+ <item>
+ <widget class="QLabel" name="row_2_label">
+ <property name="text">
+ <string>Row 2 Text:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="row_2_text_combobox"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index cb7d3f8bf..d8caee1e8 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -24,7 +24,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
}
-ConfigureGeneral::~ConfigureGeneral() {}
+ConfigureGeneral::~ConfigureGeneral() = default;
void ConfigureGeneral::setConfiguration() {
ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
@@ -35,6 +35,10 @@ void ConfigureGeneral::setConfiguration() {
ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
}
+void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) {
+ ui->widget->Populate(registry);
+}
+
void ConfigureGeneral::applyConfiguration() {
UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 447552d8c..4770034cc 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -7,6 +7,8 @@
#include <memory>
#include <QWidget>
+class HotkeyRegistry;
+
namespace Ui {
class ConfigureGeneral;
}
@@ -18,11 +20,11 @@ public:
explicit ConfigureGeneral(QWidget* parent = nullptr);
~ConfigureGeneral();
+ void PopulateHotkeyList(const HotkeyRegistry& registry);
void applyConfiguration();
private:
void setConfiguration();
-private:
std::unique_ptr<Ui::ConfigureGeneral> ui;
};
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 3379b7963..4afe0f81b 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -14,7 +14,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
this->setConfiguration();
}
-ConfigureGraphics::~ConfigureGraphics() {}
+ConfigureGraphics::~ConfigureGraphics() = default;
enum class Resolution : int {
Auto,
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 9be2c939c..e9ed9c38f 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -35,7 +35,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::
this->setConfiguration();
}
-ConfigureSystem::~ConfigureSystem() {}
+ConfigureSystem::~ConfigureSystem() = default;
void ConfigureSystem::setConfiguration() {
enabled = !Core::System::GetInstance().IsPoweredOn();
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp
index ff3efcdaa..e037223c2 100644
--- a/src/yuzu/debugger/graphics/graphics_surface.cpp
+++ b/src/yuzu/debugger/graphics/graphics_surface.cpp
@@ -34,7 +34,8 @@ static Tegra::Texture::TextureFormat ConvertToTextureFormat(
SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_)
: QLabel(parent), surface_widget(surface_widget_) {}
-SurfacePicture::~SurfacePicture() {}
+
+SurfacePicture::~SurfacePicture() = default;
void SurfacePicture::mousePressEvent(QMouseEvent* event) {
// Only do something while the left mouse button is held down
@@ -382,8 +383,10 @@ void GraphicsSurfaceWidget::OnUpdate() {
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
boost::optional<VAddr> address = gpu.memory_manager->GpuToCpuAddress(surface_address);
- auto unswizzled_data =
- Tegra::Texture::UnswizzleTexture(*address, surface_format, surface_width, surface_height);
+ // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.
+ // Needs to be fixed if we plan to use this feature more, otherwise we may remove it.
+ auto unswizzled_data = Tegra::Texture::UnswizzleTexture(
+ *address, 1, Tegra::Texture::BytesPerPixel(surface_format), surface_width, surface_height);
auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
surface_width, surface_height);
diff --git a/src/yuzu/debugger/graphics/graphics_surface.h b/src/yuzu/debugger/graphics/graphics_surface.h
index 58f9db465..323e39d94 100644
--- a/src/yuzu/debugger/graphics/graphics_surface.h
+++ b/src/yuzu/debugger/graphics/graphics_surface.h
@@ -22,11 +22,11 @@ class SurfacePicture : public QLabel {
public:
explicit SurfacePicture(QWidget* parent = nullptr,
GraphicsSurfaceWidget* surface_widget = nullptr);
- ~SurfacePicture();
+ ~SurfacePicture() override;
protected slots:
- virtual void mouseMoveEvent(QMouseEvent* event);
- virtual void mousePressEvent(QMouseEvent* event);
+ void mouseMoveEvent(QMouseEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
private:
GraphicsSurfaceWidget* surface_widget;
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index f5a5697a0..d0926d723 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -14,7 +14,7 @@
#include "core/hle/kernel/timer.h"
#include "core/hle/kernel/wait_object.h"
-WaitTreeItem::~WaitTreeItem() {}
+WaitTreeItem::~WaitTreeItem() = default;
QColor WaitTreeItem::GetColor() const {
return QColor(Qt::GlobalColor::black);
@@ -316,7 +316,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
list.push_back(std::make_unique<WaitTreeText>(
tr("reset type = %1")
- .arg(GetResetTypeQString(static_cast<const Kernel::Event&>(object).reset_type))));
+ .arg(GetResetTypeQString(static_cast<const Kernel::Event&>(object).GetResetType()))));
return list;
}
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 6cbce6856..513b3c45d 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -25,11 +25,13 @@ class WaitTreeThread;
class WaitTreeItem : public QObject {
Q_OBJECT
public:
+ ~WaitTreeItem() override;
+
virtual bool IsExpandable() const;
virtual std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const;
virtual QString GetText() const = 0;
virtual QColor GetColor() const;
- virtual ~WaitTreeItem();
+
void Expand();
WaitTreeItem* Parent() const;
const std::vector<std::unique_ptr<WaitTreeItem>>& Children() const;
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 71e24a9e2..85cb12594 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -9,9 +9,13 @@
#include <QKeyEvent>
#include <QMenu>
#include <QThreadPool>
+#include <boost/container/flat_map.hpp>
#include "common/common_paths.h"
#include "common/logging/log.h"
#include "common/string_util.h"
+#include "core/file_sys/content_archive.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/romfs.h"
#include "core/file_sys/vfs_real.h"
#include "core/loader/loader.h"
#include "game_list.h"
@@ -162,15 +166,15 @@ void GameList::onTextChanged(const QString& newText) {
}
search_field->setFilterResult(rowCount, rowCount);
} else {
- QStandardItem* child_file;
- QString file_path, file_name, file_title, file_programmid;
int result_count = 0;
for (int i = 0; i < rowCount; ++i) {
- child_file = item_model->item(i, 0);
- file_path = child_file->data(GameListItemPath::FullPathRole).toString().toLower();
- file_name = file_path.mid(file_path.lastIndexOf("/") + 1);
- file_title = child_file->data(GameListItemPath::TitleRole).toString().toLower();
- file_programmid =
+ const QStandardItem* child_file = item_model->item(i, 0);
+ const QString file_path =
+ child_file->data(GameListItemPath::FullPathRole).toString().toLower();
+ QString file_name = file_path.mid(file_path.lastIndexOf('/') + 1);
+ const QString file_title =
+ child_file->data(GameListItemPath::TitleRole).toString().toLower();
+ const QString file_programmid =
child_file->data(GameListItemPath::ProgramIdRole).toString().toLower();
// Only items which filename in combination with its title contains all words
@@ -194,7 +198,8 @@ void GameList::onFilterCloseClicked() {
main_window->filterBarSetChecked(false);
}
-GameList::GameList(GMainWindow* parent) : QWidget{parent} {
+GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent)
+ : QWidget{parent}, vfs(std::move(vfs)) {
watcher = new QFileSystemWatcher(this);
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory);
@@ -258,18 +263,20 @@ void GameList::AddEntry(const QList<QStandardItem*>& entry_items) {
void GameList::ValidateEntry(const QModelIndex& item) {
// We don't care about the individual QStandardItem that was selected, but its row.
- int row = item_model->itemFromIndex(item)->row();
- QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME);
- QString file_path = child_file->data(GameListItemPath::FullPathRole).toString();
+ const int row = item_model->itemFromIndex(item)->row();
+ const QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME);
+ const QString file_path = child_file->data(GameListItemPath::FullPathRole).toString();
if (file_path.isEmpty())
return;
- std::string std_file_path(file_path.toStdString());
- if (!FileUtil::Exists(std_file_path))
+
+ if (!QFileInfo::exists(file_path))
return;
- if (FileUtil::IsDirectory(std_file_path)) {
- QDir dir(std_file_path.c_str());
- QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files);
+
+ const QFileInfo file_info{file_path};
+ if (file_info.isDir()) {
+ const QDir dir{file_path};
+ const QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files);
if (matching_main.size() == 1) {
emit GameChosen(dir.path() + DIR_SEP + matching_main[0]);
}
@@ -336,7 +343,7 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {
emit ShouldCancelWorker();
- GameListWorker* worker = new GameListWorker(dir_path, deep_scan);
+ GameListWorker* worker = new GameListWorker(vfs, dir_path, deep_scan);
connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection);
connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating,
@@ -368,21 +375,23 @@ void GameList::LoadInterfaceLayout() {
const QStringList GameList::supported_file_extensions = {"nso", "nro", "nca", "xci"};
static bool HasSupportedFileExtension(const std::string& file_name) {
- QFileInfo file = QFileInfo(file_name.c_str());
+ const QFileInfo file = QFileInfo(QString::fromStdString(file_name));
return GameList::supported_file_extensions.contains(file.suffix(), Qt::CaseInsensitive);
}
static bool IsExtractedNCAMain(const std::string& file_name) {
- return QFileInfo(file_name.c_str()).fileName() == "main";
+ return QFileInfo(QString::fromStdString(file_name)).fileName() == "main";
}
static QString FormatGameName(const std::string& physical_name) {
- QFileInfo file_info(physical_name.c_str());
+ const QString physical_name_as_qstring = QString::fromStdString(physical_name);
+ const QFileInfo file_info(physical_name_as_qstring);
+
if (IsExtractedNCAMain(physical_name)) {
return file_info.dir().path();
- } else {
- return QString::fromStdString(physical_name);
}
+
+ return physical_name_as_qstring;
}
void GameList::RefreshGameDirectory() {
@@ -394,8 +403,32 @@ void GameList::RefreshGameDirectory() {
}
void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) {
- const auto callback = [this, recursion](u64* num_entries_out, const std::string& directory,
- const std::string& virtual_name) -> bool {
+ boost::container::flat_map<u64, std::shared_ptr<FileSys::NCA>> nca_control_map;
+
+ const auto nca_control_callback =
+ [this, &nca_control_map](u64* num_entries_out, const std::string& directory,
+ const std::string& virtual_name) -> bool {
+ std::string physical_name = directory + DIR_SEP + virtual_name;
+
+ if (stop_processing)
+ return false; // Breaks the callback loop.
+
+ bool is_dir = FileUtil::IsDirectory(physical_name);
+ QFileInfo file_info(physical_name.c_str());
+ if (!is_dir && file_info.suffix().toStdString() == "nca") {
+ auto nca =
+ std::make_shared<FileSys::NCA>(vfs->OpenFile(physical_name, FileSys::Mode::Read));
+ if (nca->GetType() == FileSys::NCAContentType::Control)
+ nca_control_map.insert_or_assign(nca->GetTitleId(), nca);
+ }
+ return true;
+ };
+
+ FileUtil::ForeachDirectoryEntry(nullptr, dir_path, nca_control_callback);
+
+ const auto callback = [this, recursion,
+ &nca_control_map](u64* num_entries_out, const std::string& directory,
+ const std::string& virtual_name) -> bool {
std::string physical_name = directory + DIR_SEP + virtual_name;
if (stop_processing)
@@ -405,18 +438,48 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
if (!is_dir &&
(HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
std::unique_ptr<Loader::AppLoader> loader =
- Loader::GetLoader(std::make_shared<FileSys::RealVfsFile>(physical_name));
- if (!loader)
+ Loader::GetLoader(vfs->OpenFile(physical_name, FileSys::Mode::Read));
+ if (!loader || ((loader->GetFileType() == Loader::FileType::Unknown ||
+ loader->GetFileType() == Loader::FileType::Error) &&
+ !UISettings::values.show_unknown))
return true;
- std::vector<u8> smdh;
- loader->ReadIcon(smdh);
-
- u64 program_id = 0;
- loader->ReadProgramId(program_id);
+ std::vector<u8> icon;
+ const auto res1 = loader->ReadIcon(icon);
+
+ u64 program_id;
+ const auto res2 = loader->ReadProgramId(program_id);
+
+ std::string name = " ";
+ const auto res3 = loader->ReadTitle(name);
+
+ if (res1 != Loader::ResultStatus::Success && res3 != Loader::ResultStatus::Success &&
+ res2 == Loader::ResultStatus::Success) {
+ // Use from metadata pool.
+ if (nca_control_map.find(program_id) != nca_control_map.end()) {
+ const auto nca = nca_control_map[program_id];
+ const auto control_dir = FileSys::ExtractRomFS(nca->GetRomFS());
+
+ const auto nacp_file = control_dir->GetFile("control.nacp");
+ FileSys::NACP nacp(nacp_file);
+ name = nacp.GetApplicationName();
+
+ FileSys::VirtualFile icon_file = nullptr;
+ for (const auto& language : FileSys::LANGUAGE_NAMES) {
+ icon_file = control_dir->GetFile("icon_" + std::string(language) + ".dat");
+ if (icon_file != nullptr) {
+ icon = icon_file->ReadAllBytes();
+ break;
+ }
+ }
+ }
+ }
emit EntryReady({
- new GameListItemPath(FormatGameName(physical_name), smdh, program_id),
+ new GameListItemPath(
+ FormatGameName(physical_name), icon, QString::fromStdString(name),
+ QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())),
+ program_id),
new GameListItem(
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),
new GameListItemSize(FileUtil::GetSize(physical_name)),
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 3bc14f07f..afe624b32 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -59,7 +59,7 @@ public:
QToolButton* button_filter_close = nullptr;
};
- explicit GameList(GMainWindow* parent = nullptr);
+ explicit GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent = nullptr);
~GameList() override;
void clearFilter();
@@ -90,6 +90,7 @@ private:
void PopupContextMenu(const QPoint& menu_location);
void RefreshGameDirectory();
+ FileSys::VirtualFilesystem vfs;
SearchField* search_field;
GMainWindow* main_window = nullptr;
QVBoxLayout* layout = nullptr;
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index a758b77aa..8fe5e8b80 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -4,12 +4,15 @@
#pragma once
+#include <array>
#include <atomic>
+#include <utility>
#include <QImage>
#include <QRunnable>
#include <QStandardItem>
#include <QString>
#include "common/string_util.h"
+#include "ui_settings.h"
#include "yuzu/util/util.h"
/**
@@ -17,8 +20,7 @@
* @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
* @return QPixmap default icon
*/
-static QPixmap GetDefaultIcon(bool large) {
- int size = large ? 48 : 24;
+static QPixmap GetDefaultIcon(u32 size) {
QPixmap icon(size, size);
icon.fill(Qt::transparent);
return icon;
@@ -27,9 +29,8 @@ static QPixmap GetDefaultIcon(bool large) {
class GameListItem : public QStandardItem {
public:
- GameListItem() : QStandardItem() {}
- GameListItem(const QString& string) : QStandardItem(string) {}
- virtual ~GameListItem() override {}
+ GameListItem() = default;
+ explicit GameListItem(const QString& string) : QStandardItem(string) {}
};
/**
@@ -39,17 +40,29 @@ public:
* If this class receives valid SMDH data, it will also display game icons and titles.
*/
class GameListItemPath : public GameListItem {
-
public:
static const int FullPathRole = Qt::UserRole + 1;
static const int TitleRole = Qt::UserRole + 2;
static const int ProgramIdRole = Qt::UserRole + 3;
+ static const int FileTypeRole = Qt::UserRole + 4;
- GameListItemPath() : GameListItem() {}
- GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id)
- : GameListItem() {
+ GameListItemPath() = default;
+ GameListItemPath(const QString& game_path, const std::vector<u8>& picture_data,
+ const QString& game_name, const QString& game_type, u64 program_id) {
setData(game_path, FullPathRole);
+ setData(game_name, TitleRole);
setData(qulonglong(program_id), ProgramIdRole);
+ setData(game_type, FileTypeRole);
+
+ const u32 size = UISettings::values.icon_size;
+
+ QPixmap picture;
+ if (!picture.loadFromData(picture_data.data(), static_cast<u32>(picture_data.size()))) {
+ picture = GetDefaultIcon(size);
+ }
+ picture = picture.scaled(size, size);
+
+ setData(picture, Qt::DecorationRole);
}
QVariant data(int role) const override {
@@ -57,11 +70,26 @@ public:
std::string filename;
Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename,
nullptr);
- QString title = data(TitleRole).toString();
- return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title);
- } else {
- return GameListItem::data(role);
+
+ const std::array<QString, 4> row_data{{
+ QString::fromStdString(filename),
+ data(FileTypeRole).toString(),
+ QString::fromStdString(fmt::format("0x{:016X}", data(ProgramIdRole).toULongLong())),
+ data(TitleRole).toString(),
+ }};
+
+ const auto& row1 = row_data.at(UISettings::values.row_1_text_id);
+ const auto& row2 = row_data.at(UISettings::values.row_2_text_id);
+
+ if (row1.isEmpty() || row1 == row2)
+ return row2;
+ if (row2.isEmpty())
+ return row1;
+
+ return row1 + "\n " + row2;
}
+
+ return GameListItem::data(role);
}
};
@@ -75,8 +103,8 @@ class GameListItemSize : public GameListItem {
public:
static const int SizeRole = Qt::UserRole + 1;
- GameListItemSize() : GameListItem() {}
- GameListItemSize(const qulonglong size_bytes) : GameListItem() {
+ GameListItemSize() = default;
+ explicit GameListItemSize(const qulonglong size_bytes) {
setData(size_bytes, SizeRole);
}
@@ -110,8 +138,8 @@ class GameListWorker : public QObject, public QRunnable {
Q_OBJECT
public:
- GameListWorker(QString dir_path, bool deep_scan)
- : QObject(), QRunnable(), dir_path(dir_path), deep_scan(deep_scan) {}
+ GameListWorker(FileSys::VirtualFilesystem vfs, QString dir_path, bool deep_scan)
+ : vfs(std::move(vfs)), dir_path(std::move(dir_path)), deep_scan(deep_scan) {}
public slots:
/// Starts the processing of directory tree information.
@@ -134,6 +162,7 @@ signals:
void Finished(QStringList watch_list);
private:
+ FileSys::VirtualFilesystem vfs;
QStringList watch_list;
QString dir_path;
bool deep_scan;
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index 61acb38ee..dce399774 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -10,58 +10,53 @@
#include "yuzu/hotkeys.h"
#include "yuzu/ui_settings.h"
-struct Hotkey {
- Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {}
+HotkeyRegistry::HotkeyRegistry() = default;
+HotkeyRegistry::~HotkeyRegistry() = default;
- QKeySequence keyseq;
- QShortcut* shortcut;
- Qt::ShortcutContext context;
-};
-
-typedef std::map<QString, Hotkey> HotkeyMap;
-typedef std::map<QString, HotkeyMap> HotkeyGroupMap;
-
-HotkeyGroupMap hotkey_groups;
-
-void SaveHotkeys() {
- UISettings::values.shortcuts.clear();
- for (auto group : hotkey_groups) {
- for (auto hotkey : group.second) {
- UISettings::values.shortcuts.emplace_back(
- UISettings::Shortcut(group.first + "/" + hotkey.first,
- UISettings::ContextualShortcut(hotkey.second.keyseq.toString(),
- hotkey.second.context)));
- }
- }
-}
-
-void LoadHotkeys() {
+void HotkeyRegistry::LoadHotkeys() {
// Make sure NOT to use a reference here because it would become invalid once we call
// beginGroup()
for (auto shortcut : UISettings::values.shortcuts) {
- QStringList cat = shortcut.first.split("/");
+ const QStringList cat = shortcut.first.split('/');
Q_ASSERT(cat.size() >= 2);
// RegisterHotkey assigns default keybindings, so use old values as default parameters
Hotkey& hk = hotkey_groups[cat[0]][cat[1]];
if (!shortcut.second.first.isEmpty()) {
hk.keyseq = QKeySequence::fromString(shortcut.second.first);
- hk.context = (Qt::ShortcutContext)shortcut.second.second;
+ hk.context = static_cast<Qt::ShortcutContext>(shortcut.second.second);
}
if (hk.shortcut)
hk.shortcut->setKey(hk.keyseq);
}
}
-void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq,
- Qt::ShortcutContext default_context) {
- if (hotkey_groups[group].find(action) == hotkey_groups[group].end()) {
- hotkey_groups[group][action].keyseq = default_keyseq;
- hotkey_groups[group][action].context = default_context;
+void HotkeyRegistry::SaveHotkeys() {
+ UISettings::values.shortcuts.clear();
+ for (const auto& group : hotkey_groups) {
+ for (const auto& hotkey : group.second) {
+ UISettings::values.shortcuts.emplace_back(
+ UISettings::Shortcut(group.first + '/' + hotkey.first,
+ UISettings::ContextualShortcut(hotkey.second.keyseq.toString(),
+ hotkey.second.context)));
+ }
}
}
-QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget) {
+void HotkeyRegistry::RegisterHotkey(const QString& group, const QString& action,
+ const QKeySequence& default_keyseq,
+ Qt::ShortcutContext default_context) {
+ auto& hotkey_group = hotkey_groups[group];
+ if (hotkey_group.find(action) != hotkey_group.end()) {
+ return;
+ }
+
+ auto& hotkey_action = hotkey_groups[group][action];
+ hotkey_action.keyseq = default_keyseq;
+ hotkey_action.context = default_context;
+}
+
+QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {
Hotkey& hk = hotkey_groups[group][action];
if (!hk.shortcut)
@@ -72,10 +67,12 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge
GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) {
ui.setupUi(this);
+}
- for (auto group : hotkey_groups) {
+void GHotkeysDialog::Populate(const HotkeyRegistry& registry) {
+ for (const auto& group : registry.hotkey_groups) {
QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first));
- for (auto hotkey : group.second) {
+ for (const auto& hotkey : group.second) {
QStringList columns;
columns << hotkey.first << hotkey.second.keyseq.toString();
QTreeWidgetItem* item = new QTreeWidgetItem(columns);
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h
index a4ccc193b..f38e6c002 100644
--- a/src/yuzu/hotkeys.h
+++ b/src/yuzu/hotkeys.h
@@ -4,6 +4,7 @@
#pragma once
+#include <map>
#include "ui_hotkeys.h"
class QDialog;
@@ -11,47 +12,69 @@ class QKeySequence;
class QSettings;
class QShortcut;
-/**
- * Register a hotkey.
- *
- * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger")
- * @param action Name of the action (e.g. "Start Emulation", "Load Image")
- * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the settings
- * file before
- * @param default_context Default context to assign if the hotkey wasn't present in the settings
- * file before
- * @warning Both the group and action strings will be displayed in the hotkey settings dialog
- */
-void RegisterHotkey(const QString& group, const QString& action,
- const QKeySequence& default_keyseq = QKeySequence(),
- Qt::ShortcutContext default_context = Qt::WindowShortcut);
-
-/**
- * Returns a QShortcut object whose activated() signal can be connected to other QObjects' slots.
- *
- * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
- * @param action Name of the action (e.g. "Start Emulation", "Load Image").
- * @param widget Parent widget of the returned QShortcut.
- * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut
- * will be the same. Thus, you shouldn't rely on the caller really being the QShortcut's parent.
- */
-QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
-
-/**
- * Saves all registered hotkeys to the settings file.
- *
- * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a
- * settings group will be created to store the key sequence and the hotkey context.
- */
-void SaveHotkeys();
-
-/**
- * Loads hotkeys from the settings file.
- *
- * @note Yet unregistered hotkeys which are present in the settings will automatically be
- * registered.
- */
-void LoadHotkeys();
+class HotkeyRegistry final {
+public:
+ friend class GHotkeysDialog;
+
+ explicit HotkeyRegistry();
+ ~HotkeyRegistry();
+
+ /**
+ * Loads hotkeys from the settings file.
+ *
+ * @note Yet unregistered hotkeys which are present in the settings will automatically be
+ * registered.
+ */
+ void LoadHotkeys();
+
+ /**
+ * Saves all registered hotkeys to the settings file.
+ *
+ * @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a
+ * settings group will be created to store the key sequence and the hotkey context.
+ */
+ void SaveHotkeys();
+
+ /**
+ * Returns a QShortcut object whose activated() signal can be connected to other QObjects'
+ * slots.
+ *
+ * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
+ * @param action Name of the action (e.g. "Start Emulation", "Load Image").
+ * @param widget Parent widget of the returned QShortcut.
+ * @warning If multiple QWidgets' call this function for the same action, the returned QShortcut
+ * will be the same. Thus, you shouldn't rely on the caller really being the
+ * QShortcut's parent.
+ */
+ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
+
+ /**
+ * Register a hotkey.
+ *
+ * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger")
+ * @param action Name of the action (e.g. "Start Emulation", "Load Image")
+ * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the
+ * settings file before
+ * @param default_context Default context to assign if the hotkey wasn't present in the settings
+ * file before
+ * @warning Both the group and action strings will be displayed in the hotkey settings dialog
+ */
+ void RegisterHotkey(const QString& group, const QString& action,
+ const QKeySequence& default_keyseq = {},
+ Qt::ShortcutContext default_context = Qt::WindowShortcut);
+
+private:
+ struct Hotkey {
+ QKeySequence keyseq;
+ QShortcut* shortcut = nullptr;
+ Qt::ShortcutContext context = Qt::WindowShortcut;
+ };
+
+ using HotkeyMap = std::map<QString, Hotkey>;
+ using HotkeyGroupMap = std::map<QString, HotkeyMap>;
+
+ HotkeyGroupMap hotkey_groups;
+};
class GHotkeysDialog : public QWidget {
Q_OBJECT
@@ -59,6 +82,8 @@ class GHotkeysDialog : public QWidget {
public:
explicit GHotkeysDialog(QWidget* parent = nullptr);
+ void Populate(const HotkeyRegistry& registry);
+
private:
Ui::hotkeys ui;
};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e28679cd1..94fb8ae6a 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -24,6 +24,7 @@
#include "common/string_util.h"
#include "core/core.h"
#include "core/crypto/key_manager.h"
+#include "core/file_sys/vfs_real.h"
#include "core/gdbstub/gdbstub.h"
#include "core/loader/loader.h"
#include "core/settings.h"
@@ -81,7 +82,11 @@ static void ShowCalloutMessage(const QString& message, CalloutFlag flag) {
void GMainWindow::ShowCallouts() {}
-GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
+const int GMainWindow::max_recent_files_item;
+
+GMainWindow::GMainWindow()
+ : config(new Config()), emu_thread(nullptr),
+ vfs(std::make_shared<FileSys::RealVfsFilesystem>()) {
debug_context = Tegra::DebugContext::Construct();
@@ -130,7 +135,7 @@ void GMainWindow::InitializeWidgets() {
render_window = new GRenderWindow(this, emu_thread.get());
render_window->hide();
- game_list = new GameList(this);
+ game_list = new GameList(vfs, this);
ui.horizontalLayout->addWidget(game_list);
// Create status bar
@@ -206,43 +211,46 @@ void GMainWindow::InitializeRecentFileMenuActions() {
}
void GMainWindow::InitializeHotkeys() {
- RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
- RegisterHotkey("Main Window", "Start Emulation");
- RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4));
- RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen);
- RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape),
- Qt::ApplicationShortcut);
- RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"),
- Qt::ApplicationShortcut);
- LoadHotkeys();
-
- connect(GetHotkey("Main Window", "Load File", this), &QShortcut::activated, this,
- &GMainWindow::OnMenuLoadFile);
- connect(GetHotkey("Main Window", "Start Emulation", this), &QShortcut::activated, this,
- &GMainWindow::OnStartGame);
- connect(GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated, this, [&] {
- if (emulation_running) {
- if (emu_thread->IsRunning()) {
- OnPauseGame();
- } else {
- OnStartGame();
- }
- }
- });
- connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated,
- ui.action_Fullscreen, &QAction::trigger);
- connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously,
- ui.action_Fullscreen, &QAction::trigger);
- connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] {
- if (emulation_running) {
- ui.action_Fullscreen->setChecked(false);
- ToggleFullscreen();
- }
- });
- connect(GetHotkey("Main Window", "Toggle Speed Limit", this), &QShortcut::activated, this, [&] {
- Settings::values.toggle_framelimit = !Settings::values.toggle_framelimit;
- UpdateStatusBar();
- });
+ hotkey_registry.RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
+ hotkey_registry.RegisterHotkey("Main Window", "Start Emulation");
+ hotkey_registry.RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4));
+ hotkey_registry.RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen);
+ hotkey_registry.RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape),
+ Qt::ApplicationShortcut);
+ hotkey_registry.RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"),
+ Qt::ApplicationShortcut);
+ hotkey_registry.LoadHotkeys();
+
+ connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated,
+ this, &GMainWindow::OnMenuLoadFile);
+ connect(hotkey_registry.GetHotkey("Main Window", "Start Emulation", this),
+ &QShortcut::activated, this, &GMainWindow::OnStartGame);
+ connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated,
+ this, [&] {
+ if (emulation_running) {
+ if (emu_thread->IsRunning()) {
+ OnPauseGame();
+ } else {
+ OnStartGame();
+ }
+ }
+ });
+ connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window),
+ &QShortcut::activated, ui.action_Fullscreen, &QAction::trigger);
+ connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window),
+ &QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger);
+ connect(hotkey_registry.GetHotkey("Main Window", "Exit Fullscreen", this),
+ &QShortcut::activated, this, [&] {
+ if (emulation_running) {
+ ui.action_Fullscreen->setChecked(false);
+ ToggleFullscreen();
+ }
+ });
+ connect(hotkey_registry.GetHotkey("Main Window", "Toggle Speed Limit", this),
+ &QShortcut::activated, this, [&] {
+ Settings::values.toggle_framelimit = !Settings::values.toggle_framelimit;
+ UpdateStatusBar();
+ });
}
void GMainWindow::SetDefaultUIGeometry() {
@@ -321,7 +329,8 @@ void GMainWindow::ConnectMenuEvents() {
connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
// Fullscreen
- ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key());
+ ui.action_Fullscreen->setShortcut(
+ hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key());
connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
// Help
@@ -400,6 +409,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
}
Core::System& system{Core::System::GetInstance()};
+ system.SetFilesystem(vfs);
system.SetGPUDebugContext(debug_context);
@@ -414,67 +424,11 @@ bool GMainWindow::LoadROM(const QString& filename) {
QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("The ROM format is not supported."));
break;
- case Core::System::ResultStatus::ErrorUnsupportedArch:
- LOG_CRITICAL(Frontend, "Unsupported architecture detected!", filename.toStdString());
- QMessageBox::critical(this, tr("Error while loading ROM!"),
- tr("The ROM uses currently unusable 32-bit architecture"));
- break;
case Core::System::ResultStatus::ErrorSystemMode:
LOG_CRITICAL(Frontend, "Failed to load ROM!");
QMessageBox::critical(this, tr("Error while loading ROM!"),
tr("Could not determine the system mode."));
break;
-
- case Core::System::ResultStatus::ErrorLoader_ErrorMissingKeys: {
- const auto reg_found = Core::Crypto::KeyManager::KeyFileExists(false);
- const auto title_found = Core::Crypto::KeyManager::KeyFileExists(true);
-
- std::string file_text;
-
- if (!reg_found && !title_found) {
- file_text = "A proper key file (prod.keys, dev.keys, or title.keys) could not be "
- "found. You will need to dump your keys from your switch to continue.";
- } else if (reg_found && title_found) {
- file_text =
- "Both key files were found in your config directory, but the correct key could"
- "not be found. You may be missing a titlekey or general key, depending on "
- "the game.";
- } else if (reg_found) {
- file_text =
- "The regular keys file (prod.keys/dev.keys) was found in your config, but the "
- "titlekeys file (title.keys) was not. You are either missing the correct "
- "titlekey or missing a general key required to decrypt the game.";
- } else {
- file_text = "The title keys file (title.keys) was found in your config, but "
- "the regular keys file (prod.keys/dev.keys) was not. Unfortunately, "
- "having the titlekey is not enough, you need additional general keys "
- "to properly decrypt the game. You should double-check to make sure "
- "your keys are correct.";
- }
-
- QMessageBox::critical(
- this, tr("Error while loading ROM!"),
- tr(("The game you are trying to load is encrypted and the required keys to load "
- "the game could not be found in your configuration. " +
- file_text + " Please refer to the yuzu wiki for help.")
- .c_str()));
- break;
- }
- case Core::System::ResultStatus::ErrorLoader_ErrorDecrypting: {
- QMessageBox::critical(
- this, tr("Error while loading ROM!"),
- tr("There was a general error while decrypting the game. This means that the keys "
- "necessary were found, but were either incorrect, the game itself was not a "
- "valid game or the game uses an unhandled cryptographic scheme. Please double "
- "check that you have the correct "
- "keys."));
- break;
- }
- case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
- QMessageBox::critical(this, tr("Error while loading ROM!"),
- tr("The ROM format is not supported."));
- break;
-
case Core::System::ResultStatus::ErrorVideoCore:
QMessageBox::critical(
this, tr("An error occurred initializing the video core."),
@@ -489,9 +443,23 @@ bool GMainWindow::LoadROM(const QString& filename) {
break;
default:
- QMessageBox::critical(
- this, tr("Error while loading ROM!"),
- tr("An unknown error occurred. Please see the log for more details."));
+ if (static_cast<u32>(result) >
+ static_cast<u32>(Core::System::ResultStatus::ErrorLoader)) {
+ LOG_CRITICAL(Frontend, "Failed to load ROM!");
+ const u16 loader_id = static_cast<u16>(Core::System::ResultStatus::ErrorLoader);
+ const u16 error_id = static_cast<u16>(result) - loader_id;
+ QMessageBox::critical(
+ this, tr("Error while loading ROM!"),
+ QString::fromStdString(fmt::format(
+ "While attempting to load the ROM requested, an error occured. Please "
+ "refer to the yuzu wiki for more information or the yuzu discord for "
+ "additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}",
+ loader_id, error_id, Loader::GetMessageForResultStatus(error_id))));
+ } else {
+ QMessageBox::critical(
+ this, tr("Error while loading ROM!"),
+ tr("An unknown error occurred. Please see the log for more details."));
+ }
break;
}
return false;
@@ -579,11 +547,11 @@ void GMainWindow::StoreRecentFile(const QString& filename) {
}
void GMainWindow::UpdateRecentFiles() {
- unsigned int num_recent_files =
- std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item));
+ const int num_recent_files =
+ std::min(UISettings::values.recent_files.size(), max_recent_files_item);
- for (unsigned int i = 0; i < num_recent_files; i++) {
- QString text = QString("&%1. %2").arg(i + 1).arg(
+ for (int i = 0; i < num_recent_files; i++) {
+ const QString text = QString("&%1. %2").arg(i + 1).arg(
QFileInfo(UISettings::values.recent_files[i]).fileName());
actions_recent_files[i]->setText(text);
actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
@@ -595,12 +563,8 @@ void GMainWindow::UpdateRecentFiles() {
actions_recent_files[j]->setVisible(false);
}
- // Grey out the recent files menu if the list is empty
- if (num_recent_files == 0) {
- ui.menu_recent_files->setEnabled(false);
- } else {
- ui.menu_recent_files->setEnabled(true);
- }
+ // Enable the recent files menu if the list isn't empty
+ ui.menu_recent_files->setEnabled(num_recent_files != 0);
}
void GMainWindow::OnGameListLoadFile(QString game_path) {
@@ -631,9 +595,15 @@ void GMainWindow::OnMenuLoadFile() {
}
void GMainWindow::OnMenuLoadFolder() {
- QDir dir = QFileDialog::getExistingDirectory(this, tr("Open Extracted ROM Directory"));
+ const QString dir_path =
+ QFileDialog::getExistingDirectory(this, tr("Open Extracted ROM Directory"));
+
+ if (dir_path.isNull()) {
+ return;
+ }
- QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files);
+ const QDir dir{dir_path};
+ const QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files);
if (matching_main.size() == 1) {
BootGame(dir.path() + DIR_SEP + matching_main[0]);
} else {
@@ -654,9 +624,8 @@ void GMainWindow::OnMenuRecentFile() {
QAction* action = qobject_cast<QAction*>(sender());
assert(action);
- QString filename = action->data().toString();
- QFileInfo file_info(filename);
- if (file_info.exists()) {
+ const QString filename = action->data().toString();
+ if (QFileInfo::exists(filename)) {
BootGame(filename);
} else {
// Display an error message and remove the file from the list.
@@ -754,13 +723,14 @@ void GMainWindow::ToggleWindowMode() {
}
void GMainWindow::OnConfigure() {
- ConfigureDialog configureDialog(this);
+ ConfigureDialog configureDialog(this, hotkey_registry);
auto old_theme = UISettings::values.theme;
auto result = configureDialog.exec();
if (result == QDialog::Accepted) {
configureDialog.applyConfiguration();
if (UISettings::values.theme != old_theme)
UpdateUITheme();
+ game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
config->Save();
}
}
@@ -893,7 +863,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
UISettings::values.first_start = false;
game_list->SaveInterfaceLayout();
- SaveHotkeys();
+ hotkey_registry.SaveHotkeys();
// Shutdown session if the emu thread is active...
if (emu_thread != nullptr)
@@ -947,15 +917,14 @@ void GMainWindow::UpdateUITheme() {
QStringList theme_paths(default_theme_paths);
if (UISettings::values.theme != UISettings::themes[0].second &&
!UISettings::values.theme.isEmpty()) {
- QString theme_uri(":" + UISettings::values.theme + "/style.qss");
+ const QString theme_uri(":" + UISettings::values.theme + "/style.qss");
QFile f(theme_uri);
- if (!f.exists()) {
- LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
- } else {
- f.open(QFile::ReadOnly | QFile::Text);
+ if (f.open(QFile::ReadOnly | QFile::Text)) {
QTextStream ts(&f);
qApp->setStyleSheet(ts.readAll());
GMainWindow::setStyleSheet(ts.readAll());
+ } else {
+ LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
}
theme_paths.append(QStringList{":/icons/default", ":/icons/" + UISettings::values.theme});
QIcon::setThemeName(":/icons/" + UISettings::values.theme);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 074bba3f9..74487c58c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -9,6 +9,7 @@
#include <QTimer>
#include "core/core.h"
#include "ui_main.h"
+#include "yuzu/hotkeys.h"
class Config;
class EmuThread;
@@ -43,7 +44,7 @@ public:
void filterBarSetChecked(bool state);
void UpdateUITheme();
GMainWindow();
- ~GMainWindow();
+ ~GMainWindow() override;
signals:
@@ -160,6 +161,9 @@ private:
bool emulation_running = false;
std::unique_ptr<EmuThread> emu_thread;
+ // FS
+ FileSys::VirtualFilesystem vfs;
+
// Debugger panes
ProfilerWidget* profilerWidget;
MicroProfileDialog* microProfileDialog;
@@ -172,6 +176,8 @@ private:
// stores default icon theme search paths for the platform
QStringList default_theme_paths;
+ HotkeyRegistry hotkey_registry;
+
protected:
void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index 2286c2559..051494bc5 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -54,6 +54,12 @@ struct Values {
// logging
bool show_console;
+
+ // Game List
+ bool show_unknown;
+ uint32_t icon_size;
+ uint8_t row_1_text_id;
+ uint8_t row_2_text_id;
};
extern Values values;
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 1d835c3c6..d34902109 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -10,7 +10,7 @@
struct SDL_Window;
-class EmuWindow_SDL2 : public EmuWindow {
+class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
public:
explicit EmuWindow_SDL2(bool fullscreen);
~EmuWindow_SDL2();
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index d637dbd0c..e44a98311 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -161,6 +161,7 @@ int main(int argc, char** argv) {
}
Core::System& system{Core::System::GetInstance()};
+ system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
SCOPE_EXIT({ system.Shutdown(); });
@@ -173,19 +174,6 @@ int main(int argc, char** argv) {
case Core::System::ResultStatus::ErrorLoader:
LOG_CRITICAL(Frontend, "Failed to load ROM!");
return -1;
- case Core::System::ResultStatus::ErrorLoader_ErrorMissingKeys:
- LOG_CRITICAL(Frontend, "The game you are trying to load is encrypted and the keys required "
- "could not be found. Please refer to the yuzu wiki for help");
- return -1;
- case Core::System::ResultStatus::ErrorLoader_ErrorDecrypting:
- LOG_CRITICAL(Frontend, "The game you are trying to load is encrypted and there was a "
- "general error while decrypting. This could mean that the keys are "
- "incorrect, game is invalid or game uses an unsupported method of "
- "crypto. Please double-check your keys");
- return -1;
- case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
- LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported.");
- return -1;
case Core::System::ResultStatus::ErrorNotInitialized:
LOG_CRITICAL(Frontend, "CPUCore not initialized");
return -1;
@@ -197,6 +185,17 @@ int main(int argc, char** argv) {
return -1;
case Core::System::ResultStatus::Success:
break; // Expected case
+ default:
+ if (static_cast<u32>(load_result) >
+ static_cast<u32>(Core::System::ResultStatus::ErrorLoader)) {
+ const u16 loader_id = static_cast<u16>(Core::System::ResultStatus::ErrorLoader);
+ const u16 error_id = static_cast<u16>(load_result) - loader_id;
+ LOG_CRITICAL(Frontend,
+ "While attempting to load the ROM requested, an error occured. Please "
+ "refer to the yuzu wiki for more information or the yuzu discord for "
+ "additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}",
+ loader_id, error_id, Loader::GetMessageForResultStatus(error_id));
+ }
}
Core::Telemetry().AddField(Telemetry::FieldType::App, "Frontend", "SDL");