[
  {
    "path": ".clang-format",
    "content": "---\nLanguage:        Cpp\n# BasedOnStyle:  LLVM\nAccessModifierOffset: -2\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: true\nAlignConsecutiveDeclarations: true\nAlignEscapedNewlines: Left\nAlignOperands:   true\nAlignTrailingComments: true\nAllowAllParametersOfDeclarationOnNextLine: true\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: None\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakAfterReturnType: None\nAlwaysBreakBeforeMultilineStrings: false\nAlwaysBreakTemplateDeclarations: true\nBinPackArguments: true\nBinPackParameters: true\nBraceWrapping:\n  AfterClass:      true\n  AfterControlStatement: true\n  AfterEnum:       true\n  AfterFunction:   true\n  AfterNamespace:  true\n  AfterObjCDeclaration: true\n  AfterStruct:     true\n  AfterUnion:      true\n  AfterExternBlock: true\n  BeforeCatch:     true\n  BeforeElse:      true\n  IndentBraces:    false\n  SplitEmptyFunction: false\n  SplitEmptyRecord: false\n  SplitEmptyNamespace: false\nBreakBeforeBinaryOperators: None\nBreakBeforeBraces: Custom\nBreakBeforeInheritanceComma: false\nBreakBeforeTernaryOperators: false\nBreakConstructorInitializersBeforeComma: false\nBreakConstructorInitializers: AfterColon\nBreakAfterJavaFieldAnnotations: false\nBreakStringLiterals: true\nColumnLimit:     0\nCommentPragmas:  '^ IWYU pragma:'\nCompactNamespaces: false\nConstructorInitializerAllOnOneLineOrOnePerLine: true\nConstructorInitializerIndentWidth: 4\nContinuationIndentWidth: 4\nCpp11BracedListStyle: true\nDerivePointerAlignment: false\nDisableFormat:   false\nExperimentalAutoDetectBinPacking: false\nFixNamespaceComments: true\nForEachMacros:\n  - foreach\n  - Q_FOREACH\n  - BOOST_FOREACH\nIncludeBlocks:   Preserve\nIncludeIsMainRegex: '(Test)?$'\nIndentCaseLabels: true\nIndentPPDirectives: AfterHash\nIndentWidth:     4\nIndentWrappedFunctionNames: true\nJavaScriptQuotes: Leave\nJavaScriptWrapImports: true\nKeepEmptyLinesAtTheStartOfBlocks: false\nMacroBlockBegin: ''\nMacroBlockEnd:   ''\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nObjCBinPackProtocolList: Auto\nObjCBlockIndentWidth: 2\nObjCSpaceAfterProperty: false\nObjCSpaceBeforeProtocolList: true\nPenaltyBreakAssignment: 2\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakString: 1000\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 60\nPointerAlignment: Right\nReflowComments:  true\nSortIncludes:    true\nSortUsingDeclarations: true\nSpaceAfterCStyleCast: true\nSpaceAfterTemplateKeyword: true\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeCtorInitializerColon: true\nSpaceBeforeInheritanceColon: true\nSpaceBeforeParens: ControlStatements\nSpaceBeforeRangeBasedForLoopColon: true\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 8\nSpacesInAngles:  false\nSpacesInContainerLiterals: false\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard:        Cpp11\nTabWidth:        4\nUseTab:          ForIndentation\n...\n"
  },
  {
    "path": ".clang-tidy",
    "content": "Checks: '-*,\n    misc-throw-by-value-catch-by-reference,\n    misc-misplaced-const,\n    misc-unconventional-assign-operator,\n    misc-redundant-expression,\n    misc-static-assert,\n    misc-unconventional-assign-operator,\n    misc-uniqueptr-reset-release,\n    misc-unused-alias-decls,\n    misc-unused-parameters,\n    misc-unused-using-decls,\n\n    modernize-avoid-bind,\n    modernize-loop-convert,\n    modernize-make-shared,\n    modernize-make-unique,\n    modernize-raw-string-literal,\n    modernize-redundant-void-arg,\n    modernize-replace-auto-ptr,\n    modernize-replace-random-shuffle,\n    modernize-use-bool-literals,\n    modernize-use-nullptr,\n    modernize-use-using,\n    modernize-use-equals-default,\n    modernize-use-equals-delete,\n\n    performance-faster-string-find,\n    performance-for-range-copy,\n    performance-implicit-conversion-in-loop,\n    performance-inefficient-algorithm,\n    performance-inefficient-vector-operation,\n    performance-move-constructor-init,\n    performance-no-automatic-move,\n    performance-trivially-destructible,\n    performance-unnecessary-copy-initialization,\n\n    readability-avoid-const-params-in-decls,\n    readability-const-return-type,\n    readability-container-size-empty,\n    readability-convert-member-functions-to-static,\n    readability-delete-null-pointer,\n    readability-deleted-default,\n    readability-make-member-function-const,\n    readability-misplaced-array-index,\n    readability-non-const-parameter,\n    readability-qualified-auto,\n    readability-redundant-access-specifiers,\n    readability-redundant-control-flow,\n    readability-redundant-function-ptr-dereference,\n    readability-redundant-smartptr-get,\n    readability-redundant-string-cstr,\n    readability-redundant-string-init,\n    readability-static-definition-in-anonymous-namespace,\n    readability-string-compare,\n    readability-uniqueptr-delete-release,\n    readability-redundant-member-init,\n    readability-simplify-subscript-expr,\n    readability-simplify-boolean-expr,\n    readability-inconsistent-declaration-parameter-name,\n    readability-identifier-naming,\n\n    bugprone-undelegated-constructor,\n    bugprone-argument-comment,\n    bugprone-bad-signal-to-kill-thread,\n    bugprone-bool-pointer-implicit-conversion,\n    bugprone-copy-constructor-init,\n    bugprone-dangling-handle,\n    bugprone-forward-declaration-namespace,\n    bugprone-fold-init-type,\n    bugprone-inaccurate-erase,\n    bugprone-incorrect-roundings,\n    bugprone-infinite-loop,\n    bugprone-integer-division,\n    bugprone-macro-parentheses,\n    bugprone-macro-repeated-side-effects,\n    bugprone-misplaced-operator-in-strlen-in-alloc,\n    bugprone-misplaced-pointer-artithmetic-in-alloc,\n    bugprone-misplaced-widening-cast,\n    bugprone-move-forwarding-reference,\n    bugprone-multiple-statement-macro,\n    bugprone-parent-virtual-call,\n    bugprone-posix-return,\n    bugprone-reserved-identifier,\n    bugprone-signed-char-misuse,\n    bugprone-sizeof-container,\n    bugprone-sizeof-expression,\n    bugprone-string-constructor,\n    bugprone-string-integer-assignment,\n    bugprone-string-literal-with-embedded-nul,\n    bugprone-suspicious-enum-usage,\n    bugprone-suspicious-include,\n    bugprone-suspicious-memset-usage,\n    bugprone-suspicious-missing-comma,\n    bugprone-suspicious-string-compare,\n    bugprone-swapped-arguments,\n    bugprone-terminating-continue,\n    bugprone-throw-keyword-missing,\n    bugprone-too-small-loop-variable,\n    bugprone-undefined-memory-manipulation,\n    bugprone-unhandled-self-assignment,\n    bugprone-unused-raii,\n    bugprone-unused-return-value,\n    bugprone-use-after-move,\n    bugprone-virtual-near-miss,\n\n    cert-dcl21-cpp,\n    cert-dcl50-cpp,\n    cert-env33-c,\n    cert-err34-c,\n    cert-err52-cpp,\n    cert-flp30-c,\n    cert-mem57-cpp,\n    cert-msc50-cpp,\n    cert-oop58-cpp,\n\n    google-build-explicit-make-pair,\n    google-build-namespaces,\n    google-default-arguments,\n    google-explicit-constructor,\n    google-readability-casting,\n    google-readability-avoid-underscore-in-googletest-name,\n    google-runtime-int,\n    google-runtime-operator,\n\n    hicpp-exception-baseclass,\n\n    clang-analyzer-core.CallAndMessage,\n    clang-analyzer-core.DivideZero,\n    clang-analyzer-core.NonNullParamChecker,\n    clang-analyzer-core.NullDereference,\n    clang-analyzer-core.StackAddressEscape,\n    clang-analyzer-core.UndefinedBinaryOperatorResult,\n    clang-analyzer-core.VLASize,\n    clang-analyzer-core.uninitialized.ArraySubscript,\n    clang-analyzer-core.uninitialized.Assign,\n    clang-analyzer-core.uninitialized.Branch,\n    clang-analyzer-core.uninitialized.CapturedBlockVariable,\n    clang-analyzer-core.uninitialized.UndefReturn,\n    clang-analyzer-cplusplus.InnerPointer,\n    clang-analyzer-cplusplus.NewDelete,\n    clang-analyzer-cplusplus.NewDeleteLeaks,\n    clang-analyzer-cplusplus.PlacementNewChecker,\n    clang-analyzer-cplusplus.SelfAssignment,\n    clang-analyzer-deadcode.DeadStores,\n    clang-analyzer-optin.cplusplus.VirtualCall,\n    clang-analyzer-security.insecureAPI.UncheckedReturn,\n    clang-analyzer-security.insecureAPI.bcmp,\n    clang-analyzer-security.insecureAPI.bcopy,\n    clang-analyzer-security.insecureAPI.bzero,\n    clang-analyzer-security.insecureAPI.getpw,\n    clang-analyzer-security.insecureAPI.gets,\n    clang-analyzer-security.insecureAPI.mkstemp,\n    clang-analyzer-security.insecureAPI.mktemp,\n    clang-analyzer-security.insecureAPI.rand,\n    clang-analyzer-security.insecureAPI.strcpy,\n    clang-analyzer-unix.Malloc,\n    clang-analyzer-unix.MallocSizeof,\n    clang-analyzer-unix.MismatchedDeallocator,\n    clang-analyzer-unix.Vfork,\n    clang-analyzer-unix.cstring.BadSizeArg,\n    clang-analyzer-unix.cstring.NullArg,\n\n    boost-use-to-string,\n'\nWarningsAsErrors: '*'\n\nCheckOptions:\n  - key: readability-identifier-naming.ClassCase\n    value: CamelCase\n  - key: readability-identifier-naming.EnumCase\n    value: CamelCase\n  - key: readability-identifier-naming.LocalVariableCase\n    value: lower_case\n  - key: readability-identifier-naming.StaticConstantCase\n    value: aNy_CasE\n  - key: readability-identifier-naming.MemberCase\n    value: lower_case\n  - key: readability-identifier-naming.ClassMemberPrefix\n    value: m_\n  - key: readability-identifier-naming.PrivateMemberPrefix\n    value: ''\n  - key: readability-identifier-naming.ProtectedMemberPrefix\n    value: ''\n  - key: readability-identifier-naming.PublicMemberCase\n    value: lower_case\n  - key: readability-identifier-naming.MethodCase\n    value: camelBack\n  - key: readability-identifier-naming.PrivateMethodPrefix\n    value: ''\n  - key: readability-identifier-naming.ProtectedMethodPrefix\n    value: ''\n  - key: readability-identifier-naming.ParameterPackCase\n    value: lower_case\n  - key: readability-identifier-naming.StructCase\n    value: CamelCase\n  - key: readability-identifier-naming.TemplateTemplateParameterCase\n    value: CamelCase\n  - key: readability-identifier-naming.TemplateUsingCase\n    value: lower_case\n  - key: readability-identifier-naming.TypeTemplateParameterCase\n    value: CamelCase\n  - key: readability-identifier-naming.TypedefCase\n    value: CamelCase\n  - key: readability-identifier-naming.UnionCase\n    value: CamelCase\n  - key: readability-identifier-naming.UsingCase\n    value: CamelCase"
  },
  {
    "path": ".github/workflows/windows_dev.yml",
    "content": "name: Windows_dev\n\non:\n  pull_request:\n    types: [dev]\n  push:\n    branches: [dev]\n\njobs:\n  build:\n    runs-on: \"windows-latest\"\n    steps:\n      - uses: actions/checkout@v2\n        with:\n          submodules: \"recursive\"\n      \n      - uses: Jimver/cuda-toolkit@v0.2.8\n        id: cuda-toolkit\n        with:\n          cuda: '11.7.0'\n          sub-packages: '[\"nvcc\", \"visual_studio_integration\", \"cudart\"]'\n\n      - uses: xmake-io/github-action-setup-xmake@v1\n        with:\n          xmake-version: latest\n          actions-cache-folder: \".xmake-cache\"\n\n      - name: Build\n        run: xmake -y"
  },
  {
    "path": ".github/workflows/windows_main.yml",
    "content": "name: Windows_main\n\non:\n  pull_request:\n    types: [main]\n  push:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: \"windows-latest\"\n    steps:\n      - uses: actions/checkout@v2\n        with:\n          submodules: \"recursive\"\n      \n      - uses: Jimver/cuda-toolkit@v0.2.8\n        id: cuda-toolkit\n        with:\n          cuda: '11.7.0'\n          sub-packages: '[\"nvcc\", \"visual_studio_integration\", \"cudart\"]'\n\n      - uses: xmake-io/github-action-setup-xmake@v1\n        with:\n          xmake-version: latest\n          actions-cache-folder: \".xmake-cache\"\n\n      - name: Build\n        run: xmake -y"
  },
  {
    "path": ".gitignore",
    "content": "# Prerequisites\n*.d\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n*.dll\n\n# Fortran module files\n*.mod\n*.smod\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n*.lib\n\n# Executables\n*.exe\n*.out\n*.app\n*.spv\n\n# Folders\n/build/*\n/bin/*\n/lib/*\n/shared/*\n\n**/Archive/*\n\n*.meta\n\n.vscode\n.xmake/\nbuild/\nvsxmake**"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"Source/Dependencies\"]\n\tpath = Source/Dependencies\n\turl = https://github.com/Chaf-Libraries/Dependencies\n"
  },
  {
    "path": "Asset/Meta/README.md",
    "content": ""
  },
  {
    "path": "Asset/MustacheTemplate/Reflection.mustache",
    "content": "{{#Header}}\n{{&Include}}\n{{/Header}}\n\nnamespace Ilum_{{Hash}}\n{\nRTTR_REGISTRATION\n{\n    {{#Enum}}\n    rttr::registration::enumeration<{{EnumQualifiedName}}>(\"{{EnumName}}\")\n    (\n        {{#EnumValue}}\n        rttr::value(\"{{EnumValueName}}\", {{EnumValueQualifiedName}}){{^IsLast}},{{/IsLast}}\n        {{/EnumValue}}  \n    );\n    {{/Enum}}\n    {{#Class}}\n    rttr::registration::class_<{{ClassQualifiedName}}>(\"{{ClassName}}\"){{#Meta}}({{#MetaData}}rttr::metadata(\"{{&Key}}\", {{&Value}}){{^IsLast}}, {{/IsLast}}{{/MetaData}}){{/Meta}}\n    {{#Field}}\n        .property(\"{{FieldName}}\", &{{FieldQualifiedName}}, rttr::registration::{{#Public}}public_access{{/Public}}{{#Private}}private_access{{/Private}}{{#Protected}}protected_access{{/Protected}}){{#Meta}}({{#MetaData}}rttr::metadata(\"{{&Key}}\", {{&Value}}){{^IsLast}}, {{/IsLast}}{{/MetaData}}){{/Meta}}\n    {{/Field}}\n    {{#Constructor}}\n        {{^Static}}.constructor<{{#Params}}{{&Param}}{{^IsLast}}, {{/IsLast}}{{/Params}}>(){{/Static}}{{#Static}}.constructor(&{{MethodQualifiedName}}){{/Static}}(rttr::policy::ctor::as_object)\n    {{/Constructor}}\n    {{#NoConstructor}}\n        .constructor<>()(rttr::policy::ctor::as_object)\n    {{/NoConstructor}}\n    {{#Method}}\n        .method(\"{{&MethodName}}\", {{^Overload}}&{{&MethodQualifiedName}}{{/Overload}}{{#Overload}}{{^Const}}rttr::select_overload<{{&ReturnType}}({{#Params}}{{&Param}}{{^IsLast}}, {{/IsLast}}{{/Params}})>{{/Const}}{{#Const}}rttr::select_const<{{&ClassQualifiedName}}, {{&ReturnType}}, {{#Params}}{{&Param}}{{^IsLast}}, {{/IsLast}}{{/Params}}>{{/Const}}(&{{&MethodQualifiedName}}){{/Overload}}, rttr::registration::{{#Public}}public_access{{/Public}}{{#Private}}private_access{{/Private}}{{#Protected}}protected_access{{/Protected}}){{#Meta}}({{#MetaData}}rttr::metadata(\"{{&Key}}\", {{&Value}}){{^IsLast}}, {{/IsLast}}{{/MetaData}}){{/Meta}}\n    {{/Method}}\n    ;\n    {{/Class}}\n}\n}"
  },
  {
    "path": "Asset/NRD_Data/Sample/blur_buffer.csv",
    "content": "﻿gViewToClip,\"[1.0000, 0.0000, 0.0000, 0.0000]\n[0.0000, 1.7778, 0.0000, 0.0000]\n[-0.0000, -0.0000, 1.0000, 1.0000]\n[0.0000, 0.0000, -0.0010, 0.0000]\"\ngViewToWorld,\"[-0.9997, -0.0236, -0.0000, 0.0000]\n[0.0031, -0.1315, 0.9913, 0.0000]\n[0.0234, -0.9910, -0.1315, 0.0000]\n[0.0000, 0.0000, 0.0000, 1.0000]\"\ngFrustum,\"[-1.0000, 0.5625, 2.0000, -1.1250]\"\ngHitDistParams,\"[3.0000, 0.1000, 20.0000, -25.0000]\"\ngViewVectorWorld,\"[-0.0234, 0.9910, 0.1315, 0.0000]\"\ngViewVectorWorldPrev,\"[-0.0234, 0.9910, 0.1315, 0.0000]\"\ngInvScreenSize,\"[0.0008, 0.0014]\"\ngScreenSize,\"[1280.0000, 720.0000]\"\ngInvRectSize,\"[0.0008, 0.0014]\"\ngRectSize,\"[1280.0000, 720.0000]\"\ngRectSizePrev,\"[1280.0000, 720.0000]\"\ngResolutionScale,\"[1.0000, 1.0000]\"\ngRectOffset,\"[0.0000, 0.0000]\"\ngSensitivityToDarkness,\"[0.0100, 0.1000]\"\ngRectOrigin,\"[0, 0]\"\ngReference,0.0000\ngOrthoMode,0.0000\ngUnproject,0.0016\ngDebug,0.0000\ngDenoisingRange,60.6960\ngPlaneDistSensitivity,0.0050\ngFramerateScale,0.5000\ngBlurRadius,30.0000\ngMaxAccumulatedFrameNum,1.0000\ngMaxFastAccumulatedFrameNum,0.0000\ngAntiFirefly,0.0000\ngMinConvergedStateBaseRadiusScale,0.2500\ngLobeAngleFraction,0.1000\ngRoughnessFraction,0.0500\ngResponsiveAccumulationRoughnessThreshold,0.0000\ngDiffPrepassBlurRadius,30.0000\ngSpecPrepassBlurRadius,50.0000\ngIsWorldSpaceMotionEnabled,1\ngFrameIndex,42372\ngResetHistory,0\ngDiffMaterialMask,1\ngSpecMaterialMask,0\ngRotator,\"[0.2651, -0.9642, 0.9642, 0.2651]\"\ngSpecLobeTrimmingParams,\"[0.9500, 0.0400, 0.1100]\"\ngBlurRadiusScale,5.0000\n"
  },
  {
    "path": "Asset/NRD_Data/Sample/history_fix_buffer.csv",
    "content": "﻿gViewToClip,\"[1.0000, 0.0000, 0.0000, 0.0000]\n[0.0000, 1.7778, 0.0000, 0.0000]\n[-0.0000, -0.0000, 1.0000, 1.0000]\n[0.0000, 0.0000, -0.0010, 0.0000]\",-\ngViewToWorld,\"[-0.9997, -0.0236, -0.0000, 0.0000]\n[0.0031, -0.1315, 0.9913, 0.0000]\n[0.0234, -0.9910, -0.1315, 0.0000]\n[0.0000, 0.0000, 0.0000, 1.0000]\",-\ngFrustum,\"[-1.0000, 0.5625, 2.0000, -1.1250]\",-\ngHitDistParams,\"[3.0000, 0.1000, 20.0000, -25.0000]\",-\ngViewVectorWorld,\"[-0.0234, 0.9910, 0.1315, 0.0000]\",-\ngViewVectorWorldPrev,\"[-0.0234, 0.9910, 0.1315, 0.0000]\",-\ngInvScreenSize,\"[0.0008, 0.0014]\",-\ngScreenSize,\"[1280.0000, 720.0000]\",-\ngInvRectSize,\"[0.0008, 0.0014]\",-\ngRectSize,\"[1280.0000, 720.0000]\",-\ngRectSizePrev,\"[1280.0000, 720.0000]\",-\ngResolutionScale,\"[1.0000, 1.0000]\",-\ngRectOffset,\"[0.0000, 0.0000]\",-\ngSensitivityToDarkness,\"[0.0100, 0.1000]\",-\ngRectOrigin,\"[0, 0]\",-\ngReference,0.0000,-\ngOrthoMode,0.0000,-\ngUnproject,0.0016,-\ngDebug,0.0000,-\ngDenoisingRange,60.6960,-\ngPlaneDistSensitivity,0.0050,-\ngFramerateScale,0.5000,-\ngBlurRadius,30.0000,-\ngMaxAccumulatedFrameNum,1.0000,-\ngMaxFastAccumulatedFrameNum,0.0000,-\ngAntiFirefly,0.0000,-\ngMinConvergedStateBaseRadiusScale,0.2500,-\ngLobeAngleFraction,0.1000,-\ngRoughnessFraction,0.0500,-\ngResponsiveAccumulationRoughnessThreshold,0.0000,-\ngDiffPrepassBlurRadius,30.0000,-\ngSpecPrepassBlurRadius,50.0000,-\ngIsWorldSpaceMotionEnabled,1,-\ngFrameIndex,42372,-\ngResetHistory,0,-\ngDiffMaterialMask,1,-\ngSpecMaterialMask,0,-\ngHistoryFixStrength,1.0000,-\n"
  },
  {
    "path": "Asset/NRD_Data/Sample/post_blur_buffer.csv",
    "content": "﻿gViewToClip,gViewToWorld,gFrustum,gHitDistParams,gViewVectorWorld,gViewVectorWorldPrev,gInvScreenSize,gScreenSize,gInvRectSize,gRectSize,gRectSizePrev,gResolutionScale,gRectOffset,gSensitivityToDarkness,gRectOrigin,gReference,gOrthoMode,gUnproject,gDebug,gDenoisingRange,gPlaneDistSensitivity,gFramerateScale,gBlurRadius,gMaxAccumulatedFrameNum,gMaxFastAccumulatedFrameNum,gAntiFirefly,gMinConvergedStateBaseRadiusScale,gLobeAngleFraction,gRoughnessFraction,gResponsiveAccumulationRoughnessThreshold,gDiffPrepassBlurRadius,gSpecPrepassBlurRadius,gIsWorldSpaceMotionEnabled,gFrameIndex,gResetHistory,gDiffMaterialMask,gSpecMaterialMask,gRotator,gSpecLobeTrimmingParams,gBlurRadiusScale\n\"[1.0000, 0.0000, 0.0000, 0.0000]\n[0.0000, 1.7778, 0.0000, 0.0000]\n[-0.0000, -0.0000, 1.0000, 1.0000]\n[0.0000, 0.0000, -0.0010, 0.0000]\",\"[-0.9997, -0.0236, -0.0000, 0.0000]\n[0.0031, -0.1315, 0.9913, 0.0000]\n[0.0234, -0.9910, -0.1315, 0.0000]\n[0.0000, 0.0000, 0.0000, 1.0000]\",\"[-1.0000, 0.5625, 2.0000, -1.1250]\",\"[3.0000, 0.1000, 20.0000, -25.0000]\",\"[-0.0234, 0.9910, 0.1315, 0.0000]\",\"[-0.0234, 0.9910, 0.1315, 0.0000]\",\"[0.0008, 0.0014]\",\"[1280.0000, 720.0000]\",\"[0.0008, 0.0014]\",\"[1280.0000, 720.0000]\",\"[1280.0000, 720.0000]\",\"[1.0000, 1.0000]\",\"[0.0000, 0.0000]\",\"[0.0100, 0.1000]\",\"[0, 0]\",0.0000,0.0000,0.0016,0.0000,60.6960,0.0050,0.5000,30.0000,1.0000,0.0000,0.0000,0.2500,0.1000,0.0500,0.0000,30.0000,50.0000,1,42372,0,1,0,\"[-0.9642, -0.2651, 0.2651, -0.9642]\",\"[0.9500, 0.0400, 0.1100]\",5.0000\n"
  },
  {
    "path": "Asset/NRD_Data/Sample/temporal_accumulate_buffer.csv",
    "content": "﻿gViewToClip,\"[1.0000, 0.0000, 0.0000, 0.0000]\n[0.0000, 1.7778, 0.0000, 0.0000]\n[-0.0000, -0.0000, 1.0000, 1.0000]\n[0.0000, 0.0000, -0.0010, 0.0000]\",-\ngViewToWorld,\"[-0.9997, -0.0236, -0.0000, 0.0000]\n[0.0031, -0.1315, 0.9913, 0.0000]\n[0.0234, -0.9910, -0.1315, 0.0000]\n[0.0000, 0.0000, 0.0000, 1.0000]\",-\ngFrustum,\"[-1.0000, 0.5625, 2.0000, -1.1250]\",-\ngHitDistParams,\"[3.0000, 0.1000, 20.0000, -25.0000]\",-\ngViewVectorWorld,\"[-0.0234, 0.9910, 0.1315, 0.0000]\",-\ngViewVectorWorldPrev,\"[-0.0234, 0.9910, 0.1315, 0.0000]\",-\ngInvScreenSize,\"[0.0008, 0.0014]\",-\ngScreenSize,\"[1280.0000, 720.0000]\",-\ngInvRectSize,\"[0.0008, 0.0014]\",-\ngRectSize,\"[1280.0000, 720.0000]\",-\ngRectSizePrev,\"[1280.0000, 720.0000]\",-\ngResolutionScale,\"[1.0000, 1.0000]\",-\ngRectOffset,\"[0.0000, 0.0000]\",-\ngSensitivityToDarkness,\"[0.0100, 0.1000]\",-\ngRectOrigin,\"[0, 0]\",-\ngReference,0.0000,-\ngOrthoMode,0.0000,-\ngUnproject,0.0016,-\ngDebug,0.0000,-\ngDenoisingRange,60.6960,-\ngPlaneDistSensitivity,0.0050,-\ngFramerateScale,0.5000,-\ngBlurRadius,30.0000,-\ngMaxAccumulatedFrameNum,1.0000,-\ngMaxFastAccumulatedFrameNum,0.0000,-\ngAntiFirefly,0.0000,-\ngMinConvergedStateBaseRadiusScale,0.2500,-\ngLobeAngleFraction,0.1000,-\ngRoughnessFraction,0.0500,-\ngResponsiveAccumulationRoughnessThreshold,0.0000,-\ngDiffPrepassBlurRadius,30.0000,-\ngSpecPrepassBlurRadius,50.0000,-\ngIsWorldSpaceMotionEnabled,1,-\ngFrameIndex,42372,-\ngResetHistory,0,-\ngDiffMaterialMask,1,-\ngSpecMaterialMask,0,-\ngWorldToViewPrev,\"[-0.9997, 0.0031, 0.0234, 0.0000]\n[-0.0236, -0.1315, -0.9910, 0.0000]\n[-0.0000, 0.9913, -0.1315, 0.0000]\n[0.0000, -0.0000, -0.0000, 1.0000]\",-\ngWorldToClipPrev,\"[-0.9997, 0.0055, 0.0234, 0.0234]\n[-0.0236, -0.2337, -0.9910, -0.9910]\n[0.0000, 1.7623, -0.1315, -0.1315]\n[0.0000, 0.0000, -0.0010, 0.0000]\",-\ngWorldToClip,\"[-0.9997, 0.0055, 0.0234, 0.0234]\n[-0.0236, -0.2337, -0.9910, -0.9910]\n[0.0000, 1.7623, -0.1315, -0.1315]\n[0.0000, 0.0000, -0.0010, 0.0000]\",-\ngWorldPrevToWorld,\"[1.0000, 0.0000, 0.0000, 0.0000]\n[0.0000, 1.0000, 0.0000, 0.0000]\n[0.0000, 0.0000, 1.0000, 0.0000]\n[0.0000, 0.0000, 0.0000, 1.0000]\",-\ngFrustumPrev,\"[-1.0000, 0.5625, 2.0000, -1.1250]\",-\ngCameraDelta,\"[0.0000, 0.0000, 0.0000, 0.0000]\",-\ngRotator,\"[-0.5868, 0.8098, -0.8098, -0.5868]\",-\ngMotionVectorScale,\"[1.0000, 1.0000]\",-\ngCheckerboardResolveAccumSpeed,0.6447,-\ngDisocclusionThreshold,0.0071,-\ngDiffCheckerboard,2,-\ngSpecCheckerboard,2,-\ngIsPrepassEnabled,0,-\n"
  },
  {
    "path": "Asset/SPD/metals/Ag.eta.spd",
    "content": "298.757050 1.519000\n302.400421 1.496000\n306.133759 1.432500\n309.960449 1.323000\n313.884003 1.142062\n317.908142 0.932000\n322.036835 0.719062\n326.274139 0.526000\n330.624481 0.388125\n335.092377 0.294000\n339.682678 0.253313\n344.400482 0.238000\n349.251221 0.221438\n354.240509 0.209000\n359.374420 0.194813\n364.659332 0.186000\n370.102020 0.192063\n375.709625 0.200000\n381.489777 0.198063\n387.450562 0.192000\n393.600555 0.182000\n399.948975 0.173000\n406.505493 0.172625\n413.280579 0.173000\n420.285339 0.166688\n427.531647 0.160000\n435.032196 0.158500\n442.800629 0.157000\n450.851562 0.151063\n459.200653 0.144000\n467.864838 0.137313\n476.862213 0.132000\n486.212463 0.130250\n495.936707 0.130000\n506.057861 0.129938\n516.600769 0.130000\n527.592224 0.130063\n539.061646 0.129000\n551.040771 0.124375\n563.564453 0.120000\n576.670593 0.119313\n590.400818 0.121000\n604.800842 0.125500\n619.920898 0.131000\n635.816284 0.136125\n652.548279 0.140000\n670.184753 0.140063\n688.800964 0.140000\n708.481018 0.144313\n729.318665 0.148000\n751.419250 0.145875\n774.901123 0.143000\n799.897949 0.142563\n826.561157 0.145000\n855.063293 0.151938\n885.601257 0.163000\n"
  },
  {
    "path": "Asset/SPD/metals/Ag.k.spd",
    "content": "298.757050 1.080000\n302.400421 0.882000\n306.133759 0.761063\n309.960449 0.647000\n313.884003 0.550875\n317.908142 0.504000\n322.036835 0.554375\n326.274139 0.663000\n330.624481 0.818563\n335.092377 0.986000\n339.682678 1.120687\n344.400482 1.240000\n349.251221 1.345250\n354.240509 1.440000\n359.374420 1.533750\n364.659332 1.610000\n370.102020 1.641875\n375.709625 1.670000\n381.489777 1.735000\n387.450562 1.810000\n393.600555 1.878750\n399.948975 1.950000\n406.505493 2.029375\n413.280579 2.110000\n420.285339 2.186250\n427.531647 2.260000\n435.032196 2.329375\n442.800629 2.400000\n450.851562 2.478750\n459.200653 2.560000\n467.864838 2.640000\n476.862213 2.720000\n486.212463 2.798125\n495.936707 2.880000\n506.057861 2.973750\n516.600769 3.070000\n527.592224 3.159375\n539.061646 3.250000\n551.040771 3.348125\n563.564453 3.450000\n576.670593 3.553750\n590.400818 3.660000\n604.800842 3.766250\n619.920898 3.880000\n635.816284 4.010625\n652.548279 4.150000\n670.184753 4.293125\n688.800964 4.440000\n708.481018 4.586250\n729.318665 4.740000\n751.419250 4.908125\n774.901123 5.090000\n799.897949 5.288750\n826.561157 5.500000\n855.063293 5.720624\n885.601257 5.950000\n"
  },
  {
    "path": "Asset/SPD/metals/Al.eta.spd",
    "content": "298.757050 0.273375\n302.400421 0.280000\n306.133759 0.286813\n309.960449 0.294000\n313.884003 0.301875\n317.908142 0.310000\n322.036835 0.317875\n326.274139 0.326000\n330.624481 0.334750\n335.092377 0.344000\n339.682678 0.353813\n344.400482 0.364000\n349.251221 0.374375\n354.240509 0.385000\n359.374420 0.395750\n364.659332 0.407000\n370.102020 0.419125\n375.709625 0.432000\n381.489777 0.445688\n387.450562 0.460000\n393.600555 0.474688\n399.948975 0.490000\n406.505493 0.506188\n413.280579 0.523000\n420.285339 0.540063\n427.531647 0.558000\n435.032196 0.577313\n442.800629 0.598000\n450.851562 0.620313\n459.200653 0.644000\n467.864838 0.668625\n476.862213 0.695000\n486.212463 0.723750\n495.936707 0.755000\n506.057861 0.789000\n516.600769 0.826000\n527.592224 0.867000\n539.061646 0.912000\n551.040771 0.963000\n563.564453 1.020000\n576.670593 1.080000\n590.400818 1.150000\n604.800842 1.220000\n619.920898 1.300000\n635.816284 1.390000\n652.548279 1.490000\n670.184753 1.600000\n688.800964 1.740000\n708.481018 1.910000\n729.318665 2.140000\n751.419250 2.410000\n774.901123 2.630000\n799.897949 2.800000\n826.561157 2.740000\n855.063293 2.580000\n885.601257 2.240000\n"
  },
  {
    "path": "Asset/SPD/metals/Al.k.spd",
    "content": "298.757050 3.593750\n302.400421 3.640000\n306.133759 3.689375\n309.960449 3.740000\n313.884003 3.789375\n317.908142 3.840000\n322.036835 3.894375\n326.274139 3.950000\n330.624481 4.005000\n335.092377 4.060000\n339.682678 4.113750\n344.400482 4.170000\n349.251221 4.233750\n354.240509 4.300000\n359.374420 4.365000\n364.659332 4.430000\n370.102020 4.493750\n375.709625 4.560000\n381.489777 4.633750\n387.450562 4.710000\n393.600555 4.784375\n399.948975 4.860000\n406.505493 4.938125\n413.280579 5.020000\n420.285339 5.108750\n427.531647 5.200000\n435.032196 5.290000\n442.800629 5.380000\n450.851562 5.480000\n459.200653 5.580000\n467.864838 5.690000\n476.862213 5.800000\n486.212463 5.915000\n495.936707 6.030000\n506.057861 6.150000\n516.600769 6.280000\n527.592224 6.420000\n539.061646 6.550000\n551.040771 6.700000\n563.564453 6.850000\n576.670593 7.000000\n590.400818 7.150000\n604.800842 7.310000\n619.920898 7.480000\n635.816284 7.650000\n652.548279 7.820000\n670.184753 8.010000\n688.800964 8.210000\n708.481018 8.390000\n729.318665 8.570000\n751.419250 8.620000\n774.901123 8.600000\n799.897949 8.450000\n826.561157 8.310000\n855.063293 8.210000\n885.601257 8.210000\n"
  },
  {
    "path": "Asset/SPD/metals/AlAs.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for cubic AlAs\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 4.470000\n309.950012 4.920000\n317.897003 5.350000\n326.263000 5.390000\n335.081024 4.990000\n344.389008 4.720000\n354.229004 4.480000\n364.647003 4.300000\n375.696991 4.130000\n387.437988 3.930000\n393.587006 0.000000\n397.372009 0.000000\n399.935028 0.000000\n403.187012 0.000000\n406.492004 0.000000\n409.850983 0.000000\n413.266998 0.000000\n416.739990 0.000000\n420.270996 0.000000\n423.863007 0.000000\n427.516998 0.000000\n431.235016 0.000000\n435.018036 0.000000\n442.785980 3.703000\n459.185028 3.570000\n476.846008 3.472000\n495.920013 3.394000\n516.583008 3.329000\n539.044006 3.273000\n563.545044 3.225000\n590.381042 3.183000\n619.900024 3.145000\n652.526001 3.112000\n688.778015 3.082000\n729.294006 3.056000\n774.875000 3.032000\n826.533020 3.010000\n885.570984 2.990000\n"
  },
  {
    "path": "Asset/SPD/metals/AlAs.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for cubic AlAs\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 2.680000\n309.950012 2.490000\n317.897003 2.150000\n326.263000 1.300000\n335.081024 0.752000\n344.389008 0.519000\n354.229004 0.334000\n364.647003 0.233000\n375.696991 0.139000\n387.437988 0.115000\n393.587006 0.119000\n397.372009 0.115000\n399.935028 0.113000\n403.187012 0.110000\n406.492004 0.106000\n409.850983 0.099800\n413.266998 0.063800\n416.739990 0.031500\n420.270996 0.018900\n423.863007 0.011800\n427.516998 0.010500\n431.235016 0.010300\n435.018036 0.009930\n442.785980 0.001610\n459.185028 0.001560\n476.846008 0.001530\n495.920013 0.001250\n516.583008 0.000682\n539.044006 0.000275\n563.545044 0.000040\n590.381042 0.000002\n619.900024 0.000000\n652.526001 0.000000\n688.778015 0.000000\n729.294006 0.000000\n774.875000 0.000000\n826.533020 0.000000\n885.570984 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/AlSb.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for cubic AlSb\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 3.150000\n309.950012 3.500000\n317.897003 3.710000\n326.263000 3.810000\n335.081024 3.930000\n344.389008 3.960000\n354.229004 3.950000\n364.647003 3.970000\n375.696991 4.140000\n387.437988 4.510000\n399.935028 4.570000\n413.266998 4.520000\n427.516998 4.660000\n442.785980 5.270000\n459.185028 5.080000\n476.846008 4.810000\n495.920013 4.610000\n516.583008 4.440000\n539.044006 4.310000\n563.545044 4.200000\n590.381042 4.010000\n"
  },
  {
    "path": "Asset/SPD/metals/AlSb.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for cubic AlSb\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 4.000000\n309.950012 3.710000\n317.897003 3.400000\n326.263000 3.160000\n335.081024 2.970000\n344.389008 2.810000\n354.229004 2.690000\n364.647003 2.640000\n375.696991 2.690000\n387.437988 2.470000\n399.935028 2.120000\n413.266998 1.970000\n427.516998 2.060000\n442.785980 1.580000\n459.185028 0.920000\n476.846008 0.630000\n495.920013 0.460000\n516.583008 0.330000\n539.044006 0.240000\n563.545044 0.010000\n590.381042 0.006000\n"
  },
  {
    "path": "Asset/SPD/metals/Au.eta.spd",
    "content": "298.757050 1.795000\n302.400421 1.812000\n306.133759 1.822625\n309.960449 1.830000\n313.884003 1.837125\n317.908142 1.840000\n322.036835 1.834250\n326.274139 1.824000\n330.624481 1.812000\n335.092377 1.798000\n339.682678 1.782000\n344.400482 1.766000\n349.251221 1.752500\n354.240509 1.740000\n359.374420 1.727625\n364.659332 1.716000\n370.102020 1.705875\n375.709625 1.696000\n381.489777 1.684750\n387.450562 1.674000\n393.600555 1.666000\n399.948975 1.658000\n406.505493 1.647250\n413.280579 1.636000\n420.285339 1.628000\n427.531647 1.616000\n435.032196 1.596250\n442.800629 1.562000\n450.851562 1.502125\n459.200653 1.426000\n467.864838 1.345875\n476.862213 1.242000\n486.212463 1.086750\n495.936707 0.916000\n506.057861 0.754500\n516.600769 0.608000\n527.592224 0.491750\n539.061646 0.402000\n551.040771 0.345500\n563.564453 0.306000\n576.670593 0.267625\n590.400818 0.236000\n604.800842 0.212375\n619.920898 0.194000\n635.816284 0.177750\n652.548279 0.166000\n670.184753 0.161000\n688.800964 0.160000\n708.481018 0.160875\n729.318665 0.164000\n751.419250 0.169500\n774.901123 0.176000\n799.897949 0.181375\n826.561157 0.188000\n855.063293 0.198125\n885.601257 0.210000\n"
  },
  {
    "path": "Asset/SPD/metals/Au.k.spd",
    "content": "298.757050 1.920375\n302.400421 1.920000\n306.133759 1.918875\n309.960449 1.916000\n313.884003 1.911375\n317.908142 1.904000\n322.036835 1.891375\n326.274139 1.878000\n330.624481 1.868250\n335.092377 1.860000\n339.682678 1.851750\n344.400482 1.846000\n349.251221 1.845250\n354.240509 1.848000\n359.374420 1.852375\n364.659332 1.862000\n370.102020 1.883000\n375.709625 1.906000\n381.489777 1.922500\n387.450562 1.936000\n393.600555 1.947750\n399.948975 1.956000\n406.505493 1.959375\n413.280579 1.958000\n420.285339 1.951375\n427.531647 1.940000\n435.032196 1.924500\n442.800629 1.904000\n450.851562 1.875875\n459.200653 1.846000\n467.864838 1.814625\n476.862213 1.796000\n486.212463 1.797375\n495.936707 1.840000\n506.057861 1.956500\n516.600769 2.120000\n527.592224 2.326250\n539.061646 2.540000\n551.040771 2.730625\n563.564453 2.880000\n576.670593 2.940625\n590.400818 2.970000\n604.800842 3.015000\n619.920898 3.060000\n635.816284 3.070000\n652.548279 3.150000\n670.184753 3.445812\n688.800964 3.800000\n708.481018 4.087687\n729.318665 4.357000\n751.419250 4.610188\n774.901123 4.860000\n799.897949 5.125813\n826.561157 5.390000\n855.063293 5.631250\n885.601257 5.880000\n"
  },
  {
    "path": "Asset/SPD/metals/Be.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for polycrystalline Be\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  Be_llnl_cxro + Be_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n310.000000 2.470000\n326.300018 2.550000\n344.399994 2.640000\n364.600006 2.730000\n387.399994 2.840000\n413.300018 2.950000\n442.800018 3.070000\n476.800018 3.190000\n516.600037 3.300000\n563.500000 3.390000\n619.900024 3.460000\n688.799988 3.470000\n774.900024 3.440000\n885.600037 3.350000\n"
  },
  {
    "path": "Asset/SPD/metals/Be.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for polycrystalline Be\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  Be_llnl_cxro + Be_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n310.000000 3.080000\n326.300018 3.080000\n344.399994 3.080000\n364.600006 3.100000\n387.399994 3.120000\n413.300018 3.140000\n442.800018 3.160000\n476.800018 3.160000\n516.600037 3.180000\n563.500000 3.170000\n619.900024 3.180000\n688.799988 3.230000\n774.900024 3.350000\n885.600037 3.550000\n"
  },
  {
    "path": "Asset/SPD/metals/Cr.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Cr\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  Cr_llnl_cxro + Cr_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n300.194000 0.980000\n307.643005 1.020000\n316.276001 1.060000\n323.708008 1.120000\n333.279999 1.180000\n341.542999 1.260000\n351.217987 1.330000\n362.514984 1.390000\n372.312012 1.430000\n385.031006 1.440000\n396.102020 1.480000\n409.175018 1.540000\n424.589020 1.650000\n438.092010 1.800000\n455.808990 1.990000\n471.406982 2.220000\n490.040009 2.490000\n512.314026 2.750000\n532.102966 2.980000\n558.468018 3.180000\n582.066040 3.340000\n610.739014 3.480000\n700.452026 3.840000\n815.658020 4.230000\n826.533020 4.270000\n849.178040 4.310000\n860.971985 4.330000\n885.570984 4.380000\n"
  },
  {
    "path": "Asset/SPD/metals/Cr.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Cr\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  Cr_llnl_cxro + Cr_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n300.194000 2.670000\n307.643005 2.760000\n316.276001 2.850000\n323.708008 2.950000\n333.279999 3.040000\n341.542999 3.120000\n351.217987 3.180000\n362.514984 3.240000\n372.312012 3.310000\n385.031006 3.400000\n396.102020 3.540000\n409.175018 3.710000\n424.589020 3.890000\n438.092010 4.060000\n455.808990 4.220000\n471.406982 4.360000\n490.040009 4.440000\n512.314026 4.460000\n532.102966 4.450000\n558.468018 4.410000\n582.066040 4.380000\n610.739014 4.360000\n700.452026 4.370000\n815.658020 4.340000\n826.533020 4.330000\n849.178040 4.320000\n860.971985 4.320000\n885.570984 4.310000\n"
  },
  {
    "path": "Asset/SPD/metals/CsI.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for CsI\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  CsI_llnl_cxro + CsI_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n304.993988 1.967310\n309.950012 1.956510\n314.989990 1.946580\n319.947998 1.937410\n324.980011 1.928930\n329.997009 1.921060\n334.990997 1.913730\n339.951019 1.906900\n344.963989 1.900510\n350.028015 1.894530\n354.937988 1.888910\n359.988007 1.883630\n364.968994 1.878660\n369.979004 1.873970\n375.014984 1.869540\n379.957001 1.865350\n385.031006 1.861380\n389.997009 1.857620\n394.967010 1.854040\n399.935028 1.850640\n409.987030 1.844330\n419.985992 1.838590\n430.037994 1.833360\n439.957001 1.828570\n450.018036 1.824170\n460.037018 1.820120\n469.977020 1.816370\n479.985016 1.812910\n490.040009 1.809700\n499.919006 1.806720\n509.996002 1.803930\n520.049988 1.801340\n530.056030 1.798910\n539.983032 1.796640\n550.044006 1.794510\n559.981995 1.792500\n570.023010 1.790620\n579.888000 1.788840\n590.100037 1.787170\n600.097046 1.785590\n619.900024 1.782680\n640.062012 1.780060\n659.819031 1.777700\n680.088013 1.775570\n700.056030 1.773630\n719.976990 1.771860\n740.179016 1.770250\n760.147034 1.768770\n779.747986 1.767410\n799.871033 1.766150\n819.974060 1.765000\n839.973083 1.763920\n859.778015 1.762930\n879.915039 1.762010\n899.709961 1.761150\n"
  },
  {
    "path": "Asset/SPD/metals/CsI.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for CsI\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  CsI_llnl_cxro + CsI_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n304.993988 0.000000\n309.950012 0.000000\n314.989990 0.000000\n319.947998 0.000000\n324.980011 0.000000\n329.997009 0.000000\n334.990997 0.000000\n339.951019 0.000000\n344.963989 0.000000\n350.028015 0.000000\n354.937988 0.000000\n359.988007 0.000000\n364.968994 0.000000\n369.979004 0.000000\n375.014984 0.000000\n379.957001 0.000000\n385.031006 0.000000\n389.997009 0.000000\n394.967010 0.000000\n399.935028 0.000000\n409.987030 0.000000\n419.985992 0.000000\n430.037994 0.000000\n439.957001 0.000000\n450.018036 0.000000\n460.037018 0.000000\n469.977020 0.000000\n479.985016 0.000000\n490.040009 0.000000\n499.919006 0.000000\n509.996002 0.000000\n520.049988 0.000000\n530.056030 0.000000\n539.983032 0.000000\n550.044006 0.000000\n559.981995 0.000000\n570.023010 0.000000\n579.888000 0.000000\n590.100037 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n680.088013 0.000000\n700.056030 0.000000\n719.976990 0.000000\n740.179016 0.000000\n760.147034 0.000000\n779.747986 0.000000\n799.871033 0.000000\n819.974060 0.000000\n839.973083 0.000000\n859.778015 0.000000\n879.915039 0.000000\n899.709961 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/Cu.eta.spd",
    "content": "298.757050 1.400313\n302.400421 1.380000\n306.133759 1.358438\n309.960449 1.340000\n313.884003 1.329063\n317.908142 1.325000\n322.036835 1.332500\n326.274139 1.340000\n330.624481 1.334375\n335.092377 1.325000\n339.682678 1.317812\n344.400482 1.310000\n349.251221 1.300313\n354.240509 1.290000\n359.374420 1.281563\n364.659332 1.270000\n370.102020 1.249062\n375.709625 1.225000\n381.489777 1.200000\n387.450562 1.180000\n393.600555 1.174375\n399.948975 1.175000\n406.505493 1.177500\n413.280579 1.180000\n420.285339 1.178125\n427.531647 1.175000\n435.032196 1.172812\n442.800629 1.170000\n450.851562 1.165312\n459.200653 1.160000\n467.864838 1.155312\n476.862213 1.150000\n486.212463 1.142812\n495.936707 1.135000\n506.057861 1.131562\n516.600769 1.120000\n527.592224 1.092437\n539.061646 1.040000\n551.040771 0.950375\n563.564453 0.826000\n576.670593 0.645875\n590.400818 0.468000\n604.800842 0.351250\n619.920898 0.272000\n635.816284 0.230813\n652.548279 0.214000\n670.184753 0.209250\n688.800964 0.213000\n708.481018 0.216250\n729.318665 0.223000\n751.419250 0.236500\n774.901123 0.250000\n799.897949 0.254188\n826.561157 0.260000\n855.063293 0.280000\n885.601257 0.300000\n"
  },
  {
    "path": "Asset/SPD/metals/Cu.k.spd",
    "content": "298.757050 1.662125\n302.400421 1.687000\n306.133759 1.703313\n309.960449 1.720000\n313.884003 1.744563\n317.908142 1.770000\n322.036835 1.791625\n326.274139 1.810000\n330.624481 1.822125\n335.092377 1.834000\n339.682678 1.851750\n344.400482 1.872000\n349.251221 1.894250\n354.240509 1.916000\n359.374420 1.931688\n364.659332 1.950000\n370.102020 1.972438\n375.709625 2.015000\n381.489777 2.121562\n387.450562 2.210000\n393.600555 2.177188\n399.948975 2.130000\n406.505493 2.160063\n413.280579 2.210000\n420.285339 2.249938\n427.531647 2.289000\n435.032196 2.326000\n442.800629 2.362000\n450.851562 2.397625\n459.200653 2.433000\n467.864838 2.469187\n476.862213 2.504000\n486.212463 2.535875\n495.936707 2.564000\n506.057861 2.589625\n516.600769 2.605000\n527.592224 2.595562\n539.061646 2.583000\n551.040771 2.576500\n563.564453 2.599000\n576.670593 2.678062\n590.400818 2.809000\n604.800842 3.010750\n619.920898 3.240000\n635.816284 3.458187\n652.548279 3.670000\n670.184753 3.863125\n688.800964 4.050000\n708.481018 4.239563\n729.318665 4.430000\n751.419250 4.619563\n774.901123 4.817000\n799.897949 5.034125\n826.561157 5.260000\n855.063293 5.485625\n885.601257 5.717000\n"
  },
  {
    "path": "Asset/SPD/metals/Cu2O.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Cu2O\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Cu2O_llnl_cxro + Cu2O_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n350.028015 2.400000\n399.935028 2.800000\n449.854980 3.060000\n499.919006 3.120000\n549.799988 3.100000\n599.806030 3.020000\n649.789978 2.900000\n700.056030 2.830000\n750.029968 2.770000\n799.871033 2.700000\n849.759949 2.660000\n899.709961 2.630000\n"
  },
  {
    "path": "Asset/SPD/metals/Cu2O.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Cu2O\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Cu2O_llnl_cxro + Cu2O_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n350.028015 1.440000\n399.935028 0.990000\n449.854980 0.600000\n499.919006 0.350000\n549.799988 0.190000\n599.806030 0.130000\n649.789978 0.100000\n700.056030 0.083000\n750.029968 0.070000\n799.871033 0.060000\n849.759949 0.053000\n899.709961 0.048000\n"
  },
  {
    "path": "Asset/SPD/metals/CuO.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for CuO\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  CuO_llnl_cxro + CuO_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n350.028015 2.240000\n399.935028 2.340000\n449.854980 2.450000\n499.919006 2.540000\n549.799988 2.580000\n599.806030 2.650000\n649.789978 2.720000\n700.056030 2.880000\n750.029968 2.970000\n799.871033 2.940000\n849.759949 2.810000\n899.709961 2.740000\n"
  },
  {
    "path": "Asset/SPD/metals/CuO.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for CuO\n# ;  \n# ;  Concatenation of:\n# ;  \n# ;  CuO_llnl_cxro + CuO_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n350.028015 1.030000\n399.935028 0.870000\n449.854980 0.770000\n499.919006 0.680000\n549.799988 0.590000\n599.806030 0.500000\n649.789978 0.400000\n700.056030 0.310000\n750.029968 0.220000\n799.871033 0.110000\n849.759949 0.040000\n899.709961 0.030000\n"
  },
  {
    "path": "Asset/SPD/metals/Hg.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Hg\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Hg_llnl_cxro + Hg_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 0.542000\n326.263000 0.589000\n344.389008 0.644000\n364.647003 0.713000\n387.437988 0.798000\n413.266998 0.898000\n442.785980 1.027000\n476.846008 1.186000\n516.583008 1.384000\n563.545044 1.620000\n619.900024 1.910000\n688.778015 2.284000\n774.875000 2.746000\n885.570984 3.324000\n"
  },
  {
    "path": "Asset/SPD/metals/Hg.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Hg\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Hg_llnl_cxro + Hg_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.502000\n326.263000 2.665000\n344.389008 2.860000\n364.647003 3.074000\n387.437988 3.294000\n413.266998 3.538000\n442.785980 3.802000\n476.846008 4.090000\n516.583008 4.407000\n563.545044 4.751000\n619.900024 5.150000\n688.778015 5.582000\n774.875000 6.054000\n885.570984 6.558000\n"
  },
  {
    "path": "Asset/SPD/metals/HgTe.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for HgTe\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n300.921997 2.481000\n302.243011 2.480000\n303.575012 2.479000\n304.919006 2.478000\n306.274994 2.476000\n307.643005 2.475000\n309.023010 2.474000\n310.415985 2.473000\n311.821014 2.471000\n313.238983 2.470000\n314.670013 2.470000\n316.113983 2.469000\n317.571991 2.468000\n319.042999 2.468000\n320.610016 2.467000\n322.110016 2.467000\n323.623016 2.467000\n325.151001 2.467000\n326.692993 2.467000\n328.250000 2.466000\n329.821991 2.467000\n331.409027 2.467000\n333.011017 2.467000\n334.628998 2.467000\n336.263000 2.468000\n337.912018 2.469000\n339.578003 2.470000\n341.261017 2.470000\n343.055023 2.472000\n344.772003 2.473000\n346.506012 2.474000\n348.258026 2.476000\n350.028015 2.478000\n351.816010 2.480000\n353.622009 2.481000\n355.446991 2.484000\n357.290985 2.487000\n359.154022 2.489000\n361.037018 2.492000\n362.938995 2.495000\n364.862030 2.499000\n366.805023 2.502000\n368.878021 2.506000\n370.864990 2.510000\n372.872009 2.515000\n374.902008 2.520000\n376.953003 2.525000\n379.028015 2.530000\n381.125000 2.536000\n383.246002 2.542000\n385.389984 2.548000\n387.559021 2.555000\n389.752014 2.563000\n391.970001 2.570000\n394.212982 2.578000\n396.482025 2.587000\n398.906006 2.596000\n401.230011 2.606000\n403.581024 2.616000\n405.959015 2.627000\n408.365997 2.639000\n410.802002 2.651000\n413.266998 2.664000\n415.760986 2.678000\n418.285980 2.694000\n420.842010 2.710000\n423.429016 2.727000\n426.048004 2.746000\n428.700012 2.768000\n431.535004 2.790000\n434.256012 2.816000\n437.010986 2.844000\n439.800995 2.874000\n442.627991 2.908000\n445.489990 2.945000\n448.391022 2.983000\n451.329010 3.020000\n454.306000 3.056000\n457.322021 3.088000\n460.378998 3.115000\n463.477020 3.138000\n466.616028 3.159000\n469.799042 3.175000\n473.206024 3.190000\n476.479980 3.203000\n479.799042 3.214000\n483.164032 3.223000\n486.577972 3.231000\n490.040009 3.239000\n493.550995 3.245000\n497.113007 3.252000\n500.727020 3.259000\n504.394012 3.265000\n508.114990 3.272000\n511.891022 3.279000\n515.724060 3.287000\n519.614014 3.294000\n523.785034 3.303000\n527.799011 3.313000\n531.875000 3.324000\n536.014038 3.335000\n540.218018 3.349000\n544.487976 3.364000\n548.827026 3.382000\n553.235046 3.402000\n557.715027 3.425000\n562.268005 3.454000\n566.895020 3.488000\n571.600037 3.532000\n576.382996 3.586000\n581.247009 3.650000\n586.471008 3.719000\n591.507996 3.785000\n596.631042 3.838000\n601.845032 3.876000\n607.150024 3.901000\n612.549011 3.917000\n618.046021 3.925000\n623.642029 3.929000\n629.340027 3.929000\n635.143005 3.924000\n641.054993 3.919000\n647.077026 3.911000\n653.214050 3.903000\n659.468018 3.892000\n666.200989 3.882000\n672.708008 3.870000\n679.341980 3.860000\n686.110046 3.848000\n693.013000 3.837000\n700.056030 3.826000\n707.245056 3.815000\n714.581970 3.805000\n722.072998 3.795000\n729.723022 3.786000\n737.537048 3.776000\n745.520020 3.767000\n753.677979 3.756000\n762.016052 3.747000\n771.020020 3.738000\n779.747986 3.729000\n788.677002 3.719000\n797.812012 3.711000\n807.161011 3.702000\n816.733032 3.691000\n826.533020 3.685000\n"
  },
  {
    "path": "Asset/SPD/metals/HgTe.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for HgTe\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n300.921997 1.782000\n302.243011 1.771000\n303.575012 1.761000\n304.919006 1.752000\n306.274994 1.744000\n307.643005 1.736000\n309.023010 1.729000\n310.415985 1.722000\n311.821014 1.716000\n313.238983 1.711000\n314.670013 1.706000\n316.113983 1.701000\n317.571991 1.697000\n319.042999 1.693000\n320.610016 1.690000\n322.110016 1.687000\n323.623016 1.684000\n325.151001 1.681000\n326.692993 1.679000\n328.250000 1.677000\n329.821991 1.675000\n331.409027 1.674000\n333.011017 1.673000\n334.628998 1.672000\n336.263000 1.672000\n337.912018 1.671000\n339.578003 1.671000\n341.261017 1.671000\n343.055023 1.672000\n344.772003 1.673000\n346.506012 1.674000\n348.258026 1.675000\n350.028015 1.677000\n351.816010 1.679000\n353.622009 1.681000\n355.446991 1.683000\n357.290985 1.686000\n359.154022 1.689000\n361.037018 1.692000\n362.938995 1.696000\n364.862030 1.699000\n366.805023 1.703000\n368.878021 1.707000\n370.864990 1.712000\n372.872009 1.716000\n374.902008 1.722000\n376.953003 1.727000\n379.028015 1.732000\n381.125000 1.738000\n383.246002 1.743000\n385.389984 1.750000\n387.559021 1.756000\n389.752014 1.763000\n391.970001 1.770000\n394.212982 1.777000\n396.482025 1.784000\n398.906006 1.792000\n401.230011 1.800000\n403.581024 1.808000\n405.959015 1.816000\n408.365997 1.825000\n410.802002 1.834000\n413.266998 1.844000\n415.760986 1.853000\n418.285980 1.863000\n420.842010 1.873000\n423.429016 1.883000\n426.048004 1.893000\n428.700012 1.904000\n431.535004 1.914000\n434.256012 1.924000\n437.010986 1.933000\n439.800995 1.940000\n442.627991 1.945000\n445.489990 1.946000\n448.391022 1.942000\n451.329010 1.932000\n454.306000 1.917000\n457.322021 1.898000\n460.378998 1.877000\n463.477020 1.856000\n466.616028 1.833000\n469.799042 1.812000\n473.206024 1.791000\n476.479980 1.771000\n479.799042 1.753000\n483.164032 1.736000\n486.577972 1.721000\n490.040009 1.707000\n493.550995 1.695000\n497.113007 1.683000\n500.727020 1.674000\n504.394012 1.665000\n508.114990 1.658000\n511.891022 1.653000\n515.724060 1.647000\n519.614014 1.644000\n523.785034 1.641000\n527.799011 1.641000\n531.875000 1.640000\n536.014038 1.642000\n540.218018 1.645000\n544.487976 1.649000\n548.827026 1.653000\n553.235046 1.660000\n557.715027 1.668000\n562.268005 1.677000\n566.895020 1.687000\n571.600037 1.696000\n576.382996 1.700000\n581.247009 1.694000\n586.471008 1.670000\n591.507996 1.626000\n596.631042 1.569000\n601.845032 1.507000\n607.150024 1.443000\n612.549011 1.382000\n618.046021 1.325000\n623.642029 1.272000\n629.340027 1.222000\n635.143005 1.176000\n641.054993 1.134000\n647.077026 1.094000\n653.214050 1.058000\n659.468018 1.024000\n666.200989 0.992300\n672.708008 0.964200\n679.341980 0.935800\n686.110046 0.910700\n693.013000 0.886300\n700.056030 0.863300\n707.245056 0.841900\n714.581970 0.822600\n722.072998 0.802400\n729.723022 0.782800\n737.537048 0.764400\n745.520020 0.747400\n753.677979 0.735100\n762.016052 0.722500\n771.020020 0.709700\n779.747986 0.695700\n788.677002 0.686400\n797.812012 0.671600\n807.161011 0.660000\n816.733032 0.655200\n826.533020 0.638200\n"
  },
  {
    "path": "Asset/SPD/metals/Ir.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Ir\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Ir_llnl_cxro + Ir_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 1.620000\n309.950012 1.640000\n317.897003 1.640000\n326.263000 1.610000\n335.081024 1.570000\n344.389008 1.520000\n354.229004 1.500000\n364.647003 1.530000\n375.696991 1.570000\n387.437988 1.620000\n399.935028 1.680000\n413.266998 1.730000\n427.516998 1.770000\n442.785980 1.810000\n459.185028 1.850000\n476.846008 1.910000\n495.920013 1.980000\n516.583008 2.070000\n539.044006 2.180000\n563.545044 2.290000\n590.381042 2.400000\n619.900024 2.500000\n652.526001 2.570000\n688.778015 2.640000\n729.294006 2.690000\n774.875000 2.680000\n826.533020 2.650000\n885.570984 2.720000\n"
  },
  {
    "path": "Asset/SPD/metals/Ir.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Ir\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Ir_llnl_cxro + Ir_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 2.700000\n309.950012 2.680000\n317.897003 2.670000\n326.263000 2.690000\n335.081024 2.720000\n344.389008 2.810000\n354.229004 2.930000\n364.647003 3.050000\n375.696991 3.150000\n387.437988 3.260000\n399.935028 3.350000\n413.266998 3.430000\n427.516998 3.510000\n442.785980 3.610000\n459.185028 3.730000\n476.846008 3.860000\n495.920013 4.000000\n516.583008 4.140000\n539.044006 4.260000\n563.545044 4.380000\n590.381042 4.480000\n619.900024 4.570000\n652.526001 4.680000\n688.778015 4.810000\n729.294006 4.920000\n774.875000 5.080000\n826.533020 5.390000\n885.570984 5.740000\n"
  },
  {
    "path": "Asset/SPD/metals/K.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for polycrystalline K\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n304.993988 0.380000\n309.950012 0.340000\n312.291992 0.287000\n334.178009 0.089000\n364.647003 0.052000\n405.162994 0.041000\n420.270996 0.041000\n439.645020 0.043000\n469.621002 0.043000\n506.041016 0.046000\n546.166992 0.049000\n598.937012 0.053000\n662.995056 0.050000\n751.393982 0.044000\n860.971985 0.040000\n"
  },
  {
    "path": "Asset/SPD/metals/K.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for polycrystalline K\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n304.993988 0.070000\n309.950012 0.080000\n312.291992 0.091000\n334.178009 0.288000\n364.647003 0.549000\n405.162994 0.799000\n420.270996 0.898000\n439.645020 1.020000\n469.621002 1.140000\n506.041016 1.280000\n546.166992 1.430000\n598.937012 1.620000\n662.995056 1.840000\n751.393982 2.190000\n860.971985 2.560000\n"
  },
  {
    "path": "Asset/SPD/metals/KBr.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for cubic KBr\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n310.027008 1.638860\n320.031006 1.630710\n329.997009 1.623570\n339.951019 1.617270\n350.028015 1.611670\n359.988007 1.606680\n369.979004 1.602200\n379.957001 1.598160\n389.997009 1.594500\n399.935028 1.591170\n419.985992 1.585370\n439.957001 1.580480\n460.037018 1.576320\n479.985016 1.572740\n499.919006 1.569640\n520.049988 1.566940\n539.983032 1.564560\n559.981995 1.562470\n579.888000 1.560600\n600.097046 1.558940\n619.900024 1.557440\n640.062012 1.556100\n659.819031 1.554880\n680.088013 1.553780\n700.056030 1.552780\n719.976990 1.551860\n740.179016 1.551020\n760.147034 1.550250\n779.747986 1.549540\n799.871033 1.548880\n819.974060 1.548280\n839.973083 1.547720\n859.778015 1.547200\n879.915039 1.546710\n899.709961 1.546260\n"
  },
  {
    "path": "Asset/SPD/metals/KBr.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for cubic KBr\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n310.027008 0.000000\n320.031006 0.000000\n329.997009 0.000000\n339.951019 0.000000\n350.028015 0.000000\n359.988007 0.000000\n369.979004 0.000000\n379.957001 0.000000\n389.997009 0.000000\n399.935028 0.000000\n419.985992 0.000000\n439.957001 0.000000\n460.037018 0.000000\n479.985016 0.000000\n499.919006 0.000000\n520.049988 0.000000\n539.983032 0.000000\n559.981995 0.000000\n579.888000 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n680.088013 0.000000\n700.056030 0.000000\n719.976990 0.000000\n740.179016 0.000000\n760.147034 0.000000\n779.747986 0.000000\n799.871033 0.000000\n819.974060 0.000000\n839.973083 0.000000\n859.778015 0.000000\n879.915039 0.000000\n899.709961 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/KCl.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for KCl\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n310.027008 1.540050\n320.031006 1.535180\n329.997009 1.530870\n339.951019 1.527030\n350.028015 1.523580\n359.988007 1.520490\n369.979004 1.517690\n379.957001 1.515150\n389.997009 1.512830\n399.935028 1.510720\n419.985992 1.507010\n439.957001 1.503860\n460.037018 1.501150\n479.985016 1.498820\n499.919006 1.496790\n520.049988 1.495010\n539.983032 1.493440\n559.981995 1.492050\n579.888000 1.490810\n600.097046 1.489690\n619.900024 1.488690\n640.062012 1.487790\n659.819031 1.486970\n680.088013 1.486230\n700.056030 1.485550\n719.976990 1.484930\n740.179016 1.484360\n760.147034 1.483840\n779.747986 1.483360\n799.871033 1.482910\n819.974060 1.482500\n839.973083 1.482120\n859.778015 1.481760\n879.915039 1.481430\n899.709961 1.481110\n"
  },
  {
    "path": "Asset/SPD/metals/KCl.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for KCl\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n310.027008 0.000000\n320.031006 0.000000\n329.997009 0.000000\n339.951019 0.000000\n350.028015 0.000000\n359.988007 0.000000\n369.979004 0.000000\n379.957001 0.000000\n389.997009 0.000000\n399.935028 0.000000\n419.985992 0.000000\n439.957001 0.000000\n460.037018 0.000000\n479.985016 0.000000\n499.919006 0.000000\n520.049988 0.000000\n539.983032 0.000000\n559.981995 0.000000\n579.888000 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n680.088013 0.000000\n700.056030 0.000000\n719.976990 0.000000\n740.179016 0.000000\n760.147034 0.000000\n779.747986 0.000000\n799.871033 0.000000\n819.974060 0.000000\n839.973083 0.000000\n859.778015 0.000000\n879.915039 0.000000\n899.709961 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/Li.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Li\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n306.123016 0.346000\n330.613007 0.345000\n359.362030 0.334000\n393.587006 0.304000\n435.018036 0.247000\n486.196014 0.217000\n551.022034 0.206000\n635.795044 0.221000\n751.393982 0.265000\n"
  },
  {
    "path": "Asset/SPD/metals/Li.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Li\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n306.123016 1.210000\n330.613007 1.320000\n359.362030 1.450000\n393.587006 1.600000\n435.018036 1.820000\n486.196014 2.110000\n551.022034 2.480000\n635.795044 2.940000\n751.393982 3.550000\n"
  },
  {
    "path": "Asset/SPD/metals/MgO.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for MgO\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  MgO_llnl_cxro + MgO_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.798000\n330.613007 1.785000\n351.118988 1.776800\n355.549011 1.775500\n360.932007 1.773200\n361.141998 1.773180\n364.968994 1.771860\n382.065002 1.766800\n386.712006 1.765500\n393.337982 1.763800\n404.634003 1.761040\n430.935028 1.755700\n435.781982 1.754710\n457.829010 1.751200\n477.949036 1.748300\n486.004974 1.747110\n487.918030 1.746900\n499.919006 1.745400\n502.350006 1.745300\n508.531982 1.744460\n514.440002 1.743900\n546.166992 1.740770\n589.258972 1.737370\n632.874023 1.734600\n643.718018 1.734000\n656.325989 1.733350\n667.635986 1.732770\n690.695984 1.731910\n706.439026 1.731010\n767.677979 1.728720\n"
  },
  {
    "path": "Asset/SPD/metals/MgO.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for MgO\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  MgO_llnl_cxro + MgO_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 0.000000\n330.613007 0.000000\n351.118988 0.000000\n355.549011 0.000001\n360.932007 0.000001\n361.141998 0.000001\n364.968994 0.000000\n382.065002 0.000000\n386.712006 0.000000\n393.337982 0.000000\n404.634003 0.000000\n430.935028 0.000000\n435.781982 0.000000\n457.829010 0.000000\n477.949036 0.000000\n486.004974 0.000000\n487.918030 0.000000\n499.919006 0.000000\n502.350006 0.000000\n508.531982 0.000000\n514.440002 0.000000\n546.166992 0.000000\n589.258972 0.000000\n632.874023 0.000000\n643.718018 0.000000\n656.325989 0.000000\n667.635986 0.000000\n690.695984 0.000000\n706.439026 0.000000\n767.677979 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/Mo.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for \n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Mo_llnl_cxro + Mo_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 2.910000\n309.950012 3.010000\n317.897003 3.040000\n326.263000 3.040000\n335.081024 3.040000\n344.389008 3.050000\n354.229004 3.060000\n364.647003 3.060000\n375.696991 3.060000\n387.437988 3.050000\n399.935028 3.030000\n413.266998 3.040000\n427.516998 3.050000\n442.785980 3.080000\n459.185028 3.130000\n476.846008 3.220000\n495.920013 3.360000\n516.583008 3.590000\n539.044006 3.790000\n563.545044 3.760000\n590.381042 3.680000\n619.900024 3.680000\n652.526001 3.740000\n688.778015 3.810000\n729.294006 3.840000\n774.875000 3.770000\n826.533020 3.530000\n885.570984 3.150000\n"
  },
  {
    "path": "Asset/SPD/metals/Mo.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for \n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Mo_llnl_cxro + Mo_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 3.670000\n309.950012 3.510000\n317.897003 3.400000\n326.263000 3.310000\n335.081024 3.270000\n344.389008 3.240000\n354.229004 3.210000\n364.647003 3.190000\n375.696991 3.180000\n387.437988 3.180000\n399.935028 3.220000\n413.266998 3.270000\n427.516998 3.330000\n442.785980 3.420000\n459.185028 3.510000\n476.846008 3.610000\n495.920013 3.730000\n516.583008 3.780000\n539.044006 3.610000\n563.545044 3.410000\n590.381042 3.450000\n619.900024 3.520000\n652.526001 3.580000\n688.778015 3.580000\n729.294006 3.510000\n774.875000 3.410000\n826.533020 3.300000\n885.570984 3.400000\n"
  },
  {
    "path": "Asset/SPD/metals/NaCl.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for NaCl\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n319.947998 1.595060\n339.951019 1.585900\n359.988007 1.578520\n379.957001 1.572480\n399.935028 1.567460\n419.985992 1.563240\n439.957001 1.559650\n460.037018 1.556570\n479.985016 1.553900\n499.919006 1.551570\n520.049988 1.549530\n539.983032 1.547730\n559.981995 1.546130\n579.888000 1.544710\n600.097046 1.543430\n619.900024 1.542280\n640.062012 1.541240\n659.819031 1.540300\n680.088013 1.539440\n700.056030 1.538650\n719.976990 1.537940\n740.179016 1.537280\n760.147034 1.536670\n779.747986 1.536110\n799.871033 1.535600\n819.974060 1.535120\n839.973083 1.534670\n859.778015 1.534260\n879.915039 1.533870\n899.709961 1.533510\n"
  },
  {
    "path": "Asset/SPD/metals/NaCl.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for NaCl\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n319.947998 0.000000\n339.951019 0.000000\n359.988007 0.000000\n379.957001 0.000000\n399.935028 0.000000\n419.985992 0.000000\n439.957001 0.000000\n460.037018 0.000000\n479.985016 0.000000\n499.919006 0.000000\n520.049988 0.000000\n539.983032 0.000000\n559.981995 0.000000\n579.888000 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n680.088013 0.000000\n700.056030 0.000000\n719.976990 0.000000\n740.179016 0.000000\n760.147034 0.000000\n779.747986 0.000000\n799.871033 0.000000\n819.974060 0.000000\n839.973083 0.000000\n859.778015 0.000000\n879.915039 0.000000\n899.709961 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/Nb.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Nb\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Nb_llnl_cxro + Nb_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.640000\n317.897003 2.620000\n326.263000 2.590000\n335.081024 2.560000\n344.389008 2.520000\n354.229004 2.480000\n364.647003 2.460000\n375.696991 2.440000\n387.437988 2.450000\n399.935028 2.480000\n413.266998 2.510000\n435.018036 2.580000\n450.835999 2.660000\n467.849030 2.740000\n486.196014 2.830000\n506.041016 2.890000\n527.575012 2.920000\n551.022034 2.930000\n576.651001 2.920000\n604.781006 2.890000\n635.795044 2.820000\n670.162048 2.690000\n708.456970 2.540000\n751.393982 2.360000\n799.871033 2.150000\n855.033997 1.950000\n"
  },
  {
    "path": "Asset/SPD/metals/Nb.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Nb\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Nb_llnl_cxro + Nb_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.330000\n317.897003 2.290000\n326.263000 2.280000\n335.081024 2.270000\n344.389008 2.290000\n354.229004 2.330000\n364.647003 2.380000\n375.696991 2.450000\n387.437988 2.530000\n399.935028 2.600000\n413.266998 2.680000\n435.018036 2.800000\n450.835999 2.860000\n467.849030 2.900000\n486.196014 2.920000\n506.041016 2.900000\n527.575012 2.880000\n551.022034 2.870000\n576.651001 2.870000\n604.781006 2.870000\n635.795044 2.860000\n670.162048 2.890000\n708.456970 2.990000\n751.393982 3.130000\n799.871033 3.370000\n855.033997 3.680000\n"
  },
  {
    "path": "Asset/SPD/metals/Rh.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Rh\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Rh_llnl_cxro + Rh_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 0.840000\n309.950012 0.860000\n317.897003 0.880000\n326.263000 0.910000\n335.081024 0.950000\n344.389008 0.990000\n354.229004 1.040000\n364.647003 1.110000\n375.696991 1.200000\n387.437988 1.300000\n399.935028 1.410000\n413.266998 1.530000\n427.516998 1.630000\n459.185028 1.800000\n476.846008 1.850000\n495.920013 1.880000\n516.583008 1.900000\n539.044006 1.940000\n563.545044 2.000000\n590.381042 2.050000\n619.900024 2.120000\n652.526001 2.200000\n688.778015 2.300000\n729.294006 2.420000\n774.875000 2.600000\n826.533020 2.780000\n885.570984 3.010000\n"
  },
  {
    "path": "Asset/SPD/metals/Rh.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Rh\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Rh_llnl_cxro + Rh_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 3.030000\n309.950012 3.120000\n317.897003 3.230000\n326.263000 3.340000\n335.081024 3.450000\n344.389008 3.580000\n354.229004 3.710000\n364.647003 3.840000\n375.696991 3.970000\n387.437988 4.090000\n399.935028 4.200000\n413.266998 4.290000\n427.516998 4.360000\n459.185028 4.490000\n476.846008 4.550000\n495.920013 4.650000\n516.583008 4.780000\n539.044006 4.940000\n563.545044 5.110000\n590.381042 5.300000\n619.900024 5.510000\n652.526001 5.760000\n688.778015 6.020000\n729.294006 6.330000\n774.875000 6.640000\n826.533020 6.970000\n885.570984 7.310000\n"
  },
  {
    "path": "Asset/SPD/metals/Se-e.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Se, extraordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n344.389008 3.390000\n364.647003 3.690000\n387.437988 3.920000\n413.266998 4.440000\n442.785980 4.590000\n476.846008 4.400000\n516.583008 4.280000\n563.545044 4.490000\n619.900024 4.790000\n688.778015 4.460000\n"
  },
  {
    "path": "Asset/SPD/metals/Se-e.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Se, extraordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n344.389008 3.010000\n364.647003 2.760000\n387.437988 2.590000\n413.266998 2.290000\n442.785980 1.700000\n476.846008 1.320000\n516.583008 1.210000\n563.545044 1.190000\n619.900024 0.760000\n688.778015 0.022000\n"
  },
  {
    "path": "Asset/SPD/metals/Se.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Se, ordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.670000\n326.263000 2.840000\n344.389008 3.060000\n364.647003 3.220000\n387.437988 3.350000\n413.266998 3.300000\n442.785980 3.120000\n476.846008 3.000000\n516.583008 2.930000\n563.545044 3.070000\n619.900024 3.380000\n688.778015 3.320000\n"
  },
  {
    "path": "Asset/SPD/metals/Se.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Se, ordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.990000\n326.263000 1.660000\n344.389008 1.470000\n364.647003 1.240000\n387.437988 1.010000\n413.266998 0.700000\n442.785980 0.580000\n476.846008 0.530000\n516.583008 0.610000\n563.545044 0.730000\n619.900024 0.650000\n688.778015 0.110000\n"
  },
  {
    "path": "Asset/SPD/metals/SiC.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for crystalline SiC\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  SiC_llnl_cxro + SiC_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.850000\n317.897003 2.923000\n326.263000 2.899000\n335.081024 2.877000\n344.389008 2.856000\n354.229004 2.836000\n364.647003 2.817000\n375.696991 2.799000\n387.437988 2.781000\n399.935028 2.765000\n413.266998 2.750000\n435.781982 2.730500\n466.968018 2.707400\n495.920013 2.684000\n497.912018 2.687000\n515.080994 2.678900\n546.166992 2.663100\n567.934021 2.655700\n577.995056 2.651100\n588.979004 2.648800\n589.539001 2.647500\n615.897034 2.641100\n619.900024 2.634000\n656.325989 2.629600\n691.080994 2.624300\n826.533020 2.598000\n"
  },
  {
    "path": "Asset/SPD/metals/SiC.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for crystalline SiC\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  SiC_llnl_cxro + SiC_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 0.174000\n317.897003 0.007650\n326.263000 0.005980\n335.081024 0.004930\n344.389008 0.003750\n354.229004 0.002890\n364.647003 0.002040\n375.696991 0.001380\n387.437988 0.000839\n399.935028 0.000191\n413.266998 0.000044\n435.781982 0.000000\n466.968018 0.000000\n495.920013 0.000012\n497.912018 0.000000\n515.080994 0.000000\n546.166992 0.000000\n567.934021 0.000000\n577.995056 0.000000\n588.979004 0.000000\n589.539001 0.000000\n615.897034 0.000000\n619.900024 0.000000\n656.325989 0.000000\n691.080994 0.000000\n826.533020 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/SiO.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for SiO\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  SiO_llnl_cxro + SiO_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.141000\n326.263000 2.157000\n344.389008 2.162000\n364.647003 2.160000\n387.437988 2.144000\n413.266998 2.116000\n442.785980 2.085000\n476.846008 2.053000\n516.583008 2.021000\n563.545044 1.994000\n619.900024 1.969000\n688.778015 1.948000\n774.875000 1.929000\n885.570984 1.913000\n"
  },
  {
    "path": "Asset/SPD/metals/SiO.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for SiO\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  SiO_llnl_cxro + SiO_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 0.400600\n326.263000 0.345300\n344.389008 0.287200\n364.647003 0.228700\n387.437988 0.170600\n413.266998 0.121100\n442.785980 0.083740\n476.846008 0.055440\n516.583008 0.035330\n563.545044 0.021530\n619.900024 0.011750\n688.778015 0.005230\n774.875000 0.001510\n885.570984 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/SnTe.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for SnTe\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n311.586029 0.967000\n332.118988 1.007000\n361.037018 1.103000\n390.242004 1.228000\n414.372040 1.364000\n453.308990 1.551000\n498.312012 1.702000\n533.476990 1.813000\n548.099060 1.878000\n550.533020 1.989000\n552.987976 2.135000\n558.216980 2.442000\n566.119019 2.719000\n582.339050 2.991000\n605.963013 3.273000\n621.454041 3.479000\n648.091980 3.701000\n681.208984 3.912000\n748.671021 4.285000\n804.020996 4.541000\n867.478027 4.803000\n"
  },
  {
    "path": "Asset/SPD/metals/SnTe.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for SnTe\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n311.586029 0.000000\n332.118988 0.000000\n361.037018 0.000000\n390.242004 0.000000\n414.372040 0.000000\n453.308990 0.000000\n498.312012 0.000000\n533.476990 0.000000\n548.099060 0.000000\n550.533020 0.000000\n552.987976 0.000000\n558.216980 0.000000\n566.119019 0.000000\n582.339050 0.000000\n605.963013 0.000000\n621.454041 0.000000\n648.091980 0.000000\n681.208984 0.000000\n748.671021 0.000000\n804.020996 0.000000\n867.478027 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/Ta.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Ta\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Ta_llnl_cxro + Ta_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.360000\n326.263000 2.400000\n344.389008 2.490000\n364.647003 2.610000\n387.437988 2.730000\n413.266998 2.810000\n427.516998 2.840000\n442.785980 2.850000\n459.185028 2.840000\n476.846008 2.800000\n495.920013 2.750000\n516.583008 2.680000\n539.044006 2.560000\n563.545044 2.360000\n590.381042 2.100000\n619.900024 1.830000\n652.526001 1.570000\n688.778015 1.350000\n729.294006 1.240000\n774.875000 1.150000\n826.533020 1.090000\n885.570984 1.040000\n"
  },
  {
    "path": "Asset/SPD/metals/Ta.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for Ta\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  Ta_llnl_cxro + Ta_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.140000\n326.263000 2.220000\n344.389008 2.300000\n364.647003 2.330000\n387.437988 2.310000\n413.266998 2.240000\n427.516998 2.200000\n442.785980 2.140000\n459.185028 2.080000\n476.846008 2.020000\n495.920013 1.980000\n516.583008 1.920000\n539.044006 1.860000\n563.545044 1.810000\n590.381042 1.840000\n619.900024 1.990000\n652.526001 2.240000\n688.778015 2.600000\n729.294006 2.950000\n774.875000 3.330000\n826.533020 3.730000\n885.570984 4.150000\n"
  },
  {
    "path": "Asset/SPD/metals/Te-e.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for trigonal Te, extraordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.330000\n330.613007 1.440000\n354.229004 1.690000\n381.477020 1.920000\n403.975006 2.220000\n413.266998 2.300000\n416.599030 2.350000\n430.037994 2.540000\n442.785980 2.730000\n444.373016 2.760000\n459.696014 2.980000\n476.114014 3.210000\n476.846008 3.250000\n489.266022 3.460000\n498.512024 3.630000\n507.906982 3.810000\n516.583008 3.940000\n517.877991 3.990000\n528.024048 4.200000\n538.809021 4.390000\n549.799988 4.650000\n561.249023 4.910000\n563.545044 4.940000\n573.450989 5.170000\n599.226990 5.760000\n612.851990 6.000000\n619.900024 4.670000\n627.429016 6.210000\n642.382996 6.400000\n658.416992 6.580000\n674.904968 6.770000\n688.778015 6.890000\n692.625977 6.850000\n710.895020 6.860000\n730.583008 6.800000\n750.939026 6.780000\n772.943054 6.740000\n774.875000 6.750000\n796.275024 6.730000\n820.516052 6.810000\n846.858032 6.950000\n874.330017 7.140000\n885.570984 7.110000\n"
  },
  {
    "path": "Asset/SPD/metals/Te-e.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for trigonal Te, extraordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.640000\n330.613007 3.060000\n354.229004 3.440000\n381.477020 3.780000\n403.975006 3.960000\n413.266998 4.160000\n416.599030 4.150000\n430.037994 4.270000\n442.785980 4.420000\n444.373016 4.390000\n459.696014 4.520000\n476.114014 4.710000\n476.846008 4.770000\n489.266022 4.850000\n498.512024 4.930000\n507.906982 5.010000\n516.583008 5.080000\n517.877991 5.080000\n528.024048 5.160000\n538.809021 5.200000\n549.799988 5.210000\n561.249023 5.200000\n563.545044 5.160000\n573.450989 5.160000\n599.226990 4.920000\n612.851990 4.770000\n619.900024 4.670000\n627.429016 4.600000\n642.382996 4.360000\n658.416992 4.100000\n674.904968 3.860000\n688.778015 3.700000\n692.625977 3.650000\n710.895020 3.470000\n730.583008 3.180000\n750.939026 3.030000\n772.943054 2.930000\n774.875000 2.910000\n796.275024 2.890000\n820.516052 2.860000\n846.858032 2.800000\n874.330017 2.560000\n885.570984 2.460000\n"
  },
  {
    "path": "Asset/SPD/metals/Te.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for trigonal Te,ordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.320000\n330.613007 1.500000\n354.229004 1.720000\n381.477020 2.020000\n403.975006 2.370000\n413.266998 2.510000\n416.599030 2.560000\n430.037994 2.770000\n442.785980 3.030000\n444.373016 3.010000\n459.696014 3.270000\n476.114014 3.550000\n476.846008 3.570000\n489.266022 3.760000\n498.512024 3.910000\n507.906982 4.070000\n516.583008 4.240000\n517.877991 4.250000\n528.024048 4.430000\n538.809021 4.620000\n549.799988 4.810000\n561.249023 5.010000\n563.545044 5.100000\n573.450989 5.260000\n599.226990 5.670000\n612.851990 5.820000\n619.900024 5.940000\n627.429016 5.970000\n642.382996 6.070000\n658.416992 6.110000\n674.904968 6.120000\n688.778015 6.100000\n692.625977 6.090000\n710.895020 6.040000\n730.583008 5.950000\n750.939026 5.870000\n772.943054 5.860000\n774.875000 5.880000\n796.275024 5.840000\n820.516052 5.780000\n846.858032 5.680000\n874.330017 5.590000\n885.570984 5.560000\n"
  },
  {
    "path": "Asset/SPD/metals/Te.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for trigonal Te,ordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.010000\n330.613007 2.370000\n354.229004 2.700000\n381.477020 3.030000\n403.975006 3.290000\n413.266998 3.390000\n416.599030 3.390000\n430.037994 3.470000\n442.785980 3.630000\n444.373016 3.570000\n459.696014 3.660000\n476.114014 3.720000\n476.846008 3.750000\n489.266022 3.760000\n498.512024 3.770000\n507.906982 3.770000\n516.583008 3.770000\n517.877991 3.780000\n528.024048 3.760000\n538.809021 3.690000\n549.799988 3.630000\n561.249023 3.570000\n563.545044 3.610000\n573.450989 3.520000\n599.226990 3.160000\n612.851990 2.940000\n619.900024 2.690000\n627.429016 2.700000\n642.382996 2.450000\n658.416992 2.250000\n674.904968 2.020000\n688.778015 1.800000\n692.625977 1.720000\n710.895020 1.520000\n730.583008 1.360000\n750.939026 1.260000\n772.943054 1.170000\n774.875000 1.150000\n796.275024 1.060000\n820.516052 0.895000\n846.858032 0.760000\n874.330017 0.659000\n885.570984 0.630000\n"
  },
  {
    "path": "Asset/SPD/metals/ThF4.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for polycrystalline ThF4\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.545000\n319.947998 1.542000\n329.997009 1.540000\n340.044006 1.538000\n349.929016 1.536000\n359.988007 1.534000\n369.979004 1.532000\n379.957001 1.531000\n389.997009 1.530000\n399.935028 1.529000\n409.987030 1.528000\n419.985992 1.527000\n430.037994 1.526000\n435.781982 1.533000\n439.957001 1.526000\n450.018036 1.525000\n460.037018 1.524000\n469.977020 1.524000\n479.985016 1.523000\n490.040009 1.523000\n499.919006 1.523000\n509.996002 1.522000\n520.049988 1.522000\n539.983032 1.521000\n545.927002 1.521000\n559.981995 1.521000\n579.888000 1.520000\n600.097046 1.520000\n619.900024 1.520000\n640.062012 1.519000\n659.819031 1.519000\n700.056030 1.519000\n739.737000 1.518000\n779.747986 1.518000\n799.871033 1.518000\n"
  },
  {
    "path": "Asset/SPD/metals/ThF4.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for polycrystalline ThF4\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids II', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1991.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 0.000000\n319.947998 0.000000\n329.997009 0.000000\n340.044006 0.000000\n349.929016 0.000000\n359.988007 0.000000\n369.979004 0.000000\n379.957001 0.000000\n389.997009 0.000000\n399.935028 0.000000\n409.987030 0.000000\n419.985992 0.000000\n430.037994 0.000000\n435.781982 0.000000\n439.957001 0.000000\n450.018036 0.000000\n460.037018 0.000000\n469.977020 0.000000\n479.985016 0.000000\n490.040009 0.000000\n499.919006 0.000000\n509.996002 0.000000\n520.049988 0.000000\n539.983032 0.000000\n545.927002 0.000000\n559.981995 0.000000\n579.888000 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n700.056030 0.000000\n739.737000 0.000000\n779.747986 0.000000\n799.871033 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/TiC.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for TiC\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  TiC_llnl_cxro + TiC_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.300000\n354.229004 2.570000\n413.266998 2.780000\n495.920013 2.950000\n619.900024 3.050000\n826.533020 3.510000\n"
  },
  {
    "path": "Asset/SPD/metals/TiC.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for TiC\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  TiC_llnl_cxro + TiC_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.330000\n354.229004 2.340000\n413.266998 2.430000\n495.920013 2.380000\n619.900024 2.670000\n826.533020 3.070000\n"
  },
  {
    "path": "Asset/SPD/metals/TiN.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for TiN\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  TiN_llnl_cxro + TiN_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.270000\n354.229004 2.140000\n413.266998 1.740000\n495.920013 1.200000\n619.900024 1.320000\n826.533020 1.820000\n"
  },
  {
    "path": "Asset/SPD/metals/TiN.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for TiN\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  TiN_llnl_cxro + TiN_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.230000\n354.229004 1.060000\n413.266998 1.040000\n495.920013 1.650000\n619.900024 2.690000\n826.533020 3.810000\n"
  },
  {
    "path": "Asset/SPD/metals/TiO2-e.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for tetragonal TiO2, extraordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n307.033020 3.420000\n317.979004 4.000000\n327.037994 3.870000\n344.007019 4.300000\n358.013000 3.380000\n388.044006 2.880000\n399.935028 3.000000\n402.010010 3.000000\n419.985992 2.910000\n439.957001 2.840000\n460.037018 2.790000\n479.985016 2.750000\n499.919006 2.710000\n520.049988 2.680000\n539.983032 2.660000\n559.981995 2.640000\n579.888000 2.620000\n600.097046 2.600000\n619.900024 2.590000\n640.062012 2.580000\n659.819031 2.570000\n680.088013 2.560000\n700.056030 2.550000\n719.976990 2.540000\n740.179016 2.540000\n760.147034 2.530000\n779.747986 2.520000\n799.871033 2.520000\n819.974060 2.520000\n839.973083 2.510000\n859.778015 2.510000\n879.915039 2.500000\n899.709961 2.500000\n"
  },
  {
    "path": "Asset/SPD/metals/TiO2-e.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for tetragonal TiO2, extraordinary ray\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n307.033020 1.610000\n317.979004 1.790000\n327.037994 0.810000\n344.007019 0.000000\n358.013000 0.117000\n388.044006 0.000000\n399.935028 0.000000\n402.010010 0.008000\n419.985992 0.000000\n439.957001 0.000000\n460.037018 0.000000\n479.985016 0.000000\n499.919006 0.000000\n520.049988 0.000000\n539.983032 0.000000\n559.981995 0.000000\n579.888000 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n680.088013 0.000000\n700.056030 0.000000\n719.976990 0.000000\n740.179016 0.000000\n760.147034 0.000000\n779.747986 0.000000\n799.871033 0.000000\n819.974060 0.000000\n839.973083 0.000000\n859.778015 0.000000\n879.915039 0.000000\n899.709961 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/TiO2.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for tetragonal TiO2, ordinary ray\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  TiO2_llnl_cxro + TiO2_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n305.972015 3.840000\n317.979004 5.380000\n334.990997 4.220000\n344.007019 4.360000\n359.988007 3.870000\n388.044006 3.490000\n399.935028 3.400000\n412.031006 3.240000\n419.985992 3.290000\n439.957001 3.200000\n460.037018 3.130000\n479.985016 3.080000\n499.919006 3.030000\n520.049988 3.000000\n539.044006 2.950000\n539.983032 2.970000\n559.981995 2.940000\n579.888000 2.920000\n600.097046 2.900000\n619.900024 2.880000\n640.062012 2.870000\n659.819031 2.850000\n680.088013 2.840000\n700.056030 2.830000\n719.976990 2.820000\n740.179016 2.810000\n760.147034 2.810000\n779.747986 2.800000\n799.871033 2.790000\n819.974060 2.790000\n839.973083 2.780000\n859.778015 2.780000\n879.915039 2.770000\n899.709961 2.770000\n"
  },
  {
    "path": "Asset/SPD/metals/TiO2.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for tetragonal TiO2, ordinary ray\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  TiO2_llnl_cxro + TiO2_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n305.972015 1.950000\n317.979004 2.180000\n334.990997 0.788000\n344.007019 0.000000\n359.988007 0.251000\n388.044006 0.000000\n399.935028 0.000000\n412.031006 0.022000\n419.985992 0.000000\n439.957001 0.000000\n460.037018 0.000000\n479.985016 0.000000\n499.919006 0.000000\n520.049988 0.000000\n539.044006 0.000000\n539.983032 0.000000\n559.981995 0.000000\n579.888000 0.000000\n600.097046 0.000000\n619.900024 0.000000\n640.062012 0.000000\n659.819031 0.000000\n680.088013 0.000000\n700.056030 0.000000\n719.976990 0.000000\n740.179016 0.000000\n760.147034 0.000000\n779.747986 0.000000\n799.871033 0.000000\n819.974060 0.000000\n839.973083 0.000000\n859.778015 0.000000\n879.915039 0.000000\n899.709961 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/VC.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for VC\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  VC_llnl_cxro + VC_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.470000\n354.229004 2.590000\n413.266998 2.770000\n495.920013 2.840000\n619.900024 3.010000\n826.533020 3.370000\n"
  },
  {
    "path": "Asset/SPD/metals/VC.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for VC\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  VC_llnl_cxro + VC_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.150000\n354.229004 2.120000\n413.266998 2.160000\n495.920013 2.210000\n619.900024 2.510000\n826.533020 2.880000\n"
  },
  {
    "path": "Asset/SPD/metals/VN.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for VN\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  VN_llnl_cxro + VN_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 2.200000\n354.229004 2.180000\n413.266998 2.130000\n495.920013 2.170000\n619.900024 2.350000\n826.533020 2.730000\n"
  },
  {
    "path": "Asset/SPD/metals/VN.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for VN\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  VN_llnl_cxro + VN_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.540000\n354.229004 1.580000\n413.266998 1.700000\n495.920013 1.980000\n619.900024 2.470000\n826.533020 2.920000\n"
  },
  {
    "path": "Asset/SPD/metals/W.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for W\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  W_llnl_cxro + W_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 2.970000\n309.950012 2.950000\n313.873016 2.950000\n317.897003 2.960000\n322.026001 2.980000\n326.263000 2.990000\n330.613007 3.020000\n335.081024 3.050000\n339.670990 3.090000\n344.389008 3.130000\n349.238983 3.180000\n354.229004 3.240000\n359.362030 3.320000\n364.647003 3.390000\n370.089996 3.430000\n375.696991 3.450000\n381.477020 3.450000\n387.437988 3.430000\n393.587006 3.410000\n399.935028 3.390000\n406.492004 3.370000\n413.266998 3.350000\n420.270996 3.330000\n427.516998 3.320000\n435.018036 3.310000\n442.785980 3.300000\n450.835999 3.310000\n459.185028 3.310000\n467.849030 3.320000\n476.846008 3.340000\n486.196014 3.350000\n495.920013 3.380000\n506.041016 3.420000\n516.583008 3.450000\n527.575012 3.480000\n539.044006 3.500000\n551.022034 3.500000\n563.545044 3.490000\n576.651001 3.510000\n590.381042 3.540000\n604.781006 3.570000\n619.900024 3.600000\n635.795044 3.650000\n652.526001 3.700000\n670.162048 3.760000\n688.778015 3.820000\n708.456970 3.850000\n729.294006 3.840000\n751.393982 3.780000\n774.875000 3.670000\n799.871033 3.560000\n826.533020 3.480000\n855.033997 3.380000\n885.570984 3.290000\n"
  },
  {
    "path": "Asset/SPD/metals/W.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for W\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  W_llnl_cxro + W_palik\n# ;\n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n302.389984 2.370000\n309.950012 2.430000\n313.873016 2.460000\n317.897003 2.500000\n322.026001 2.530000\n326.263000 2.560000\n330.613007 2.600000\n335.081024 2.620000\n339.670990 2.650000\n344.389008 2.670000\n349.238983 2.690000\n354.229004 2.700000\n359.362030 2.700000\n364.647003 2.660000\n370.089996 2.600000\n375.696991 2.550000\n381.477020 2.490000\n387.437988 2.450000\n393.587006 2.430000\n399.935028 2.410000\n406.492004 2.420000\n413.266998 2.420000\n420.270996 2.430000\n427.516998 2.450000\n435.018036 2.470000\n442.785980 2.490000\n450.835999 2.530000\n459.185028 2.550000\n467.849030 2.590000\n476.846008 2.620000\n486.196014 2.640000\n495.920013 2.680000\n506.041016 2.710000\n516.583008 2.720000\n527.575012 2.720000\n539.044006 2.720000\n551.022034 2.730000\n563.545044 2.750000\n576.651001 2.810000\n590.381042 2.840000\n604.781006 2.860000\n619.900024 2.890000\n635.795044 2.920000\n652.526001 2.940000\n670.162048 2.950000\n688.778015 2.910000\n708.456970 2.860000\n729.294006 2.780000\n751.393982 2.720000\n774.875000 2.680000\n799.871033 2.730000\n826.533020 2.790000\n855.033997 2.850000\n885.570984 2.960000\n"
  },
  {
    "path": "Asset/SPD/metals/a-C.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for amorphous carbon\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  a-C_llnl_cxro + a-C_windt88 + a-C_palik\n# ;  \n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 1.840000\n326.263000 1.900000\n344.389008 1.940000\n364.647003 2.000000\n387.437988 2.060000\n413.266998 2.110000\n442.785980 2.170000\n476.846008 2.240000\n516.583008 2.300000\n563.545044 2.380000\n619.900024 2.430000\n688.778015 2.430000\n774.875000 2.330000\n885.570984 2.240000\n"
  },
  {
    "path": "Asset/SPD/metals/a-C.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for amorphous carbon\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  a-C_llnl_cxro + a-C_windt88 + a-C_palik\n# ;  \n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 0.808000\n326.263000 0.910000\n344.389008 0.920000\n364.647003 0.920000\n387.437988 0.910000\n413.266998 0.900000\n442.785980 0.890000\n476.846008 0.880000\n516.583008 0.870000\n563.545044 0.820000\n619.900024 0.750000\n688.778015 0.700000\n774.875000 0.710000\n885.570984 0.800000\n"
  },
  {
    "path": "Asset/SPD/metals/a-SiH.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for a-Si:H, amorphous glow-discharge Si onto\n# ;  400 C substrates, ~4 at.% H\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 3.360000\n354.229004 4.590000\n413.266998 5.430000\n495.920013 5.250000\n619.900024 4.710000\n826.533020 4.130000\n"
  },
  {
    "path": "Asset/SPD/metals/a-SiH.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for a-Si:H, amorphous glow-discharge Si onto\n# ;  400 C substrates, ~4 at.% H\n# ; \n# ;   taken from:\n# ;\n# ;   'Handbook of Optical Constants of Solids', Ed. by Edward D. Palik,\n# ;   Academic Press, Inc., 1985.\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n309.950012 3.920000\n354.229004 3.380000\n413.266998 2.190000\n495.920013 0.992000\n619.900024 0.217000\n826.533020 0.000000\n"
  },
  {
    "path": "Asset/SPD/metals/d-C.eta.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for diamond\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  d-C_llnl_cxro + d-C_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n346.700012 2.495400\n361.037018 2.485400\n404.634003 2.462600\n467.795990 2.440800\n486.120026 2.435400\n508.552002 2.430600\n546.047058 2.423500\n588.979004 2.417500\n643.818054 2.411100\n656.257019 2.410400\n"
  },
  {
    "path": "Asset/SPD/metals/d-C.k.spd",
    "content": "# data from www.luxpop.com database\n# ;  Optical constants for diamond\n# ;  \n# ;  Concatenation of:\n# ;\n# ;  d-C_llnl_cxro + d-C_palik\n# ;   \n# ;    Lambda (A)            n            k\n# ;-----------------------------------------\n346.700012 0.000000\n361.037018 0.000000\n404.634003 0.000000\n467.795990 0.000000\n486.120026 0.000000\n508.552002 0.000000\n546.047058 0.000000\n588.979004 0.000000\n643.818054 0.000000\n656.257019 0.000000\n"
  },
  {
    "path": "Doc/Material.drawio",
    "content": "<mxfile host=\"65bd71144e\">\n    <diagram id=\"Oj6RUKoLF9Hl1Nya2uuC\" name=\"第 1 页\">\n        <mxGraphModel dx=\"1064\" dy=\"674\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" math=\"0\" shadow=\"0\">\n            <root>\n                <mxCell id=\"0\"/>\n                <mxCell id=\"1\" parent=\"0\"/>\n                <mxCell id=\"48\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Diffuse&lt;br&gt;&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"440\" width=\"200\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"59\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"50\" target=\"55\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"60\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"50\" target=\"56\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"50\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Dielectric&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"520\" width=\"200\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"51\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;ThinDielectric&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"600\" width=\"200\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"61\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"53\" target=\"57\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"62\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"53\" target=\"58\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"53\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Conductor&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"680\" width=\"200\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"54\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;ThinConductor&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"760\" width=\"200\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"55\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Smooth Dielectric&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"400\" y=\"480\" width=\"240\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"56\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Rough Dielectric&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"400\" y=\"560\" width=\"240\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"57\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Smooth&amp;nbsp;&lt;/font&gt;&lt;span style=&quot;font-size: 24px;&quot;&gt;Conductor&lt;/span&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"400\" y=\"640\" width=\"240\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"58\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Rough&amp;nbsp;&lt;/font&gt;&lt;span style=&quot;font-size: 24px;&quot;&gt;Conductor&lt;/span&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"400\" y=\"720\" width=\"240\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n            </root>\n        </mxGraphModel>\n    </diagram>\n</mxfile>"
  },
  {
    "path": "Doc/RHI.drawio",
    "content": "<mxfile host=\"65bd71144e\">\n    <diagram id=\"qQwCbRc1wy9BN8YB_Oij\" name=\"第 1 页\">\n        <mxGraphModel dx=\"1064\" dy=\"674\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" background=\"none\" math=\"0\" shadow=\"0\">\n            <root>\n                <mxCell id=\"0\"/>\n                <mxCell id=\"1\" parent=\"0\"/>\n                <mxCell id=\"57\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;RHI&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"280\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"58\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Device&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"200\" y=\"280\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"59\" value=\"Vulkan\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"80\" y=\"340\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"60\" value=\"&lt;font style=&quot;font-size: 12px;&quot;&gt;VkInstance&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"200\" y=\"340\" width=\"80\" height=\"30\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"61\" value=\"&lt;font style=&quot;font-size: 12px;&quot;&gt;VkDevice&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"280\" y=\"340\" width=\"80\" height=\"30\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"62\" value=\"&lt;font style=&quot;font-size: 12px;&quot;&gt;VkPhysicalDevice&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"200\" y=\"370\" width=\"160\" height=\"30\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"63\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Texture&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"360\" y=\"280\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"64\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;VkImage&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"360\" y=\"340\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"65\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Buffer&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"480\" y=\"280\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"66\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;VkBuffer&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"480\" y=\"340\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"67\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Queue&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"600\" y=\"280\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"68\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Descriptor&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"720\" y=\"280\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"69\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Shader&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"880\" y=\"280\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"70\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Sampler&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"1000\" y=\"280\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"71\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Swapchain&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"1160\" y=\"280\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"72\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Command&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"1320\" y=\"280\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"73\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Render Target&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"1480\" y=\"280\" width=\"170\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"74\" value=\"&lt;span style=&quot;font-size: 24px;&quot;&gt;Synchronization&lt;/span&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"1650\" y=\"280\" width=\"190\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"75\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;VkQueue&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"600\" y=\"340\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n            </root>\n        </mxGraphModel>\n    </diagram>\n</mxfile>"
  },
  {
    "path": "Doc/RenderGraph.drawio",
    "content": ""
  },
  {
    "path": "Doc/Resource.drawio",
    "content": "<mxfile host=\"65bd71144e\">\n    <diagram id=\"B0Vu0QsbAyju_w0uTxer\" name=\"第 1 页\">\n        <mxGraphModel dx=\"2317\" dy=\"944\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" background=\"none\" math=\"0\" shadow=\"0\">\n            <root>\n                <mxCell id=\"0\"/>\n                <mxCell id=\"1\" parent=\"0\"/>\n                <mxCell id=\"36\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-460\" y=\"120\" width=\"140\" height=\"340\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"12\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"640\" y=\"120\" width=\"220\" height=\"310\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"21\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"2\" target=\"5\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"2\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Mesh&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"320\" y=\"10\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"22\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"3\" target=\"5\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"3\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Skinned Mesh&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"320\" y=\"90\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"15\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"4\" target=\"2\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"16\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"4\" target=\"3\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"17\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"4\" target=\"6\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"25\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"4\" target=\"9\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"4\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Prefab&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry y=\"170\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"5\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Scene&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d80073;fontColor=#ffffff;strokeColor=#A50040;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"650\" y=\"200\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"23\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"6\" target=\"5\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"6\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Animation&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"320\" y=\"170\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"7\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Texture2D&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry y=\"290\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"8\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;TextureCube&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry y=\"410\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"20\" style=\"edgeStyle=none;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"9\" target=\"7\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"24\" style=\"edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontSize=24;dashed=1;\" parent=\"1\" source=\"9\" target=\"5\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"9\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Material&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d80073;fontColor=#ffffff;strokeColor=#A50040;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"650\" y=\"320\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"26\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" parent=\"1\" source=\"10\" target=\"4\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"10\" value=\"Model Importer\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-240\" y=\"160\" width=\"160\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"11\" value=\"&lt;span style=&quot;font-size: 24px;&quot;&gt;Render Pipeline&lt;/span&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d80073;fontColor=#ffffff;strokeColor=#A50040;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"650\" y=\"130\" width=\"200\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"13\" value=\"Engine Resource\" style=\"text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"650\" y=\"390\" width=\"200\" height=\"30\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"28\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" parent=\"1\" source=\"27\" target=\"7\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"29\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" parent=\"1\" source=\"27\" target=\"8\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"27\" value=\"Texture&lt;br&gt;Importer\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-240\" y=\"340\" width=\"160\" height=\"80\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"31\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" parent=\"1\" source=\"30\" target=\"10\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"30\" value=\"Assimp\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-450\" y=\"170\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"34\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" parent=\"1\" source=\"32\" target=\"27\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"32\" value=\"STB\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-450\" y=\"320\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"35\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" parent=\"1\" source=\"33\" target=\"27\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"33\" value=\"DDS\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-450\" y=\"390\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"37\" value=\"Plugin\" style=\"text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-420\" y=\"130\" width=\"60\" height=\"30\" as=\"geometry\"/>\n                </mxCell>\n            </root>\n        </mxGraphModel>\n    </diagram>\n</mxfile>"
  },
  {
    "path": "Doc/Scene.drawio",
    "content": "<mxfile host=\"65bd71144e\">\n    <diagram id=\"DN1jI_-sQySN9qRA725S\" name=\"第 1 页\">\n        <mxGraphModel dx=\"1973\" dy=\"944\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" background=\"none\" math=\"0\" shadow=\"0\">\n            <root>\n                <mxCell id=\"0\"/>\n                <mxCell id=\"1\" parent=\"0\"/>\n                <mxCell id=\"34\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;fontSize=24;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"354\" y=\"100\" width=\"496\" height=\"310\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"21\" style=\"edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"2\" target=\"3\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"22\" style=\"edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"2\" target=\"4\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"2\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Scene&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"40\" y=\"90\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"24\" style=\"edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"3\" target=\"6\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"25\" style=\"edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"3\" target=\"5\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"3\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Entity #1&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-80\" y=\"250\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"31\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.576;entryY=-0.011;entryDx=0;entryDy=0;entryPerimeter=0;fontSize=24;curved=1;\" edge=\"1\" parent=\"1\" source=\"4\" target=\"26\">\n                    <mxGeometry relative=\"1\" as=\"geometry\">\n                        <Array as=\"points\">\n                            <mxPoint x=\"220\" y=\"40\"/>\n                            <mxPoint x=\"612\" y=\"40\"/>\n                        </Array>\n                    </mxGeometry>\n                </mxCell>\n                <mxCell id=\"33\" style=\"edgeStyle=orthogonalEdgeStyle;curved=1;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"4\" target=\"32\">\n                    <mxGeometry relative=\"1\" as=\"geometry\">\n                        <Array as=\"points\">\n                            <mxPoint x=\"220\" y=\"480\"/>\n                            <mxPoint x=\"760\" y=\"480\"/>\n                        </Array>\n                    </mxGeometry>\n                </mxCell>\n                <mxCell id=\"4\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Entity #2&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"160\" y=\"250\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"5\" value=\"&lt;span style=&quot;font-size: 24px;&quot;&gt;...&lt;/span&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"40\" y=\"410\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"6\" value=\"&lt;span style=&quot;font-size: 24px;&quot;&gt;Entity #N&lt;/span&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" parent=\"1\" vertex=\"1\">\n                    <mxGeometry x=\"-200\" y=\"410\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"17\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Light&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#fa6800;strokeColor=#C73500;fontColor=#000000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"360\" y=\"120\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"18\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Camera&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d80073;fontColor=#ffffff;strokeColor=#A50040;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"360\" y=\"180\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"19\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Renderable&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#a20025;fontColor=#ffffff;strokeColor=#6F0000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"360\" y=\"240\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"20\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Transform&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#e51400;fontColor=#ffffff;strokeColor=#B20000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"360\" y=\"300\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"26\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;#0 Cmpt #0&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#fa6800;strokeColor=#C73500;fontColor=#000000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"520\" y=\"120\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"27\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;#1 Cmpt #0&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d80073;fontColor=#ffffff;strokeColor=#A50040;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"520\" y=\"180\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"28\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;#2 Cmpt #0&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#a20025;fontColor=#ffffff;strokeColor=#6F0000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"520\" y=\"240\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"29\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;#3 Cmpt #0&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#e51400;fontColor=#ffffff;strokeColor=#B20000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"520\" y=\"300\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"30\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;#0 Cmpt #1&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#fa6800;strokeColor=#C73500;fontColor=#000000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"680\" y=\"120\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"32\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;#3 Cmpt #1&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#e51400;fontColor=#ffffff;strokeColor=#B20000;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"680\" y=\"300\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"35\" value=\"Component Map\" style=\"text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"503\" y=\"370\" width=\"198\" height=\"30\" as=\"geometry\"/>\n                </mxCell>\n            </root>\n        </mxGraphModel>\n    </diagram>\n</mxfile>"
  },
  {
    "path": "Doc/Shader.drawio",
    "content": "<mxfile host=\"65bd71144e\" pages=\"1\">\n    <diagram id=\"FqTtuIh2T_jkB8yKotZ9\" name=\"第 1 页\">\n        <mxGraphModel dx=\"1146\" dy=\"726\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" background=\"none\" math=\"0\" shadow=\"0\">\n            <root>\n                <mxCell id=\"0\"/>\n                <mxCell id=\"1\" parent=\"0\"/>\n                <mxCell id=\"31\" style=\"edgeStyle=orthogonalEdgeStyle;curved=1;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;\" parent=\"1\" target=\"6\" edge=\"1\">\n                    <mxGeometry relative=\"1\" as=\"geometry\">\n                        <Array as=\"points\">\n                            <mxPoint x=\"180\" y=\"90\"/>\n                            <mxPoint x=\"580\" y=\"90\"/>\n                        </Array>\n                        <mxPoint x=\"180\" y=\"160.0000000000001\" as=\"sourcePoint\"/>\n                    </mxGeometry>\n                </mxCell>\n                <mxCell id=\"52\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"46\" target=\"49\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"62\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"46\" target=\"51\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"46\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;HLSL&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"40\" y=\"260\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"53\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"47\" target=\"50\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"47\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;GLSL&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"40\" y=\"480\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"58\" style=\"edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"49\" target=\"57\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"67\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"49\" target=\"65\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"49\" value=\"dxc\" style=\"rounded=1;whiteSpace=wrap;html=1;fontSize=24;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"240\" y=\"260\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"66\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"50\" target=\"65\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"50\" value=\"glslang\" style=\"rounded=1;whiteSpace=wrap;html=1;fontSize=24;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"240\" y=\"480\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"64\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"51\" target=\"63\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"51\" value=\"slang\" style=\"rounded=1;whiteSpace=wrap;html=1;fontSize=24;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"240\" y=\"160\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"57\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;DXIL&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"440\" y=\"260\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"63\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;PTX&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"440\" y=\"160\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"70\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"65\" target=\"69\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"73\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"65\" target=\"72\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"65\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;SPIR-V&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"240\" y=\"370\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"71\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"69\" target=\"46\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"69\" value=\"spirv-cross\" style=\"rounded=1;whiteSpace=wrap;html=1;fontSize=24;fillColor=#6a00ff;fontColor=#ffffff;strokeColor=#3700CC;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"20\" y=\"370\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"75\" style=\"edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontSize=24;\" edge=\"1\" parent=\"1\" source=\"72\" target=\"74\">\n                    <mxGeometry relative=\"1\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"72\" value=\"spirv-reflect\" style=\"rounded=1;whiteSpace=wrap;html=1;fontSize=24;fillColor=#6a00ff;fontColor=#ffffff;strokeColor=#3700CC;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"420\" y=\"370\" width=\"160\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n                <mxCell id=\"74\" value=\"&lt;font style=&quot;font-size: 24px;&quot;&gt;Meta Info&lt;/font&gt;\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#647687;fontColor=#ffffff;strokeColor=#314354;\" vertex=\"1\" parent=\"1\">\n                    <mxGeometry x=\"440\" y=\"480\" width=\"120\" height=\"60\" as=\"geometry\"/>\n                </mxCell>\n            </root>\n        </mxGraphModel>\n    </diagram>\n</mxfile>"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2021 Chaf-Graphics\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Ilum(WIP)\n\n[![Windows](https://github.com/Chaf-Libraries/Ilum/actions/workflows/windows_main.yml/badge.svg)](https://github.com/Chaf-Libraries/Ilum/actions/workflows/windows.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/b0cb3a2729ee4be783dd5feb2cc67eb6)](https://www.codacy.com/gh/Chaf-Libraries/IlumEngine/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=Chaf-Libraries/IlumEngine&amp;utm_campaign=Badge_Grade)\n\nIlum Graphics Playground, name after *Planet Ilum* from [star wars](https://starwars.fandom.com/wiki/Ilum).\n\nA framework for computer graphics learning and practice (It's not a game engine!)  \n[bilibili: Project demo video](https://www.bilibili.com/video/BV1Zy4y1f7PX/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=80dfe42ae16a11fb93eda40958202849)\n\n![image-20230212023548756](Doc/Img/image-20230212023548756.png)\n\n## Install\n\n**Platform**\n\n* Windows 10\n* Visual Studio 2022\n* xmake >= v2.7.5\n* [optional] CUDA >= 11.7\n\n**Build**\n\nIlum uses [xmake](https://xmake.io/#/) for building. You can compile the whole project by simply run command:\n\n```shell\nxmake -y\n```\n\nor you can open the project in Visual Studio by generating `.sln` file:\n\n```shell\nxmake project -k vsxmake\n```\n\n## Feature\n\n### Cross-Platform RHI\n\n* Vulkan\n  * Mesh Shading\n  * Dynamic Rendering\n  * Ray Tracing Pipeline\n  * Draw/Dispatch Indirect\n  * Bindless Resource\n\n* CUDA\n  * CUDA & Vulkan Interop\n\n\n### Resource Manager\n\n![](./Doc/Img/Resource.png)\n\n### Scene Graph\n\n![](./Doc/Img/Scene.png)\n\n### Shader Compilation\n\n![shader](Doc/Img/shader.png)\n\n### Render Graph\n\n* Static compilation\n* Automatic resource state tracking and transition\n* Texture memory aliasing\n* Seamless interoperation between Graphics API and CUDA\n* Easy to customize render pass\n\n**Render Pass**\n\n* Visibility Deferred Shading Pipeline\n\n  * Visibility Geometry Pass\n    * Mesh shading with meshlet frustum culling (if device support `mesh_shader`)\n    * Usual rasterization without optimization\n\n  * Visibility Buffer Visualization\n    * Visualize visibility buffer: instance and primitive\n  * Visibility Buffer Lighting Pass\n    * Indirect dispatch to support multiple material graphs\n    * Generate lighting result and GBuffer\n\n* Shadow\n\n  * Classic Shadow Map (Spot Light)\n  * Omnidirectional Shadow Map (Point Light)\n  * Cascade Shadow Map (Directional Light)\n\n* Ambient Occlusion\n  * SSAO\n\n* IBL\n  * Spherical Harmonic Encoding Diffuse\n  * Pre-Filter For Specular\n\n* Ray Tracing\n  * Path Tracing\n* Post Process\n  * Tone Mapping\n  * Bloom\n  * FXAA\n\n**TODO**\n\n* Resource Pool\n* Runtime compilation maybe\n* Multi-threading\n\n### Material Graph\n\n**Feature**\n\n* Static compilation and HLSL generation\n* Easy to customize material node\n* Support usual BSDF models\n\n### Plugins\n\nYou can extend the renderer features by adding these plugins:\n\n* RHI\n* Render Pass\n* Material Node\n* Importer\n* Editor\n\n#### Customize Render Pass\n\n\n\n#### Customize Material Node\n\n\n\n## Gallery\n\n### Render Graph Editor\n\n![image-20230210193225994](./Doc/Img/image-20230210193225994.png)\n\n### Material Graph Editor\n\n![image-20230210194028080](./Doc/Img/image-20230210194028080.png)\n\n### Path Tracing\n\n![](./Doc/Img/material.png)\n\n## Reference\n\n* [https://www.pbr-book.org/](https://www.pbr-book.org/)\n* [http://www.realtimerendering.com/](http://www.realtimerendering.com/)\n* [https://learnopengl-cn.github.io/](https://learnopengl-cn.github.io/)\n* [https://hazelengine.com/](https://hazelengine.com/)\n* [https://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf](https://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf)\n* [https://www.gdcvault.com/play/1024612/FrameGraph-Extensible-Rendering-Architecture-in](https://www.gdcvault.com/play/1024612/FrameGraph-Extensible-Rendering-Architecture-in)\n* [https://github.com/SaschaWillems/Vulkan](https://github.com/SaschaWillems/Vulkan)\n* [https://github.com/KhronosGroup/Vulkan-Samples](https://github.com/KhronosGroup/Vulkan-Samples)\n* [https://github.com/wdas/brdf](https://github.com/wdas/brdf)\n* [http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf.](http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf.)\n* [https://www.froyok.fr/blog/2021-12-ue4-custom-bloom/](https://www.froyok.fr/blog/2021-12-ue4-custom-bloom/)\n\n* [https://filmicworlds.com/blog/visibility-buffer-rendering-with-material-graphs](https://filmicworlds.com/blog/visibility-buffer-rendering-with-material-graphs)\n"
  },
  {
    "path": "Source/Editor/Editor.cpp",
    "content": "#include \"Editor.hpp\"\n#include \"ImGui/ImGuiContext.hpp\"\n#include \"Widget.hpp\"\n\n#include <Core/Plugin.hpp>\n#include <Scene/Components/Camera/Camera.hpp>\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n\n#include <filesystem>\n#include <regex>\n\nnamespace Ilum\n{\nstruct Editor::Impl\n{\n\tstd::unique_ptr<GuiContext> imgui_context = nullptr;\n\n\tRHIContext *rhi_context = nullptr;\n\tRenderer   *renderer    = nullptr;\n\n\tstd::vector<std::unique_ptr<Widget>> widgets;\n\n\tNode *select = nullptr;\n\n\tCmpt::Camera *main_camera = nullptr;\n};\n\nEditor::Editor(Window *window, RHIContext *rhi_context, Renderer *renderer)\n{\n\tm_impl = new Impl;\n\n\tm_impl->imgui_context = std::make_unique<GuiContext>(rhi_context, window);\n\tm_impl->renderer      = renderer;\n\tm_impl->rhi_context   = rhi_context;\n\n\tfor (const auto &file : std::filesystem::directory_iterator(\"shared/Editor/\"))\n\t{\n\t\tm_impl->widgets.emplace_back(std::unique_ptr<Widget>(std::move(PluginManager::GetInstance().Call<Widget *>(file.path().string(), \"Create\", this, ImGui::GetCurrentContext()))));\n\t}\n}\n\nEditor::~Editor()\n{\n\tm_impl->imgui_context.reset();\n\tdelete m_impl;\n}\n\nvoid Editor::PreTick()\n{\n\tm_impl->imgui_context->BeginFrame();\n}\n\nvoid Editor::Tick()\n{\n\tif (ImGui::BeginMainMenuBar())\n\t{\n\t\tif (ImGui::BeginMenu(\"Widget\"))\n\t\t{\n\t\t\tfor (auto &widget : m_impl->widgets)\n\t\t\t{\n\t\t\t\tImGui::MenuItem(widget->GetName().c_str(), nullptr, &widget->GetActive());\n\t\t\t}\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\tImGui::EndMainMenuBar();\n\t}\n\n\tfor (auto &widget : m_impl->widgets)\n\t{\n\t\tif (widget->GetActive())\n\t\t{\n\t\t\twidget->Tick();\n\t\t}\n\t}\n}\n\nvoid Editor::PostTick()\n{\n\tm_impl->imgui_context->EndFrame();\n\tm_impl->imgui_context->Render();\n}\n\nRenderer *Editor::GetRenderer() const\n{\n\treturn m_impl->renderer;\n}\n\nRHIContext *Editor::GetRHIContext() const\n{\n\treturn m_impl->rhi_context;\n}\n\nWindow *Editor::GetWindow() const\n{\n\treturn m_impl->imgui_context->GetWindow();\n}\n\nvoid Editor::SelectNode(Node *node)\n{\n\tm_impl->select = node;\n}\n\nvoid Editor::SetMainCamera(Cmpt::Camera *camera)\n{\n\tm_impl->main_camera = camera;\n}\n\nNode *Editor::GetSelectedNode() const\n{\n\treturn m_impl->select;\n}\n\nCmpt::Camera *Editor::GetMainCamera() const\n{\n\treturn m_impl->main_camera;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Editor/Editor.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\n#include <memory>\n#include <vector>\n\nnamespace Ilum\n{\nclass Window;\nclass RHIContext;\nclass GuiContext;\nclass Widget;\nclass Renderer;\nclass Node;\n\nnamespace Cmpt\n{\nclass Camera;\n}\n\nclass EXPORT_API Editor\n{\n  public:\n\tEditor(Window *window, RHIContext *rhi_context, Renderer *renderer);\n\n\t~Editor();\n\n\tvoid PreTick();\n\n\tvoid Tick();\n\n\tvoid PostTick();\n\n\tRenderer *GetRenderer() const;\n\n\tRHIContext *GetRHIContext() const;\n\n\tWindow *GetWindow() const;\n\n\tvoid SelectNode(Node *node = nullptr);\n\n\tvoid SetMainCamera(Cmpt::Camera *camera = nullptr);\n\n\tNode *GetSelectedNode() const;\n\n\tCmpt::Camera *GetMainCamera() const;\n\n  private:\n\tstruct Impl;\n\tImpl* m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Editor/ImGui/ImGuiContext.cpp",
    "content": "#include \"ImGuiContext.hpp\"\n\n#include <Core/Path.hpp>\n#include <ShaderCompiler/ShaderCompiler.hpp>\n\n#include <imgui.h>\n#include <imgui_impl_glfw.h>\n#include <imnodes/imnodes.h>\n#include <implot/implot.h>\n\n#include <IconsFontAwesome/IconsFontAwesome5.h>\n\n#include <GLFW/glfw3.h>\n#define GLFW_EXPOSE_NATIVE_WIN32\n#include <GLFW/glfw3native.h>\n\n#undef CreateSemaphore\n\nnamespace Ilum\n{\nstatic RHIContext       *gContext       = nullptr;\nstatic Window           *gWindow        = nullptr;\nstatic RHIPipelineState *gPipelineState = nullptr;\nstatic RHIDescriptor    *gDescriptor    = nullptr;\nstatic RHISampler       *gSampler       = nullptr;\nstatic RHIRenderTarget  *gRenderTarget  = nullptr;\n\nstruct ConstantBlock\n{\n\tglm::vec2 scale;\n\tglm::vec2 translate;\n};\n\nstruct ViewportResources\n{\n\tViewportResources(const std::string &name = \"subwindow\")\n\t{\n\t\tuniform_buffer = gContext->CreateBuffer(BufferDesc{\n\t\t    \"imgui_uniform_buffer - \" + name + std::to_string((uint64_t) this),\n\t\t    RHIBufferUsage::ConstantBuffer,\n\t\t    RHIMemoryUsage::CPU_TO_GPU,\n\t\t    sizeof(ConstantBlock),\n\t\t});\n\n\t\tfor (uint32_t i = 0; i < 3; i++)\n\t\t{\n\t\t\trender_completes[i]  = gContext->CreateSemaphore();\n\t\t\tpresent_completes[i] = gContext->CreateSemaphore();\n\t\t}\n\t}\n\n\tstd::unique_ptr<RHIBuffer> vertex_buffer  = nullptr;\n\tstd::unique_ptr<RHIBuffer> index_buffer   = nullptr;\n\tstd::unique_ptr<RHIBuffer> uniform_buffer = nullptr;\n\n\tstd::array<std::unique_ptr<RHISemaphore>, 3> render_completes;\n\tstd::array<std::unique_ptr<RHISemaphore>, 3> present_completes;\n\n\tstd::vector<RHICommand *> cmd_buffers;\n\n\tuint32_t vertex_count = 0;\n\tuint32_t index_count  = 0;\n\n\tuint32_t frame_index = 0;\n};\n\nstruct WindowData\n{\n\tstd::unique_ptr<ViewportResources> viewport_data;\n\tstd::unique_ptr<RHISwapchain>      swapchain;\n};\n\nstatic std::unique_ptr<ViewportResources> gResource;\n\nGuiContext::GuiContext(RHIContext *context, Window *window) :\n    p_context(context), p_window(window)\n{\n\tgContext = p_context;\n\tgWindow  = p_window;\n\n\tgResource = std::make_unique<ViewportResources>(\"mainwindows\");\n\n\tImGui::CreateContext();\n\n\tSetStyle();\n\n\tImGui_ImplGlfw_InitForOther(window->GetHandle(), true);\n\n\tm_pipeline_state = context->CreatePipelineState();\n\tm_render_target  = context->CreateRenderTarget();\n\tm_sampler        = context->CreateSampler(SamplerDesc{\n        RHIFilter::Linear,\n        RHIFilter::Linear,\n        RHIAddressMode::Clamp_To_Edge,\n        RHIAddressMode::Clamp_To_Edge,\n        RHIAddressMode::Clamp_To_Edge,\n        RHIMipmapMode::Linear,\n        RHISamplerBorderColor::Float_Opaque_White});\n\n\t// Setup pipeline state\n\tDepthStencilState depth_stencil_state  = {};\n\tdepth_stencil_state.depth_test_enable  = false;\n\tdepth_stencil_state.depth_write_enable = false;\n\tdepth_stencil_state.compare            = RHICompareOp::Always;\n\n\tRasterizationState rasterization_state = {};\n\trasterization_state.cull_mode          = RHICullMode::None;\n\trasterization_state.polygon_mode       = RHIPolygonMode::Solid;\n\trasterization_state.front_face         = RHIFrontFace::Clockwise;\n\n\tInputAssemblyState input_assembly_state = {};\n\tinput_assembly_state.topology           = RHIPrimitiveTopology::Triangle;\n\n\tBlendState blend_state = {};\n\tblend_state.enable     = false;\n\tblend_state.attachment_states.push_back(BlendState::AttachmentState{\n\t    true,\n\t    RHIBlendFactor::Src_Alpha,\n\t    RHIBlendFactor::One_Minus_Src_Alpha,\n\t    RHIBlendOp::Add,\n\t    RHIBlendFactor::One,\n\t    RHIBlendFactor::One_Minus_Src_Alpha,\n\t    RHIBlendOp::Add,\n\t    1 | 2 | 4 | 8});\n\n\tVertexInputState vertex_input_state = {};\n\tvertex_input_state.input_attributes = {\n\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32_FLOAT, offsetof(ImDrawVert, pos)},\n\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 1, 0, RHIFormat::R32G32_FLOAT, offsetof(ImDrawVert, uv)},\n\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 2, 0, RHIFormat::R8G8B8A8_UNORM, offsetof(ImDrawVert, col)},\n\t};\n\n\tvertex_input_state.input_bindings = {\n\t    VertexInputState::InputBinding{0, sizeof(ImDrawVert), RHIVertexInputRate::Vertex}};\n\n\t/*std::vector<uint8_t> raw_shader;\n\tPath::GetInstance().Read(\"./Source/Shaders/ImGui.hlsl\", raw_shader);\n\n\tstd::string shader_source;\n\tshader_source.resize(raw_shader.size());\n\tstd::memcpy(shader_source.data(), raw_shader.data(), raw_shader.size());\n\tshader_source += \"\\n\";\n\n\tShaderDesc vertex_shader_desc  = {};\n\tvertex_shader_desc.entry_point = \"VSmain\";\n\tvertex_shader_desc.stage       = RHIShaderStage::Vertex;\n\tvertex_shader_desc.source      = ShaderSource::HLSL;\n\tvertex_shader_desc.target      = ShaderTarget::SPIRV;\n\tvertex_shader_desc.code        = shader_source;\n\tvertex_shader_desc.macros      = {\"VULKAN_BACKEND\"};\n\n\tShaderDesc fragment_shader_desc  = {};\n\tfragment_shader_desc.entry_point = \"PSmain\";\n\tfragment_shader_desc.stage       = RHIShaderStage::Fragment;\n\tfragment_shader_desc.source      = ShaderSource::HLSL;\n\tfragment_shader_desc.target      = ShaderTarget::SPIRV;\n\tfragment_shader_desc.code        = shader_source;\n\tfragment_shader_desc.macros      = {\"VULKAN_BACKEND\"};\n\n\tShaderMeta vertex_meta   = {};\n\tShaderMeta fragment_meta = {};\n\n\tauto vertex_shader_spirv   = ShaderCompiler::GetInstance().Compile(vertex_shader_desc, vertex_meta);\n\tauto fragment_shader_spirv = ShaderCompiler::GetInstance().Compile(fragment_shader_desc, fragment_meta);\n\n\tm_vertex_shader   = p_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\tm_fragment_shader = p_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\tShaderMeta shader_meta= vertex_meta;\n\tshader_meta += fragment_meta;*/\n\n\tShaderMeta           shader_meta;\n\tstd::vector<uint8_t> vertex_shader_spirv;\n\tstd::vector<uint8_t> fragment_shader_spirv;\n\tDESERIALIZE(\"Asset/BuildIn/ImGui.spv.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\n\tm_vertex_shader   = p_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\tm_fragment_shader = p_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\tm_descriptor = p_context->CreateDescriptor(shader_meta);\n\n\tm_pipeline_state->SetDepthStencilState(depth_stencil_state);\n\tm_pipeline_state->SetRasterizationState(rasterization_state);\n\tm_pipeline_state->SetVertexInputState(vertex_input_state);\n\tm_pipeline_state->SetBlendState(blend_state);\n\tm_pipeline_state->SetInputAssemblyState(input_assembly_state);\n\tm_pipeline_state->SetShader(RHIShaderStage::Vertex, m_vertex_shader.get());\n\tm_pipeline_state->SetShader(RHIShaderStage::Fragment, m_fragment_shader.get());\n\n\t// Font atlas\n\tunsigned char *pixels;\n\tint32_t        atlas_width, atlas_height, bpp;\n\tauto          &io = ImGui::GetIO();\n\tio.Fonts->GetTexDataAsRGBA32(&pixels, &atlas_width, &atlas_height, &bpp);\n\n\tconst uint32_t size = atlas_width * atlas_height * bpp;\n\n\tauto buffer = p_context->CreateBuffer(static_cast<size_t>(size), RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\tstd::memcpy(buffer->Map(), pixels, size);\n\tbuffer->Unmap();\n\n\tm_font_atlas = p_context->CreateTexture2D(atlas_width, atlas_height, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer, false);\n\n\tauto *cmd_buffer = p_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->BeginMarker(\"UI\");\n\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t                                        m_font_atlas.get(),\n\t                                        RHIResourceState::Undefined,\n\t                                        RHIResourceState::TransferDest,\n\t                                        TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t                                    {});\n\tcmd_buffer->CopyBufferToTexture(buffer.get(), m_font_atlas.get(), 0, 0, 1);\n\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t                                        m_font_atlas.get(),\n\t                                        RHIResourceState::TransferDest,\n\t                                        RHIResourceState::ShaderResource,\n\t                                        TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t                                    {});\n\tcmd_buffer->EndMarker();\n\tcmd_buffer->End();\n\n\tp_context->Execute(cmd_buffer);\n\n\tio.Fonts->TexID = static_cast<ImTextureID>(m_font_atlas.get());\n\n\tgPipelineState = m_pipeline_state.get();\n\tgDescriptor    = m_descriptor;\n\tgSampler       = m_sampler;\n\tgRenderTarget  = m_render_target.get();\n\n\tInitializePlatformInterface();\n}\n\nGuiContext::~GuiContext()\n{\n\tImGui_ImplGlfw_Shutdown();\n\tImGui::DestroyContext();\n\n\tgContext       = nullptr;\n\tgWindow        = nullptr;\n\tgPipelineState = nullptr;\n\tgDescriptor    = nullptr;\n\tgSampler       = nullptr;\n\tgRenderTarget  = nullptr;\n\n\tgResource.reset();\n}\n\nvoid GuiContext::BeginFrame()\n{\n\tImGui_ImplGlfw_NewFrame();\n\tImGui::NewFrame();\n\n\tImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking;\n\twindow_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;\n\twindow_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;\n\tImGuiViewport *viewport = ImGui::GetMainViewport();\n\tImGui::SetNextWindowPos(viewport->WorkPos);\n\tImGui::SetNextWindowSize(viewport->WorkSize);\n\tImGui::SetNextWindowViewport(viewport->ID);\n\tImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);\n\tImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);\n\tImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));\n\tImGui::Begin(\"DockSpace\", (bool *) 1, window_flags);\n\tImGui::PopStyleVar();\n\tImGui::PopStyleVar(2);\n\n\tImGuiIO &io = ImGui::GetIO();\n\tif (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)\n\t{\n\t\tImGuiID dockspace_id = ImGui::GetID(\"DockSpace\");\n\t\tImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);\n\t}\n}\n\nvoid GuiContext::EndFrame()\n{\n\tImGui::End();\n\tImGuiIO &io    = ImGui::GetIO();\n\tio.DisplaySize = ImVec2(static_cast<float>(gWindow->GetWidth()), static_cast<float>(gWindow->GetHeight()));\n\n\tImGui::EndFrame();\n\n\tImGui::Render();\n\n\tif (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)\n\t{\n\t\tImGui::UpdatePlatformWindows();\n\t\tImGui::RenderPlatformWindowsDefault();\n\t}\n}\n\nvoid GuiContext::SetStyle()\n{\n\tImGuiIO &io = ImGui::GetIO();\n\t(void) io;\n\tio.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;\n\tio.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;\n\tio.ConfigFlags |= ImGuiConfigFlags_DockingEnable;\n\tio.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;\n\n\tio.BackendFlags |= ImGuiBackendFlags_RendererHasViewports;\n\n\t// Set fonts\n\tstatic const ImWchar icon_ranges[] = {ICON_MIN_FA, ICON_MAX_FA, 0};\n\tImFontConfig         config;\n\tconfig.MergeMode        = true;\n\tconfig.GlyphMinAdvanceX = 13.0f;\n\tio.Fonts->AddFontFromFileTTF(\"./Asset/Font/ArialUnicodeMS.ttf\", 20.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());\n\tio.Fonts->AddFontFromFileTTF(\"./Asset/Font/fontawesome-webfont.ttf\", 15.0f, &config, icon_ranges);\n\n\t// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.\n\tImGuiStyle &style  = ImGui::GetStyle();\n\tauto        colors = style.Colors;\n\n\tif (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)\n\t{\n\t\tstyle.WindowRounding              = 0.0f;\n\t\tstyle.Colors[ImGuiCol_WindowBg].w = 1.0f;\n\t}\n\n\tcolors[ImGuiCol_Text]                  = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n\tcolors[ImGuiCol_TextDisabled]          = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);\n\tcolors[ImGuiCol_WindowBg]              = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);\n\tcolors[ImGuiCol_ChildBg]               = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\n\tcolors[ImGuiCol_PopupBg]               = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);\n\tcolors[ImGuiCol_Border]                = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);\n\tcolors[ImGuiCol_BorderShadow]          = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\n\tcolors[ImGuiCol_FrameBg]               = ImVec4(0.44f, 0.44f, 0.44f, 0.60f);\n\tcolors[ImGuiCol_FrameBgHovered]        = ImVec4(0.57f, 0.57f, 0.57f, 0.70f);\n\tcolors[ImGuiCol_FrameBgActive]         = ImVec4(0.76f, 0.76f, 0.76f, 0.80f);\n\tcolors[ImGuiCol_TitleBg]               = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);\n\tcolors[ImGuiCol_TitleBgActive]         = ImVec4(0.16f, 0.16f, 0.16f, 1.00f);\n\tcolors[ImGuiCol_TitleBgCollapsed]      = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);\n\tcolors[ImGuiCol_MenuBarBg]             = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);\n\tcolors[ImGuiCol_ScrollbarBg]           = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);\n\tcolors[ImGuiCol_ScrollbarGrab]         = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);\n\tcolors[ImGuiCol_ScrollbarGrabHovered]  = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);\n\tcolors[ImGuiCol_ScrollbarGrabActive]   = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);\n\tcolors[ImGuiCol_CheckMark]             = ImVec4(0.13f, 0.75f, 0.55f, 0.80f);\n\tcolors[ImGuiCol_SliderGrab]            = ImVec4(0.13f, 0.75f, 0.75f, 0.80f);\n\tcolors[ImGuiCol_SliderGrabActive]      = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);\n\tcolors[ImGuiCol_Button]                = ImVec4(0.13f, 0.75f, 0.55f, 0.40f);\n\tcolors[ImGuiCol_ButtonHovered]         = ImVec4(0.13f, 0.75f, 0.75f, 0.60f);\n\tcolors[ImGuiCol_ButtonActive]          = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);\n\tcolors[ImGuiCol_Header]                = ImVec4(0.13f, 0.75f, 0.55f, 0.40f);\n\tcolors[ImGuiCol_HeaderHovered]         = ImVec4(0.13f, 0.75f, 0.75f, 0.60f);\n\tcolors[ImGuiCol_HeaderActive]          = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);\n\tcolors[ImGuiCol_Separator]             = ImVec4(0.13f, 0.75f, 0.55f, 0.40f);\n\tcolors[ImGuiCol_SeparatorHovered]      = ImVec4(0.13f, 0.75f, 0.75f, 0.60f);\n\tcolors[ImGuiCol_SeparatorActive]       = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);\n\tcolors[ImGuiCol_ResizeGrip]            = ImVec4(0.13f, 0.75f, 0.55f, 0.40f);\n\tcolors[ImGuiCol_ResizeGripHovered]     = ImVec4(0.13f, 0.75f, 0.75f, 0.60f);\n\tcolors[ImGuiCol_ResizeGripActive]      = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);\n\tcolors[ImGuiCol_Tab]                   = ImVec4(0.13f, 0.75f, 0.55f, 0.80f);\n\tcolors[ImGuiCol_TabHovered]            = ImVec4(0.13f, 0.75f, 0.75f, 0.80f);\n\tcolors[ImGuiCol_TabActive]             = ImVec4(0.13f, 0.75f, 1.00f, 0.80f);\n\tcolors[ImGuiCol_TabUnfocused]          = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);\n\tcolors[ImGuiCol_TabUnfocusedActive]    = ImVec4(0.36f, 0.36f, 0.36f, 0.54f);\n\tcolors[ImGuiCol_DockingPreview]        = ImVec4(0.13f, 0.75f, 0.55f, 0.80f);\n\tcolors[ImGuiCol_DockingEmptyBg]        = ImVec4(0.13f, 0.13f, 0.13f, 0.80f);\n\tcolors[ImGuiCol_PlotLines]             = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);\n\tcolors[ImGuiCol_PlotLinesHovered]      = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);\n\tcolors[ImGuiCol_PlotHistogram]         = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);\n\tcolors[ImGuiCol_PlotHistogramHovered]  = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);\n\tcolors[ImGuiCol_TableHeaderBg]         = ImVec4(0.19f, 0.19f, 0.20f, 1.00f);\n\tcolors[ImGuiCol_TableBorderStrong]     = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);\n\tcolors[ImGuiCol_TableBorderLight]      = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);\n\tcolors[ImGuiCol_TableRowBg]            = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\n\tcolors[ImGuiCol_TableRowBgAlt]         = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);\n\tcolors[ImGuiCol_TextSelectedBg]        = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);\n\tcolors[ImGuiCol_DragDropTarget]        = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);\n\tcolors[ImGuiCol_NavHighlight]          = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);\n\tcolors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);\n\tcolors[ImGuiCol_NavWindowingDimBg]     = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);\n\tcolors[ImGuiCol_ModalWindowDimBg]      = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);\n\n\tstyle.WindowPadding     = ImVec2(8.00f, 8.00f);\n\tstyle.FramePadding      = ImVec2(5.00f, 2.00f);\n\tstyle.CellPadding       = ImVec2(6.00f, 6.00f);\n\tstyle.ItemSpacing       = ImVec2(6.00f, 6.00f);\n\tstyle.ItemInnerSpacing  = ImVec2(6.00f, 6.00f);\n\tstyle.TouchExtraPadding = ImVec2(0.00f, 0.00f);\n\tstyle.IndentSpacing     = 25;\n\tstyle.ScrollbarSize     = 15;\n\tstyle.GrabMinSize       = 10;\n\tstyle.WindowBorderSize  = 1;\n\tstyle.ChildBorderSize   = 1;\n\tstyle.PopupBorderSize   = 1;\n\tstyle.FrameBorderSize   = 1;\n\tstyle.TabBorderSize     = 1;\n\tstyle.WindowRounding    = 7;\n\tstyle.ChildRounding     = 4;\n\tstyle.FrameRounding     = 3;\n\tstyle.PopupRounding     = 4;\n\tstyle.ScrollbarRounding = 9;\n\tstyle.GrabRounding      = 3;\n\tstyle.LogSliderDeadzone = 4;\n\tstyle.TabRounding       = 4;\n}\n\nstatic void RHI_Render(ImDrawData *draw_data, WindowData *window_data = nullptr)\n{\n\tsize_t vertex_buffer_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);\n\tsize_t index_buffer_size  = draw_data->TotalIdxCount * sizeof(ImDrawIdx);\n\n\tif (draw_data->DisplaySize.x == 0 ||\n\t    draw_data->DisplaySize.y == 0)\n\t{\n\t\treturn;\n\t}\n\n\tbool               is_child_window = window_data != nullptr;\n\tRHISwapchain      *swapchain       = is_child_window ? window_data->swapchain.get() : gContext->GetSwapchain();\n\tViewportResources *resources       = is_child_window ? window_data->viewport_data.get() : gResource.get();\n\n\tauto &vertex_buffer  = resources->vertex_buffer;\n\tauto &index_buffer   = resources->index_buffer;\n\tauto &uniform_buffer = resources->uniform_buffer;\n\n\tauto &vertex_count = resources->vertex_count;\n\tauto &index_count  = resources->index_count;\n\n\tif (vertex_buffer == nullptr || vertex_count != static_cast<uint32_t>(draw_data->TotalVtxCount))\n\t{\n\t\tif (vertex_buffer_size != 0)\n\t\t{\n\t\t\tvertex_buffer.reset();\n\t\t\tvertex_buffer = gContext->CreateBuffer(vertex_buffer_size, RHIBufferUsage::Vertex, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\tvertex_count  = draw_data->TotalVtxCount;\n\t\t\tvertex_buffer->Map();\n\t\t}\n\t}\n\n\tif (index_buffer == nullptr || index_count < static_cast<uint32_t>(draw_data->TotalIdxCount))\n\t{\n\t\tif (index_buffer_size != 0)\n\t\t{\n\t\t\tindex_buffer.reset();\n\t\t\tindex_buffer = gContext->CreateBuffer(index_buffer_size, RHIBufferUsage::Index, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\tindex_count  = draw_data->TotalIdxCount;\n\t\t\tindex_buffer->Map();\n\t\t}\n\t}\n\n\tImDrawVert *vtx_dst = vertex_buffer ? (ImDrawVert *) vertex_buffer->Map() : nullptr;\n\tImDrawIdx  *idx_dst = index_buffer ? (ImDrawIdx *) index_buffer->Map() : nullptr;\n\n\tfor (int n = 0; n < draw_data->CmdListsCount; n++)\n\t{\n\t\tconst ImDrawList *cmd_list = draw_data->CmdLists[n];\n\t\tif (vtx_dst)\n\t\t{\n\t\t\tmemcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));\n\t\t}\n\t\tif (idx_dst)\n\t\t{\n\t\t\tmemcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));\n\t\t}\n\t\tvtx_dst += cmd_list->VtxBuffer.Size;\n\t\tidx_dst += cmd_list->IdxBuffer.Size;\n\t}\n\n\tif (vertex_buffer)\n\t{\n\t\tvertex_buffer->Flush(0, vertex_buffer->GetDesc().size);\n\t}\n\n\tif (index_buffer)\n\t{\n\t\tindex_buffer->Flush(0, index_buffer->GetDesc().size);\n\t}\n\n\tint32_t fb_width  = (int32_t) (draw_data->DisplaySize.x * draw_data->FramebufferScale.x);\n\tint32_t fb_height = (int32_t) (draw_data->DisplaySize.y * draw_data->FramebufferScale.y);\n\tif (fb_width <= 0 || fb_height <= 0)\n\t{\n\t\treturn;\n\t}\n\n\tConstantBlock constant_block = {};\n\tconstant_block.scale         = glm::vec2(2.0f / draw_data->DisplaySize.x, 2.0f / draw_data->DisplaySize.y);\n\tconstant_block.translate     = glm::vec2(-1.0f - draw_data->DisplayPos.x * constant_block.scale[0], -1.0f - draw_data->DisplayPos.y * constant_block.scale[1]);\n\n\tstd::memcpy(uniform_buffer->Map(), &constant_block, sizeof(constant_block));\n\n\tgDescriptor->BindSampler(\"fontSampler\", gSampler);\n\tgDescriptor->BindBuffer(\"constant\", uniform_buffer.get());\n\n\tgRenderTarget->Clear();\n\tColorAttachment attachment = {};\n\tattachment.clear_value[3]  = 1.f;\n\tgRenderTarget->Set(0, swapchain->GetCurrentTexture(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, ColorAttachment{});\n\n\tauto *cmd_buffer = gContext->CreateCommand(RHIQueueFamily::Graphics);\n\n\tcmd_buffer->Begin();\n\tcmd_buffer->BeginMarker(\"UI\");\n\n\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t                                        swapchain->GetCurrentTexture(),\n\t                                        RHIResourceState::Present,\n\t                                        RHIResourceState::RenderTarget,\n\t                                        TextureRange{\n\t                                            RHITextureDimension::Texture2D,\n\t                                            0, 1, 0, 1}}},\n\t                                    {});\n\n\tcmd_buffer->SetViewport(draw_data->DisplaySize.x, draw_data->DisplaySize.y);\n\n\tcmd_buffer->BeginRenderPass(gRenderTarget);\n\n\tint32_t global_vtx_offset = 0;\n\tint32_t global_idx_offset = 0;\n\n\tconst ImVec2 &clip_off   = draw_data->DisplayPos;\n\tImVec2        clip_scale = draw_data->FramebufferScale;\n\n\tvoid *current_texture = nullptr;\n\n\tfor (int32_t i = 0; i < draw_data->CmdListsCount; i++)\n\t{\n\t\tcmd_buffer->BindVertexBuffer(0, vertex_buffer.get());\n\t\tcmd_buffer->BindIndexBuffer(index_buffer.get(), true);\n\n\t\tImDrawList *cmd_list_imgui = draw_data->CmdLists[i];\n\t\tfor (int32_t cmd_i = 0; cmd_i < cmd_list_imgui->CmdBuffer.Size; cmd_i++)\n\t\t{\n\t\t\tconst ImDrawCmd *pcmd = &cmd_list_imgui->CmdBuffer[cmd_i];\n\t\t\tif (pcmd->UserCallback != nullptr)\n\t\t\t{\n\t\t\t\tpcmd->UserCallback(cmd_list_imgui, pcmd);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);\n\t\t\t\tImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);\n\n\t\t\t\tif (clip_min.x < 0.0f)\n\t\t\t\t{\n\t\t\t\t\tclip_min.x = 0.0f;\n\t\t\t\t}\n\t\t\t\tif (clip_min.y < 0.0f)\n\t\t\t\t{\n\t\t\t\t\tclip_min.y = 0.0f;\n\t\t\t\t}\n\t\t\t\tif (clip_max.x > fb_width)\n\t\t\t\t{\n\t\t\t\t\tclip_max.x = (float) fb_width;\n\t\t\t\t}\n\t\t\t\tif (clip_max.y > fb_height)\n\t\t\t\t{\n\t\t\t\t\tclip_max.y = (float) fb_height;\n\t\t\t\t}\n\t\t\t\tif (clip_max.x < clip_min.x || clip_max.y < clip_min.y)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcmd_buffer->SetScissor((uint32_t) (clip_max.x - clip_min.x), (uint32_t) (clip_max.y - clip_min.y), (int32_t) (clip_min.x), (int32_t) (clip_min.y));\n\n\t\t\t\tif (current_texture != pcmd->TextureId)\n\t\t\t\t{\n\t\t\t\t\tauto texture = static_cast<RHITexture *>(pcmd->TextureId);\n\t\t\t\t\tgDescriptor->BindTexture(\"fontTexture\", static_cast<RHITexture *>(pcmd->TextureId), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1});\n\t\t\t\t\tcmd_buffer->BindDescriptor(gDescriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(gPipelineState);\n\t\t\t\t\tcurrent_texture = pcmd->TextureId;\n\t\t\t\t}\n\n\t\t\t\tcmd_buffer->DrawIndexed(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);\n\t\t\t}\n\t\t}\n\t\tglobal_idx_offset += cmd_list_imgui->IdxBuffer.Size;\n\t\tglobal_vtx_offset += cmd_list_imgui->VtxBuffer.Size;\n\t}\n\n\tcmd_buffer->EndRenderPass();\n\n\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t                                        swapchain->GetCurrentTexture(),\n\t                                        RHIResourceState::RenderTarget,\n\t                                        RHIResourceState::Present,\n\t                                        TextureRange{\n\t                                            RHITextureDimension::Texture2D,\n\t                                            0, 1, 0, 1}}},\n\t                                    {});\n\n\tcmd_buffer->EndMarker();\n\tcmd_buffer->End();\n\n\tif (is_child_window)\n\t{\n\t\tresources->cmd_buffers.push_back(cmd_buffer);\n\t}\n\telse\n\t{\n\t\tgContext->Submit({cmd_buffer}, {}, {});\n\t}\n}\n\nstatic void ImGuiWindowCreate(ImGuiViewport *viewport)\n{\n\tWindowData *window = new WindowData();\n\n\twindow->swapchain = gContext->CreateSwapchain(\n#ifdef _WIN32\n\t    glfwGetWin32Window((GLFWwindow *) viewport->PlatformHandle),\n#endif        // _WIN32\n\t    static_cast<uint32_t>(viewport->Size.x),\n\t    static_cast<uint32_t>(viewport->Size.y),\n\t    gContext->IsVsync());\n\n\twindow->viewport_data = std::make_unique<ViewportResources>();\n\n\tviewport->RendererUserData = window;\n}\n\nstatic void ImGuiWindowDestroy(ImGuiViewport *viewport)\n{\n\tif (WindowData *window = static_cast<WindowData *>(viewport->RendererUserData))\n\t{\n\t\tgContext->WaitIdle();\n\t\tdelete window;\n\t}\n\tviewport->RendererUserData = nullptr;\n}\n\nstatic void ImGuiWindowSetSize(ImGuiViewport *viewport, const ImVec2 size)\n{\n\tstatic_cast<WindowData *>(viewport->RendererUserData)->swapchain->Resize(static_cast<uint32_t>(size.x), static_cast<uint32_t>(size.y), gContext->IsVsync());\n}\n\nstatic void ImGuiWindowRender(ImGuiViewport *viewport, void *)\n{\n\tWindowData *window_data = static_cast<WindowData *>(viewport->RendererUserData);\n\twindow_data->swapchain->AcquireNextTexture(window_data->viewport_data->present_completes.at(window_data->viewport_data->frame_index).get(), nullptr);\n\tRHI_Render(viewport->DrawData, window_data);\n}\n\nstatic void ImGuiWindowPresent(ImGuiViewport *viewport, void *)\n{\n\tWindowData *window_data = static_cast<WindowData *>(viewport->RendererUserData);\n\n\tgContext->Execute(\n\t    std::move(window_data->viewport_data->cmd_buffers),\n\t    {window_data->viewport_data->present_completes.at(window_data->viewport_data->frame_index).get()},\n\t    {window_data->viewport_data->render_completes.at(window_data->viewport_data->frame_index).get()},\n\t    gContext->CreateFrameFence());\n\twindow_data->viewport_data->cmd_buffers.clear();\n\n\twindow_data->swapchain->Present(window_data->viewport_data->render_completes.at(window_data->viewport_data->frame_index).get());\n\twindow_data->viewport_data->frame_index = (window_data->viewport_data->frame_index + 1) % 3;\n}\n\nvoid GuiContext::Render()\n{\n\tRHI_Render(ImGui::GetDrawData());\n}\n\nWindow *GuiContext::GetWindow() const\n{\n\treturn p_window;\n}\n\nvoid GuiContext::InitializePlatformInterface()\n{\n\tImGuiPlatformIO &platform_io       = ImGui::GetPlatformIO();\n\tplatform_io.Renderer_CreateWindow  = ImGuiWindowCreate;\n\tplatform_io.Renderer_DestroyWindow = ImGuiWindowDestroy;\n\tplatform_io.Renderer_SetWindowSize = ImGuiWindowSetSize;\n\tplatform_io.Renderer_RenderWindow  = ImGuiWindowRender;\n\tplatform_io.Renderer_SwapBuffers   = ImGuiWindowPresent;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Editor/ImGui/ImGuiContext.hpp",
    "content": "#pragma once\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass GuiContext\n{\n  public:\n\tGuiContext(RHIContext *context, Window *window);\n\n\t~GuiContext();\n\n\tvoid BeginFrame();\n\n\tvoid EndFrame();\n\n\tvoid Render();\n\n\tWindow *GetWindow() const;\n\n  private:\n\tvoid SetStyle();\n\n\tvoid InitializePlatformInterface();\n\n  private:\n\tRHIContext *p_context = nullptr;\n\tWindow     *p_window  = nullptr;\n\n\tstd::unique_ptr<RHIPipelineState> m_pipeline_state = nullptr;\n\tRHIDescriptor*    m_descriptor     = nullptr;\n\n\tRHISampler* m_sampler = nullptr;\n\n\tstd::unique_ptr<RHIShader> m_vertex_shader   = nullptr;\n\tstd::unique_ptr<RHIShader> m_fragment_shader = nullptr;\n\n\tstd::unique_ptr<RHIRenderTarget> m_render_target = nullptr;\n\n\tstd::unique_ptr<RHITexture> m_font_atlas = nullptr;\n\n\tsize_t m_vertex_count = 0;\n\tsize_t m_index_count  = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Editor/Precompile.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n"
  },
  {
    "path": "Source/Editor/Widget.hpp",
    "content": "#pragma once\n\n#include <string>\n\nnamespace Ilum\n{\nclass Editor;\n\nclass Widget\n{\n  public:\n\tWidget(const std::string &name, Editor *editor) :\n\t    m_name(name), p_editor(editor)\n\t{\n\t}\n\n\tvirtual ~Widget() = default;\n\n\tvirtual void Tick() = 0;\n\n\tinline bool &GetActive()\n\t{\n\t\treturn m_active;\n\t}\n\n\tconst std::string& GetName() const\n\t{\n\t\treturn m_name;\n\t}\n\n  protected:\n\tEditor *p_editor = nullptr;\n\n\tstd::string m_name;\n\n\tbool m_active = true;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Engine/Engine.cpp",
    "content": "#include \"Engine.hpp\"\n\n#include <Core/Path.hpp>\n#include <Core/Window.hpp>\n#include <Editor/Editor.hpp>\n#include <RHI/RHIContext.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Scene.hpp>\n\nnamespace Ilum\n{\nEngine::Engine()\n{\n\tm_window           = std::make_unique<Window>(\"Ilum\", \"Asset/Icon/logo.bmp\");\n\tm_rhi_context      = std::make_unique<RHIContext>(m_window.get(), \"Vulkan\", true);\n\tm_resource_manager = std::make_unique<ResourceManager>(m_rhi_context.get());\n\tm_scene            = std::make_unique<Scene>(\"Default Scene\");\n\tm_renderer         = std::make_unique<Renderer>(m_rhi_context.get(), m_scene.get(), m_resource_manager.get());\n\tm_editor           = std::make_unique<Editor>(m_window.get(), m_rhi_context.get(), m_renderer.get());\n\n\tPath::GetInstance().SetCurrent(\"./\");\n}\n\nEngine::~Engine()\n{\n\tm_scene.reset();\n\tm_editor.reset();\n\tm_renderer.reset();\n\tm_resource_manager.reset();\n\tm_rhi_context.reset();\n\tm_window.reset();\n}\n\nvoid Engine::Tick()\n{\n\twhile (m_window->Tick())\n\t{\n\t\tm_timer.Tick();\n\n\t\tif (m_window->GetWidth() != 0 && m_window->GetHeight() != 0)\n\t\t{\n\t\t\tm_rhi_context->BeginFrame();\n\n\t\t\t// Render loop\n\t\t\tm_renderer->Tick();\n\n\t\t\t// Update resource manager\n\t\t\tm_resource_manager->Tick();\n\n\t\t\t// Render UI\n\t\t\tm_editor->PreTick();\n\t\t\tm_editor->Tick();\n\t\t\tm_editor->PostTick();\n\n\t\t\tm_rhi_context->EndFrame();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds(16));\n\t\t}\n\n\t\tm_window->SetTitle(fmt::format(\"IlumEngine v{} | Scene - {} | FPS - {}\",\n\t\t                               \"1.0Beta\",\n\t\t                               m_scene->GetName(),\n\t\t                               m_timer.FrameRate()));\n\t}\n}\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Engine/Engine.hpp",
    "content": "#pragma once\n\n#include <Core/Time.hpp>\n\nnamespace Ilum\n{\nclass Window;\nclass RHIContext;\nclass Editor;\nclass ResourceManager;\nclass Renderer;\nclass Scene;\n\nclass Engine\n{\n  public:\n\tEngine();\n\n\t~Engine();\n\n\tvoid Tick();\n\n  private:\n\tstd::unique_ptr<Window>     m_window      = nullptr;\n\tstd::unique_ptr<RHIContext> m_rhi_context = nullptr;\n\tstd::unique_ptr<ResourceManager> m_resource_manager = nullptr;\n\tstd::unique_ptr<Scene>      m_scene       = nullptr;\n\tstd::unique_ptr<Renderer> m_renderer = nullptr;\n\tstd::unique_ptr<Editor> m_editor = nullptr;\n\n\tTimer m_timer;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Engine/Precompile.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>"
  },
  {
    "path": "Source/Engine/main.cpp",
    "content": "#include \"Engine.hpp\"\n\n#include <ShaderCompiler/ShaderCompiler.hpp> \n\nint main()\n{\n\tIlum::Engine engine;\n\t//Ilum::ShaderCompiler::GetInstance();\n\n\tengine.Tick();\n\n\treturn 0;\n}"
  },
  {
    "path": "Source/External/dxc/inc/d3d12shader.h",
    "content": "//////////////////////////////////////////////////////////////////////////////\n//\n//  Copyright (c) Microsoft Corporation.\n//  Licensed under the MIT license.\n//\n//  File:       D3D12Shader.h\n//  Content:    D3D12 Shader Types and APIs\n//\n//////////////////////////////////////////////////////////////////////////////\n\n#ifndef __D3D12SHADER_H__\n#define __D3D12SHADER_H__\n\n#include \"d3dcommon.h\"\n\ntypedef enum D3D12_SHADER_VERSION_TYPE\n{\n    D3D12_SHVER_PIXEL_SHADER          = 0,\n    D3D12_SHVER_VERTEX_SHADER         = 1,\n    D3D12_SHVER_GEOMETRY_SHADER       = 2,\n    \n    // D3D11 Shaders\n    D3D12_SHVER_HULL_SHADER           = 3,\n    D3D12_SHVER_DOMAIN_SHADER         = 4,\n    D3D12_SHVER_COMPUTE_SHADER        = 5,\n\n    // D3D12 Shaders\n    D3D12_SHVER_LIBRARY               = 6,\n\n    D3D12_SHVER_RAY_GENERATION_SHADER = 7,\n    D3D12_SHVER_INTERSECTION_SHADER   = 8,\n    D3D12_SHVER_ANY_HIT_SHADER        = 9,\n    D3D12_SHVER_CLOSEST_HIT_SHADER    = 10,\n    D3D12_SHVER_MISS_SHADER           = 11,\n    D3D12_SHVER_CALLABLE_SHADER       = 12,\n\n    D3D12_SHVER_MESH_SHADER           = 13,\n    D3D12_SHVER_AMPLIFICATION_SHADER  = 14,\n\n    D3D12_SHVER_RESERVED0             = 0xFFF0,\n} D3D12_SHADER_VERSION_TYPE;\n\n#define D3D12_SHVER_GET_TYPE(_Version) \\\n    (((_Version) >> 16) & 0xffff)\n#define D3D12_SHVER_GET_MAJOR(_Version) \\\n    (((_Version) >> 4) & 0xf)\n#define D3D12_SHVER_GET_MINOR(_Version) \\\n    (((_Version) >> 0) & 0xf)\n\n// Slot ID for library function return\n#define D3D_RETURN_PARAMETER_INDEX (-1)\n\ntypedef D3D_RESOURCE_RETURN_TYPE D3D12_RESOURCE_RETURN_TYPE;\n\ntypedef D3D_CBUFFER_TYPE D3D12_CBUFFER_TYPE;\n\n\ntypedef struct _D3D12_SIGNATURE_PARAMETER_DESC\n{\n    LPCSTR                      SemanticName;   // Name of the semantic\n    UINT                        SemanticIndex;  // Index of the semantic\n    UINT                        Register;       // Number of member variables\n    D3D_NAME                    SystemValueType;// A predefined system value, or D3D_NAME_UNDEFINED if not applicable\n    D3D_REGISTER_COMPONENT_TYPE ComponentType;  // Scalar type (e.g. uint, float, etc.)\n    BYTE                        Mask;           // Mask to indicate which components of the register\n                                                // are used (combination of D3D10_COMPONENT_MASK values)\n    BYTE                        ReadWriteMask;  // Mask to indicate whether a given component is \n                                                // never written (if this is an output signature) or\n                                                // always read (if this is an input signature).\n                                                // (combination of D3D_MASK_* values)\n    UINT                        Stream;         // Stream index\n    D3D_MIN_PRECISION           MinPrecision;   // Minimum desired interpolation precision\n} D3D12_SIGNATURE_PARAMETER_DESC;\n\ntypedef struct _D3D12_SHADER_BUFFER_DESC\n{\n    LPCSTR                  Name;           // Name of the constant buffer\n    D3D_CBUFFER_TYPE        Type;           // Indicates type of buffer content\n    UINT                    Variables;      // Number of member variables\n    UINT                    Size;           // Size of CB (in bytes)\n    UINT                    uFlags;         // Buffer description flags\n} D3D12_SHADER_BUFFER_DESC;\n\ntypedef struct _D3D12_SHADER_VARIABLE_DESC\n{\n    LPCSTR                  Name;           // Name of the variable\n    UINT                    StartOffset;    // Offset in constant buffer's backing store\n    UINT                    Size;           // Size of variable (in bytes)\n    UINT                    uFlags;         // Variable flags\n    LPVOID                  DefaultValue;   // Raw pointer to default value\n    UINT                    StartTexture;   // First texture index (or -1 if no textures used)\n    UINT                    TextureSize;    // Number of texture slots possibly used.\n    UINT                    StartSampler;   // First sampler index (or -1 if no textures used)\n    UINT                    SamplerSize;    // Number of sampler slots possibly used.\n} D3D12_SHADER_VARIABLE_DESC;\n\ntypedef struct _D3D12_SHADER_TYPE_DESC\n{\n    D3D_SHADER_VARIABLE_CLASS   Class;          // Variable class (e.g. object, matrix, etc.)\n    D3D_SHADER_VARIABLE_TYPE    Type;           // Variable type (e.g. float, sampler, etc.)\n    UINT                        Rows;           // Number of rows (for matrices, 1 for other numeric, 0 if not applicable)\n    UINT                        Columns;        // Number of columns (for vectors & matrices, 1 for other numeric, 0 if not applicable)\n    UINT                        Elements;       // Number of elements (0 if not an array)\n    UINT                        Members;        // Number of members (0 if not a structure)\n    UINT                        Offset;         // Offset from the start of structure (0 if not a structure member)\n    LPCSTR                      Name;           // Name of type, can be NULL\n} D3D12_SHADER_TYPE_DESC;\n\ntypedef D3D_TESSELLATOR_DOMAIN D3D12_TESSELLATOR_DOMAIN;\n\ntypedef D3D_TESSELLATOR_PARTITIONING D3D12_TESSELLATOR_PARTITIONING;\n\ntypedef D3D_TESSELLATOR_OUTPUT_PRIMITIVE D3D12_TESSELLATOR_OUTPUT_PRIMITIVE;\n\ntypedef struct _D3D12_SHADER_DESC\n{\n    UINT                    Version;                     // Shader version\n    LPCSTR                  Creator;                     // Creator string\n    UINT                    Flags;                       // Shader compilation/parse flags\n    \n    UINT                    ConstantBuffers;             // Number of constant buffers\n    UINT                    BoundResources;              // Number of bound resources\n    UINT                    InputParameters;             // Number of parameters in the input signature\n    UINT                    OutputParameters;            // Number of parameters in the output signature\n\n    UINT                    InstructionCount;            // Number of emitted instructions\n    UINT                    TempRegisterCount;           // Number of temporary registers used \n    UINT                    TempArrayCount;              // Number of temporary arrays used\n    UINT                    DefCount;                    // Number of constant defines \n    UINT                    DclCount;                    // Number of declarations (input + output)\n    UINT                    TextureNormalInstructions;   // Number of non-categorized texture instructions\n    UINT                    TextureLoadInstructions;     // Number of texture load instructions\n    UINT                    TextureCompInstructions;     // Number of texture comparison instructions\n    UINT                    TextureBiasInstructions;     // Number of texture bias instructions\n    UINT                    TextureGradientInstructions; // Number of texture gradient instructions\n    UINT                    FloatInstructionCount;       // Number of floating point arithmetic instructions used\n    UINT                    IntInstructionCount;         // Number of signed integer arithmetic instructions used\n    UINT                    UintInstructionCount;        // Number of unsigned integer arithmetic instructions used\n    UINT                    StaticFlowControlCount;      // Number of static flow control instructions used\n    UINT                    DynamicFlowControlCount;     // Number of dynamic flow control instructions used\n    UINT                    MacroInstructionCount;       // Number of macro instructions used\n    UINT                    ArrayInstructionCount;       // Number of array instructions used\n    UINT                    CutInstructionCount;         // Number of cut instructions used\n    UINT                    EmitInstructionCount;        // Number of emit instructions used\n    D3D_PRIMITIVE_TOPOLOGY  GSOutputTopology;            // Geometry shader output topology\n    UINT                    GSMaxOutputVertexCount;      // Geometry shader maximum output vertex count\n    D3D_PRIMITIVE           InputPrimitive;              // GS/HS input primitive\n    UINT                    PatchConstantParameters;     // Number of parameters in the patch constant signature\n    UINT                    cGSInstanceCount;            // Number of Geometry shader instances\n    UINT                    cControlPoints;              // Number of control points in the HS->DS stage\n    D3D_TESSELLATOR_OUTPUT_PRIMITIVE HSOutputPrimitive;  // Primitive output by the tessellator\n    D3D_TESSELLATOR_PARTITIONING HSPartitioning;         // Partitioning mode of the tessellator\n    D3D_TESSELLATOR_DOMAIN  TessellatorDomain;           // Domain of the tessellator (quad, tri, isoline)\n    // instruction counts\n    UINT cBarrierInstructions;                           // Number of barrier instructions in a compute shader\n    UINT cInterlockedInstructions;                       // Number of interlocked instructions\n    UINT cTextureStoreInstructions;                      // Number of texture writes\n} D3D12_SHADER_DESC;\n\ntypedef struct _D3D12_SHADER_INPUT_BIND_DESC\n{\n    LPCSTR                      Name;           // Name of the resource\n    D3D_SHADER_INPUT_TYPE       Type;           // Type of resource (e.g. texture, cbuffer, etc.)\n    UINT                        BindPoint;      // Starting bind point\n    UINT                        BindCount;      // Number of contiguous bind points (for arrays)\n\n    UINT                        uFlags;         // Input binding flags\n    D3D_RESOURCE_RETURN_TYPE    ReturnType;     // Return type (if texture)\n    D3D_SRV_DIMENSION           Dimension;      // Dimension (if texture)\n    UINT                        NumSamples;     // Number of samples (0 if not MS texture)\n    UINT                        Space;          // Register space\n    UINT uID;                                   // Range ID in the bytecode\n} D3D12_SHADER_INPUT_BIND_DESC;\n\n#define D3D_SHADER_REQUIRES_DOUBLES                                                         0x00000001\n#define D3D_SHADER_REQUIRES_EARLY_DEPTH_STENCIL                                             0x00000002\n#define D3D_SHADER_REQUIRES_UAVS_AT_EVERY_STAGE                                             0x00000004\n#define D3D_SHADER_REQUIRES_64_UAVS                                                         0x00000008\n#define D3D_SHADER_REQUIRES_MINIMUM_PRECISION                                               0x00000010\n#define D3D_SHADER_REQUIRES_11_1_DOUBLE_EXTENSIONS                                          0x00000020\n#define D3D_SHADER_REQUIRES_11_1_SHADER_EXTENSIONS                                          0x00000040\n#define D3D_SHADER_REQUIRES_LEVEL_9_COMPARISON_FILTERING                                    0x00000080\n#define D3D_SHADER_REQUIRES_TILED_RESOURCES                                                 0x00000100\n#define D3D_SHADER_REQUIRES_STENCIL_REF                                                     0x00000200\n#define D3D_SHADER_REQUIRES_INNER_COVERAGE                                                  0x00000400\n#define D3D_SHADER_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS                               0x00000800\n#define D3D_SHADER_REQUIRES_ROVS                                                            0x00001000\n#define D3D_SHADER_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER  0x00002000\n#define D3D_SHADER_REQUIRES_WAVE_OPS                                                        0x00004000\n#define D3D_SHADER_REQUIRES_INT64_OPS                                                       0x00008000\n#define D3D_SHADER_REQUIRES_VIEW_ID                                                         0x00010000\n#define D3D_SHADER_REQUIRES_BARYCENTRICS                                                    0x00020000\n#define D3D_SHADER_REQUIRES_NATIVE_16BIT_OPS                                                0x00040000\n#define D3D_SHADER_REQUIRES_SHADING_RATE                                                    0x00080000\n#define D3D_SHADER_REQUIRES_RAYTRACING_TIER_1_1                                             0x00100000\n#define D3D_SHADER_REQUIRES_SAMPLER_FEEDBACK                                                0x00200000\n#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_TYPED_RESOURCE                                  0x00400000\n#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_GROUP_SHARED                                    0x00800000\n#define D3D_SHADER_REQUIRES_DERIVATIVES_IN_MESH_AND_AMPLIFICATION_SHADERS                   0x01000000\n#define D3D_SHADER_REQUIRES_RESOURCE_DESCRIPTOR_HEAP_INDEXING                               0x02000000\n#define D3D_SHADER_REQUIRES_SAMPLER_DESCRIPTOR_HEAP_INDEXING                                0x04000000\n#define D3D_SHADER_REQUIRES_WAVE_MMA                                                        0x08000000\n#define D3D_SHADER_REQUIRES_ATOMIC_INT64_ON_DESCRIPTOR_HEAP_RESOURCE                        0x10000000\n\ntypedef struct _D3D12_LIBRARY_DESC\n{\n    LPCSTR    Creator;           // The name of the originator of the library.\n    UINT      Flags;             // Compilation flags.\n    UINT      FunctionCount;     // Number of functions exported from the library.\n} D3D12_LIBRARY_DESC;\n\ntypedef struct _D3D12_FUNCTION_DESC\n{\n    UINT                    Version;                     // Shader version\n    LPCSTR                  Creator;                     // Creator string\n    UINT                    Flags;                       // Shader compilation/parse flags\n    \n    UINT                    ConstantBuffers;             // Number of constant buffers\n    UINT                    BoundResources;              // Number of bound resources\n\n    UINT                    InstructionCount;            // Number of emitted instructions\n    UINT                    TempRegisterCount;           // Number of temporary registers used \n    UINT                    TempArrayCount;              // Number of temporary arrays used\n    UINT                    DefCount;                    // Number of constant defines \n    UINT                    DclCount;                    // Number of declarations (input + output)\n    UINT                    TextureNormalInstructions;   // Number of non-categorized texture instructions\n    UINT                    TextureLoadInstructions;     // Number of texture load instructions\n    UINT                    TextureCompInstructions;     // Number of texture comparison instructions\n    UINT                    TextureBiasInstructions;     // Number of texture bias instructions\n    UINT                    TextureGradientInstructions; // Number of texture gradient instructions\n    UINT                    FloatInstructionCount;       // Number of floating point arithmetic instructions used\n    UINT                    IntInstructionCount;         // Number of signed integer arithmetic instructions used\n    UINT                    UintInstructionCount;        // Number of unsigned integer arithmetic instructions used\n    UINT                    StaticFlowControlCount;      // Number of static flow control instructions used\n    UINT                    DynamicFlowControlCount;     // Number of dynamic flow control instructions used\n    UINT                    MacroInstructionCount;       // Number of macro instructions used\n    UINT                    ArrayInstructionCount;       // Number of array instructions used\n    UINT                    MovInstructionCount;         // Number of mov instructions used\n    UINT                    MovcInstructionCount;        // Number of movc instructions used\n    UINT                    ConversionInstructionCount;  // Number of type conversion instructions used\n    UINT                    BitwiseInstructionCount;     // Number of bitwise arithmetic instructions used\n    D3D_FEATURE_LEVEL       MinFeatureLevel;             // Min target of the function byte code\n    UINT64                  RequiredFeatureFlags;        // Required feature flags\n\n    LPCSTR                  Name;                        // Function name\n    INT                     FunctionParameterCount;      // Number of logical parameters in the function signature (not including return)\n    BOOL                    HasReturn;                   // TRUE, if function returns a value, false - it is a subroutine\n    BOOL                    Has10Level9VertexShader;     // TRUE, if there is a 10L9 VS blob\n    BOOL                    Has10Level9PixelShader;      // TRUE, if there is a 10L9 PS blob\n} D3D12_FUNCTION_DESC;\n\ntypedef struct _D3D12_PARAMETER_DESC\n{\n    LPCSTR                      Name;               // Parameter name.\n    LPCSTR                      SemanticName;       // Parameter semantic name (+index).\n    D3D_SHADER_VARIABLE_TYPE    Type;               // Element type.\n    D3D_SHADER_VARIABLE_CLASS   Class;              // Scalar/Vector/Matrix.\n    UINT                        Rows;               // Rows are for matrix parameters.\n    UINT                        Columns;            // Components or Columns in matrix.\n    D3D_INTERPOLATION_MODE      InterpolationMode;  // Interpolation mode.\n    D3D_PARAMETER_FLAGS         Flags;              // Parameter modifiers.\n\n    UINT                        FirstInRegister;    // The first input register for this parameter.\n    UINT                        FirstInComponent;   // The first input register component for this parameter.\n    UINT                        FirstOutRegister;   // The first output register for this parameter.\n    UINT                        FirstOutComponent;  // The first output register component for this parameter.\n} D3D12_PARAMETER_DESC;\n\n\n//////////////////////////////////////////////////////////////////////////////\n// Interfaces ////////////////////////////////////////////////////////////////\n//////////////////////////////////////////////////////////////////////////////\n\ntypedef interface ID3D12ShaderReflectionType ID3D12ShaderReflectionType;\ntypedef interface ID3D12ShaderReflectionType *LPD3D12SHADERREFLECTIONTYPE;\n\ntypedef interface ID3D12ShaderReflectionVariable ID3D12ShaderReflectionVariable;\ntypedef interface ID3D12ShaderReflectionVariable *LPD3D12SHADERREFLECTIONVARIABLE;\n\ntypedef interface ID3D12ShaderReflectionConstantBuffer ID3D12ShaderReflectionConstantBuffer;\ntypedef interface ID3D12ShaderReflectionConstantBuffer *LPD3D12SHADERREFLECTIONCONSTANTBUFFER;\n\ntypedef interface ID3D12ShaderReflection ID3D12ShaderReflection;\ntypedef interface ID3D12ShaderReflection *LPD3D12SHADERREFLECTION;\n\ntypedef interface ID3D12LibraryReflection ID3D12LibraryReflection;\ntypedef interface ID3D12LibraryReflection *LPD3D12LIBRARYREFLECTION;\n\ntypedef interface ID3D12FunctionReflection ID3D12FunctionReflection;\ntypedef interface ID3D12FunctionReflection *LPD3D12FUNCTIONREFLECTION;\n\ntypedef interface ID3D12FunctionParameterReflection ID3D12FunctionParameterReflection;\ntypedef interface ID3D12FunctionParameterReflection *LPD3D12FUNCTIONPARAMETERREFLECTION;\n\n\n// {E913C351-783D-48CA-A1D1-4F306284AD56}\ninterface DECLSPEC_UUID(\"E913C351-783D-48CA-A1D1-4F306284AD56\") ID3D12ShaderReflectionType;\nDEFINE_GUID(IID_ID3D12ShaderReflectionType, \n0xe913c351, 0x783d, 0x48ca, 0xa1, 0xd1, 0x4f, 0x30, 0x62, 0x84, 0xad, 0x56);\n\n#undef INTERFACE\n#define INTERFACE ID3D12ShaderReflectionType\n\nDECLARE_INTERFACE(ID3D12ShaderReflectionType)\n{\n    STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_TYPE_DESC *pDesc) PURE;\n    \n    STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByIndex)(THIS_ _In_ UINT Index) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionType*, GetMemberTypeByName)(THIS_ _In_ LPCSTR Name) PURE;\n    STDMETHOD_(LPCSTR, GetMemberTypeName)(THIS_ _In_ UINT Index) PURE;\n\n    STDMETHOD(IsEqual)(THIS_ _In_ ID3D12ShaderReflectionType* pType) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionType*, GetSubType)(THIS) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionType*, GetBaseClass)(THIS) PURE;\n    STDMETHOD_(UINT, GetNumInterfaces)(THIS) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionType*, GetInterfaceByIndex)(THIS_ _In_ UINT uIndex) PURE;\n    STDMETHOD(IsOfType)(THIS_ _In_ ID3D12ShaderReflectionType* pType) PURE;\n    STDMETHOD(ImplementsInterface)(THIS_ _In_ ID3D12ShaderReflectionType* pBase) PURE;\n};\n\n// {8337A8A6-A216-444A-B2F4-314733A73AEA}\ninterface DECLSPEC_UUID(\"8337A8A6-A216-444A-B2F4-314733A73AEA\") ID3D12ShaderReflectionVariable;\nDEFINE_GUID(IID_ID3D12ShaderReflectionVariable, \n0x8337a8a6, 0xa216, 0x444a, 0xb2, 0xf4, 0x31, 0x47, 0x33, 0xa7, 0x3a, 0xea);\n\n#undef INTERFACE\n#define INTERFACE ID3D12ShaderReflectionVariable\n\nDECLARE_INTERFACE(ID3D12ShaderReflectionVariable)\n{\n    STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_VARIABLE_DESC *pDesc) PURE;\n    \n    STDMETHOD_(ID3D12ShaderReflectionType*, GetType)(THIS) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetBuffer)(THIS) PURE;\n\n    STDMETHOD_(UINT, GetInterfaceSlot)(THIS_ _In_ UINT uArrayIndex) PURE;\n};\n\n// {C59598B4-48B3-4869-B9B1-B1618B14A8B7}\ninterface DECLSPEC_UUID(\"C59598B4-48B3-4869-B9B1-B1618B14A8B7\") ID3D12ShaderReflectionConstantBuffer;\nDEFINE_GUID(IID_ID3D12ShaderReflectionConstantBuffer, \n0xc59598b4, 0x48b3, 0x4869, 0xb9, 0xb1, 0xb1, 0x61, 0x8b, 0x14, 0xa8, 0xb7);\n\n#undef INTERFACE\n#define INTERFACE ID3D12ShaderReflectionConstantBuffer\n\nDECLARE_INTERFACE(ID3D12ShaderReflectionConstantBuffer)\n{\n    STDMETHOD(GetDesc)(THIS_ D3D12_SHADER_BUFFER_DESC *pDesc) PURE;\n    \n    STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByIndex)(THIS_ _In_ UINT Index) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE;\n};\n\n// The ID3D12ShaderReflection IID may change from SDK version to SDK version\n// if the reflection API changes.  This prevents new code with the new API\n// from working with an old binary.  Recompiling with the new header\n// will pick up the new IID.\n\n// {5A58797D-A72C-478D-8BA2-EFC6B0EFE88E}\ninterface DECLSPEC_UUID(\"5A58797D-A72C-478D-8BA2-EFC6B0EFE88E\") ID3D12ShaderReflection;\nDEFINE_GUID(IID_ID3D12ShaderReflection, \n0x5a58797d, 0xa72c, 0x478d, 0x8b, 0xa2, 0xef, 0xc6, 0xb0, 0xef, 0xe8, 0x8e);\n\n#undef INTERFACE\n#define INTERFACE ID3D12ShaderReflection\n\nDECLARE_INTERFACE_(ID3D12ShaderReflection, IUnknown)\n{\n    STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid,\n                              _Out_ LPVOID *ppv) PURE;\n    STDMETHOD_(ULONG, AddRef)(THIS) PURE;\n    STDMETHOD_(ULONG, Release)(THIS) PURE;\n\n    STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_SHADER_DESC *pDesc) PURE;\n    \n    STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByIndex)(THIS_ _In_ UINT Index) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionConstantBuffer*, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE;\n    \n    STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex,\n                                      _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE;\n    \n    STDMETHOD(GetInputParameterDesc)(THIS_ _In_ UINT ParameterIndex,\n                                     _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE;\n    STDMETHOD(GetOutputParameterDesc)(THIS_ _In_ UINT ParameterIndex,\n                                      _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE;\n    STDMETHOD(GetPatchConstantParameterDesc)(THIS_ _In_ UINT ParameterIndex,\n                                             _Out_ D3D12_SIGNATURE_PARAMETER_DESC *pDesc) PURE;\n\n    STDMETHOD_(ID3D12ShaderReflectionVariable*, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE;\n\n    STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name,\n                                            _Out_ D3D12_SHADER_INPUT_BIND_DESC *pDesc) PURE;\n\n    STDMETHOD_(UINT, GetMovInstructionCount)(THIS) PURE;\n    STDMETHOD_(UINT, GetMovcInstructionCount)(THIS) PURE;\n    STDMETHOD_(UINT, GetConversionInstructionCount)(THIS) PURE;\n    STDMETHOD_(UINT, GetBitwiseInstructionCount)(THIS) PURE;\n    \n    STDMETHOD_(D3D_PRIMITIVE, GetGSInputPrimitive)(THIS) PURE;\n    STDMETHOD_(BOOL, IsSampleFrequencyShader)(THIS) PURE;\n\n    STDMETHOD_(UINT, GetNumInterfaceSlots)(THIS) PURE;\n    STDMETHOD(GetMinFeatureLevel)(THIS_ _Out_ enum D3D_FEATURE_LEVEL* pLevel) PURE;\n\n    STDMETHOD_(UINT, GetThreadGroupSize)(THIS_\n                                         _Out_opt_ UINT* pSizeX,\n                                         _Out_opt_ UINT* pSizeY,\n                                         _Out_opt_ UINT* pSizeZ) PURE;\n\n    STDMETHOD_(UINT64, GetRequiresFlags)(THIS) PURE;\n};\n\n// {8E349D19-54DB-4A56-9DC9-119D87BDB804}\ninterface DECLSPEC_UUID(\"8E349D19-54DB-4A56-9DC9-119D87BDB804\") ID3D12LibraryReflection;\nDEFINE_GUID(IID_ID3D12LibraryReflection, \n0x8e349d19, 0x54db, 0x4a56, 0x9d, 0xc9, 0x11, 0x9d, 0x87, 0xbd, 0xb8, 0x4);\n\n#undef INTERFACE\n#define INTERFACE ID3D12LibraryReflection\n\nDECLARE_INTERFACE_(ID3D12LibraryReflection, IUnknown)\n{\n    STDMETHOD(QueryInterface)(THIS_ _In_ REFIID iid, _Out_ LPVOID * ppv) PURE;\n    STDMETHOD_(ULONG, AddRef)(THIS) PURE;\n    STDMETHOD_(ULONG, Release)(THIS) PURE;\n\n    STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_LIBRARY_DESC * pDesc) PURE;\n    \n    STDMETHOD_(ID3D12FunctionReflection *, GetFunctionByIndex)(THIS_ _In_ INT FunctionIndex) PURE;\n};\n\n// {1108795C-2772-4BA9-B2A8-D464DC7E2799}\ninterface DECLSPEC_UUID(\"1108795C-2772-4BA9-B2A8-D464DC7E2799\") ID3D12FunctionReflection;\nDEFINE_GUID(IID_ID3D12FunctionReflection, \n0x1108795c, 0x2772, 0x4ba9, 0xb2, 0xa8, 0xd4, 0x64, 0xdc, 0x7e, 0x27, 0x99);\n\n#undef INTERFACE\n#define INTERFACE ID3D12FunctionReflection\n\nDECLARE_INTERFACE(ID3D12FunctionReflection)\n{\n    STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_FUNCTION_DESC * pDesc) PURE;\n    \n    STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByIndex)(THIS_ _In_ UINT BufferIndex) PURE;\n    STDMETHOD_(ID3D12ShaderReflectionConstantBuffer *, GetConstantBufferByName)(THIS_ _In_ LPCSTR Name) PURE;\n    \n    STDMETHOD(GetResourceBindingDesc)(THIS_ _In_ UINT ResourceIndex,\n                                      _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) PURE;\n    \n    STDMETHOD_(ID3D12ShaderReflectionVariable *, GetVariableByName)(THIS_ _In_ LPCSTR Name) PURE;\n\n    STDMETHOD(GetResourceBindingDescByName)(THIS_ _In_ LPCSTR Name,\n                                            _Out_ D3D12_SHADER_INPUT_BIND_DESC * pDesc) PURE;\n\n    // Use D3D_RETURN_PARAMETER_INDEX to get description of the return value.\n    STDMETHOD_(ID3D12FunctionParameterReflection *, GetFunctionParameter)(THIS_ _In_ INT ParameterIndex) PURE;\n};\n\n// {EC25F42D-7006-4F2B-B33E-02CC3375733F}\ninterface DECLSPEC_UUID(\"EC25F42D-7006-4F2B-B33E-02CC3375733F\") ID3D12FunctionParameterReflection;\nDEFINE_GUID(IID_ID3D12FunctionParameterReflection, \n0xec25f42d, 0x7006, 0x4f2b, 0xb3, 0x3e, 0x2, 0xcc, 0x33, 0x75, 0x73, 0x3f);\n\n#undef INTERFACE\n#define INTERFACE ID3D12FunctionParameterReflection\n\nDECLARE_INTERFACE(ID3D12FunctionParameterReflection)\n{\n    STDMETHOD(GetDesc)(THIS_ _Out_ D3D12_PARAMETER_DESC * pDesc) PURE;\n};\n\n\n//////////////////////////////////////////////////////////////////////////////\n// APIs //////////////////////////////////////////////////////////////////////\n//////////////////////////////////////////////////////////////////////////////\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif //__cplusplus\n\n#ifdef __cplusplus\n}\n#endif //__cplusplus\n    \n#endif //__D3D12SHADER_H__\n\n"
  },
  {
    "path": "Source/External/dxc/inc/dxcapi.h",
    "content": "\n///////////////////////////////////////////////////////////////////////////////\n//                                                                           //\n// dxcapi.h                                                                  //\n// Copyright (C) Microsoft Corporation. All rights reserved.                 //\n// This file is distributed under the University of Illinois Open Source     //\n// License. See LICENSE.TXT for details.                                     //\n//                                                                           //\n// Provides declarations for the DirectX Compiler API entry point.           //\n//                                                                           //\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef __DXC_API__\n#define __DXC_API__\n\n#ifdef _WIN32\n#ifndef DXC_API_IMPORT\n#define DXC_API_IMPORT __declspec(dllimport)\n#endif\n#else\n#ifndef DXC_API_IMPORT\n#define DXC_API_IMPORT __attribute__ ((visibility (\"default\")))\n#endif\n#endif\n\n#ifdef _WIN32\n\n#ifndef CROSS_PLATFORM_UUIDOF\n// Warning: This macro exists in WinAdapter.h as well\n#define CROSS_PLATFORM_UUIDOF(interface, spec)                                 \\\n  struct __declspec(uuid(spec)) interface;\n#endif\n\n#else\n\n#include <dlfcn.h>\n#include \"dxc/Support/WinAdapter.h\"\n#endif\n\nstruct IMalloc;\n\nstruct IDxcIncludeHandler;\n\ntypedef HRESULT (__stdcall *DxcCreateInstanceProc)(\n    _In_ REFCLSID   rclsid,\n    _In_ REFIID     riid,\n    _Out_ LPVOID*   ppv\n);\n\ntypedef HRESULT(__stdcall *DxcCreateInstance2Proc)(\n  _In_ IMalloc    *pMalloc,\n  _In_ REFCLSID   rclsid,\n  _In_ REFIID     riid,\n  _Out_ LPVOID*   ppv\n  );\n\n/// <summary>\n/// Creates a single uninitialized object of the class associated with a specified CLSID.\n/// </summary>\n/// <param name=\"rclsid\">\n/// The CLSID associated with the data and code that will be used to create the object.\n/// </param>\n/// <param name=\"riid\">\n/// A reference to the identifier of the interface to be used to communicate\n/// with the object.\n/// </param>\n/// <param name=\"ppv\">\n/// Address of pointer variable that receives the interface pointer requested\n/// in riid. Upon successful return, *ppv contains the requested interface\n/// pointer. Upon failure, *ppv contains NULL.</param>\n/// <remarks>\n/// While this function is similar to CoCreateInstance, there is no COM involvement.\n/// </remarks>\n\nextern \"C\"\nDXC_API_IMPORT HRESULT __stdcall DxcCreateInstance(\n  _In_ REFCLSID   rclsid,\n  _In_ REFIID     riid,\n  _Out_ LPVOID*   ppv\n  );\n\nextern \"C\"\nDXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2(\n  _In_ IMalloc    *pMalloc,\n  _In_ REFCLSID   rclsid,\n  _In_ REFIID     riid,\n  _Out_ LPVOID*   ppv\n);\n\n// For convenience, equivalent definitions to CP_UTF8 and CP_UTF16.\n#define DXC_CP_UTF8 65001\n#define DXC_CP_UTF16 1200\n#define DXC_CP_UTF32 12000\n// Use DXC_CP_ACP for: Binary;  ANSI Text;  Autodetect UTF with BOM\n#define DXC_CP_ACP 0\n\n#ifdef _WIN32\n#define DXC_CP_WIDE DXC_CP_UTF16\n#else\n#define DXC_CP_WIDE DXC_CP_UTF32\n#endif\n\n// This flag indicates that the shader hash was computed taking into account source information (-Zss)\n#define DXC_HASHFLAG_INCLUDES_SOURCE  1\n\n// Hash digest type for ShaderHash\ntypedef struct DxcShaderHash {\n  UINT32 Flags; // DXC_HASHFLAG_*\n  BYTE HashDigest[16];\n} DxcShaderHash;\n\n#define DXC_FOURCC(ch0, ch1, ch2, ch3) (                     \\\n  (UINT32)(UINT8)(ch0)        | (UINT32)(UINT8)(ch1) << 8  | \\\n  (UINT32)(UINT8)(ch2) << 16  | (UINT32)(UINT8)(ch3) << 24   \\\n  )\n#define DXC_PART_PDB                      DXC_FOURCC('I', 'L', 'D', 'B')\n#define DXC_PART_PDB_NAME                 DXC_FOURCC('I', 'L', 'D', 'N')\n#define DXC_PART_PRIVATE_DATA             DXC_FOURCC('P', 'R', 'I', 'V')\n#define DXC_PART_ROOT_SIGNATURE           DXC_FOURCC('R', 'T', 'S', '0')\n#define DXC_PART_DXIL                     DXC_FOURCC('D', 'X', 'I', 'L')\n#define DXC_PART_REFLECTION_DATA          DXC_FOURCC('S', 'T', 'A', 'T')\n#define DXC_PART_SHADER_HASH              DXC_FOURCC('H', 'A', 'S', 'H')\n#define DXC_PART_INPUT_SIGNATURE          DXC_FOURCC('I', 'S', 'G', '1')\n#define DXC_PART_OUTPUT_SIGNATURE         DXC_FOURCC('O', 'S', 'G', '1')\n#define DXC_PART_PATCH_CONSTANT_SIGNATURE DXC_FOURCC('P', 'S', 'G', '1')\n\n// Some option arguments are defined here for continuity with D3DCompile interface\n#define DXC_ARG_DEBUG L\"-Zi\"\n#define DXC_ARG_SKIP_VALIDATION L\"-Vd\"\n#define DXC_ARG_SKIP_OPTIMIZATIONS L\"-Od\"\n#define DXC_ARG_PACK_MATRIX_ROW_MAJOR L\"-Zpr\"\n#define DXC_ARG_PACK_MATRIX_COLUMN_MAJOR L\"-Zpc\"\n#define DXC_ARG_AVOID_FLOW_CONTROL L\"-Gfa\"\n#define DXC_ARG_PREFER_FLOW_CONTROL L\"-Gfp\"\n#define DXC_ARG_ENABLE_STRICTNESS L\"-Ges\"\n#define DXC_ARG_ENABLE_BACKWARDS_COMPATIBILITY L\"-Gec\"\n#define DXC_ARG_IEEE_STRICTNESS L\"-Gis\"\n#define DXC_ARG_OPTIMIZATION_LEVEL0 L\"-O0\"\n#define DXC_ARG_OPTIMIZATION_LEVEL1 L\"-O1\"\n#define DXC_ARG_OPTIMIZATION_LEVEL2 L\"-O2\"\n#define DXC_ARG_OPTIMIZATION_LEVEL3 L\"-O3\"\n#define DXC_ARG_WARNINGS_ARE_ERRORS L\"-WX\"\n#define DXC_ARG_RESOURCES_MAY_ALIAS L\"-res_may_alias\"\n#define DXC_ARG_ALL_RESOURCES_BOUND L\"-all_resources_bound\"\n#define DXC_ARG_DEBUG_NAME_FOR_SOURCE L\"-Zss\"\n#define DXC_ARG_DEBUG_NAME_FOR_BINARY L\"-Zsb\"\n\n// IDxcBlob is an alias of ID3D10Blob and ID3DBlob\nCROSS_PLATFORM_UUIDOF(IDxcBlob, \"8BA5FB08-5195-40e2-AC58-0D989C3A0102\")\nstruct IDxcBlob : public IUnknown {\npublic:\n  virtual LPVOID STDMETHODCALLTYPE GetBufferPointer(void) = 0;\n  virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(void) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcBlobEncoding, \"7241d424-2646-4191-97c0-98e96e42fc68\")\nstruct IDxcBlobEncoding : public IDxcBlob {\npublic:\n  virtual HRESULT STDMETHODCALLTYPE GetEncoding(_Out_ BOOL *pKnown,\n                                                _Out_ UINT32 *pCodePage) = 0;\n};\n\n// Notes on IDxcBlobWide and IDxcBlobUtf8\n// These guarantee null-terminated text and eithre utf8 or the native wide char encoding.\n// GetBufferSize() will return the size in bytes, including null-terminator\n// GetStringLength() will return the length in characters, excluding the null-terminator\n// Name strings will use IDxcBlobWide, while other string output blobs,\n// such as errors/warnings, preprocessed HLSL, or other text will be based\n// on the -encoding option.\n\n// The API will use this interface for output name strings\nCROSS_PLATFORM_UUIDOF(IDxcBlobWide, \"A3F84EAB-0FAA-497E-A39C-EE6ED60B2D84\")\nstruct IDxcBlobWide : public IDxcBlobEncoding {\npublic:\n  virtual LPCWSTR STDMETHODCALLTYPE GetStringPointer(void) = 0;\n  virtual SIZE_T STDMETHODCALLTYPE GetStringLength(void) = 0;\n};\nCROSS_PLATFORM_UUIDOF(IDxcBlobUtf8, \"3DA636C9-BA71-4024-A301-30CBF125305B\")\nstruct IDxcBlobUtf8 : public IDxcBlobEncoding {\npublic:\n  virtual LPCSTR STDMETHODCALLTYPE GetStringPointer(void) = 0;\n  virtual SIZE_T STDMETHODCALLTYPE GetStringLength(void) = 0;\n};\n\n// Define legacy name IDxcBlobUtf16 as IDxcBlobWide for Win32\n#ifdef _WIN32\ntypedef IDxcBlobWide IDxcBlobUtf16;\n#endif\n\nCROSS_PLATFORM_UUIDOF(IDxcIncludeHandler, \"7f61fc7d-950d-467f-b3e3-3c02fb49187c\")\nstruct IDxcIncludeHandler : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE LoadSource(\n    _In_z_ LPCWSTR pFilename,                                 // Candidate filename.\n    _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource  // Resultant source object for included file, nullptr if not found.\n    ) = 0;\n};\n\n// Structure for supplying bytes or text input to Dxc APIs.\n// Use Encoding = 0 for non-text bytes, ANSI text, or unknown with BOM.\ntypedef struct DxcBuffer {\n  LPCVOID Ptr;\n  SIZE_T Size;\n  UINT Encoding;\n} DxcText;\n\nstruct DxcDefine {\n  LPCWSTR Name;\n  _Maybenull_ LPCWSTR Value;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcCompilerArgs, \"73EFFE2A-70DC-45F8-9690-EFF64C02429D\")\nstruct IDxcCompilerArgs : public IUnknown {\n  // Pass GetArguments() and GetCount() to Compile\n  virtual LPCWSTR* STDMETHODCALLTYPE GetArguments() = 0;\n  virtual UINT32 STDMETHODCALLTYPE GetCount() = 0;\n\n  // Add additional arguments or defines here, if desired.\n  virtual HRESULT STDMETHODCALLTYPE AddArguments(\n    _In_opt_count_(argCount) LPCWSTR *pArguments,       // Array of pointers to arguments to add\n    _In_ UINT32 argCount                                // Number of arguments to add\n  ) = 0;\n  virtual HRESULT STDMETHODCALLTYPE AddArgumentsUTF8(\n    _In_opt_count_(argCount)LPCSTR *pArguments,         // Array of pointers to UTF-8 arguments to add\n    _In_ UINT32 argCount                                // Number of arguments to add\n  ) = 0;\n  virtual HRESULT STDMETHODCALLTYPE AddDefines(\n      _In_count_(defineCount) const DxcDefine *pDefines, // Array of defines\n      _In_ UINT32 defineCount                            // Number of defines\n  ) = 0;\n};\n\n//////////////////////////\n// Legacy Interfaces\n/////////////////////////\n\n// NOTE: IDxcUtils replaces IDxcLibrary\nCROSS_PLATFORM_UUIDOF(IDxcLibrary, \"e5204dc7-d18c-4c3c-bdfb-851673980fe7\")\nstruct IDxcLibrary : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE SetMalloc(_In_opt_ IMalloc *pMalloc) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob(\n    _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobFromFile(\n    _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingFromPinned(\n    _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnHeapCopy(\n    _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnMalloc(\n    _In_bytecount_(size) LPCVOID pText, IMalloc *pIMalloc, UINT32 size, UINT32 codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateIncludeHandler(\n    _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateStreamFromBlobReadOnly(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n\n  // Renamed from GetBlobAsUtf16 to GetBlobAsWide\n  virtual HRESULT STDMETHODCALLTYPE GetBlobAsWide(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n\n#ifdef _WIN32\n  // Alias to GetBlobAsWide on Win32\n  inline HRESULT GetBlobAsUtf16(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) {\n    return this->GetBlobAsWide(pBlob, pBlobEncoding);\n  }\n#endif\n};\n\n// NOTE: IDxcResult replaces IDxcOperationResult\nCROSS_PLATFORM_UUIDOF(IDxcOperationResult, \"CEDB484A-D4E9-445A-B991-CA21CA157DC2\")\nstruct IDxcOperationResult : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) = 0;\n\n  // GetResult returns the main result of the operation.\n  // This corresponds to:\n  // DXC_OUT_OBJECT - Compile() with shader or library target\n  // DXC_OUT_DISASSEMBLY - Disassemble()\n  // DXC_OUT_HLSL - Compile() with -P\n  // DXC_OUT_ROOT_SIGNATURE - Compile() with rootsig_* target\n  virtual HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0;\n\n  // GetErrorBuffer Corresponds to DXC_OUT_ERRORS.\n  virtual HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **ppErrors) = 0;\n};\n\n// NOTE: IDxcCompiler3 replaces IDxcCompiler and IDxcCompiler2\nCROSS_PLATFORM_UUIDOF(IDxcCompiler, \"8c210bf3-011f-4422-8d70-6f9acb8db617\")\nstruct IDxcCompiler : public IUnknown {\n  // Compile a single entry point to the target shader model\n  virtual HRESULT STDMETHODCALLTYPE Compile(\n    _In_ IDxcBlob *pSource,                       // Source text to compile\n    _In_opt_z_ LPCWSTR pSourceName,               // Optional file name for pSource. Used in errors and include handlers.\n    _In_opt_z_ LPCWSTR pEntryPoint,               // entry point name\n    _In_z_ LPCWSTR pTargetProfile,                // shader profile to compile\n    _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments\n    _In_ UINT32 argCount,                         // Number of arguments\n    _In_count_(defineCount)\n      const DxcDefine *pDefines,                  // Array of defines\n    _In_ UINT32 defineCount,                      // Number of defines\n    _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)\n    _COM_Outptr_ IDxcOperationResult **ppResult   // Compiler output status, buffer, and errors\n  ) = 0;\n\n  // Preprocess source text\n  virtual HRESULT STDMETHODCALLTYPE Preprocess(\n    _In_ IDxcBlob *pSource,                       // Source text to preprocess\n    _In_opt_z_ LPCWSTR pSourceName,               // Optional file name for pSource. Used in errors and include handlers.\n    _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments\n    _In_ UINT32 argCount,                         // Number of arguments\n    _In_count_(defineCount)\n      const DxcDefine *pDefines,                  // Array of defines\n    _In_ UINT32 defineCount,                      // Number of defines\n    _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)\n    _COM_Outptr_ IDxcOperationResult **ppResult   // Preprocessor output status, buffer, and errors\n  ) = 0;\n\n  // Disassemble a program.\n  virtual HRESULT STDMETHODCALLTYPE Disassemble(\n    _In_ IDxcBlob *pSource,                         // Program to disassemble.\n    _COM_Outptr_ IDxcBlobEncoding **ppDisassembly   // Disassembly text.\n    ) = 0;\n};\n\n// NOTE: IDxcCompiler3 replaces IDxcCompiler and IDxcCompiler2\nCROSS_PLATFORM_UUIDOF(IDxcCompiler2, \"A005A9D9-B8BB-4594-B5C9-0E633BEC4D37\")\nstruct IDxcCompiler2 : public IDxcCompiler {\n  // Compile a single entry point to the target shader model with debug information.\n  virtual HRESULT STDMETHODCALLTYPE CompileWithDebug(\n    _In_ IDxcBlob *pSource,                       // Source text to compile\n    _In_opt_z_ LPCWSTR pSourceName,               // Optional file name for pSource. Used in errors and include handlers.\n    _In_opt_z_ LPCWSTR pEntryPoint,               // Entry point name\n    _In_z_ LPCWSTR pTargetProfile,                // Shader profile to compile\n    _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments\n    _In_ UINT32 argCount,                         // Number of arguments\n    _In_count_(defineCount)\n      const DxcDefine *pDefines,                  // Array of defines\n    _In_ UINT32 defineCount,                      // Number of defines\n    _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)\n    _COM_Outptr_ IDxcOperationResult **ppResult,  // Compiler output status, buffer, and errors\n    _Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob. (Must be CoTaskMemFree()'d!)\n    _COM_Outptr_opt_ IDxcBlob **ppDebugBlob       // Debug blob\n  ) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcLinker, \"F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6\")\nstruct IDxcLinker : public IUnknown {\npublic:\n  // Register a library with name to ref it later.\n  virtual HRESULT RegisterLibrary(\n    _In_opt_ LPCWSTR pLibName,          // Name of the library.\n    _In_ IDxcBlob *pLib                 // Library blob.\n  ) = 0;\n\n  // Links the shader and produces a shader blob that the Direct3D runtime can\n  // use.\n  virtual HRESULT STDMETHODCALLTYPE Link(\n    _In_opt_ LPCWSTR pEntryName,        // Entry point name\n    _In_ LPCWSTR pTargetProfile,        // shader profile to link\n    _In_count_(libCount)\n        const LPCWSTR *pLibNames,       // Array of library names to link\n    _In_ UINT32 libCount,               // Number of libraries to link\n    _In_opt_count_(argCount) const LPCWSTR *pArguments, // Array of pointers to arguments\n    _In_ UINT32 argCount,               // Number of arguments\n    _COM_Outptr_\n        IDxcOperationResult **ppResult  // Linker output status, buffer, and errors\n  ) = 0;\n};\n\n/////////////////////////\n// Latest interfaces. Please use these\n////////////////////////\n\n// NOTE: IDxcUtils replaces IDxcLibrary\nCROSS_PLATFORM_UUIDOF(IDxcUtils, \"4605C4CB-2019-492A-ADA4-65F20BB7D67F\")\nstruct IDxcUtils : public IUnknown {\n  // Create a sub-blob that holds a reference to the outer blob and points to its memory.\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob(\n    _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0;\n\n  // For codePage, use 0 (or DXC_CP_ACP) for raw binary or ANSI code page\n\n  // Creates a blob referencing existing memory, with no copy.\n  // User must manage the memory lifetime separately.\n  // (was: CreateBlobWithEncodingFromPinned)\n  virtual HRESULT STDMETHODCALLTYPE CreateBlobFromPinned(\n    _In_bytecount_(size) LPCVOID pData, UINT32 size, UINT32 codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n\n  // Create blob, taking ownership of memory allocated with supplied allocator.\n  // (was: CreateBlobWithEncodingOnMalloc)\n  virtual HRESULT STDMETHODCALLTYPE MoveToBlob(\n    _In_bytecount_(size) LPCVOID pData, IMalloc *pIMalloc, UINT32 size, UINT32 codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n\n  ////\n  // New blobs and copied contents are allocated with the current allocator\n\n  // Copy blob contents to memory owned by the new blob.\n  // (was: CreateBlobWithEncodingOnHeapCopy)\n  virtual HRESULT STDMETHODCALLTYPE CreateBlob(\n    _In_bytecount_(size) LPCVOID pData, UINT32 size, UINT32 codePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n\n  // (was: CreateBlobFromFile)\n  virtual HRESULT STDMETHODCALLTYPE LoadFile(\n    _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* pCodePage,\n    _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE CreateReadOnlyStreamFromBlob(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0;\n\n  // Create default file-based include handler\n  virtual HRESULT STDMETHODCALLTYPE CreateDefaultIncludeHandler(\n    _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0;\n\n  // Convert or return matching encoded text blobs\n  virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobUtf8 **pBlobEncoding) = 0;\n\n  // Renamed from GetBlobAsUtf16 to GetBlobAsWide\n  virtual HRESULT STDMETHODCALLTYPE GetBlobAsWide(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobWide **pBlobEncoding) = 0;\n\n#ifdef _WIN32\n  // Alias to GetBlobAsWide on Win32\n  inline HRESULT GetBlobAsUtf16(\n    _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobWide **pBlobEncoding) {\n    return this->GetBlobAsWide(pBlob, pBlobEncoding);\n  }\n#endif\n\n  virtual HRESULT STDMETHODCALLTYPE GetDxilContainerPart(\n    _In_ const DxcBuffer *pShader,\n    _In_ UINT32 DxcPart,\n    _Outptr_result_nullonfailure_ void **ppPartData,\n    _Out_ UINT32 *pPartSizeInBytes) = 0;\n\n  // Create reflection interface from serialized Dxil container, or DXC_PART_REFLECTION_DATA.\n  // TBD: Require part header for RDAT?  (leaning towards yes)\n  virtual HRESULT STDMETHODCALLTYPE CreateReflection(\n    _In_ const DxcBuffer *pData, REFIID iid, void **ppvReflection) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE BuildArguments(\n    _In_opt_z_ LPCWSTR pSourceName,               // Optional file name for pSource. Used in errors and include handlers.\n    _In_opt_z_ LPCWSTR pEntryPoint,               // Entry point name. (-E)\n    _In_z_ LPCWSTR pTargetProfile,                // Shader profile to compile. (-T)\n    _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments\n    _In_ UINT32 argCount,                         // Number of arguments\n    _In_count_(defineCount)\n      const DxcDefine *pDefines,                  // Array of defines\n    _In_ UINT32 defineCount,                      // Number of defines\n    _COM_Outptr_ IDxcCompilerArgs **ppArgs        // Arguments you can use with Compile() method\n  ) = 0;\n\n  // Takes the shader PDB and returns the hash and the container inside it\n  virtual HRESULT STDMETHODCALLTYPE GetPDBContents(\n    _In_ IDxcBlob *pPDBBlob, _COM_Outptr_ IDxcBlob **ppHash, _COM_Outptr_ IDxcBlob **ppContainer) = 0;\n};\n\n// For use with IDxcResult::[Has|Get]Output dxcOutKind argument\n// Note: text outputs returned from version 2 APIs are UTF-8 or UTF-16 based on -encoding option\ntypedef enum DXC_OUT_KIND {\n  DXC_OUT_NONE = 0,\n  DXC_OUT_OBJECT = 1,         // IDxcBlob - Shader or library object\n  DXC_OUT_ERRORS = 2,         // IDxcBlobUtf8 or IDxcBlobWide\n  DXC_OUT_PDB = 3,            // IDxcBlob\n  DXC_OUT_SHADER_HASH = 4,    // IDxcBlob - DxcShaderHash of shader or shader with source info (-Zsb/-Zss)\n  DXC_OUT_DISASSEMBLY = 5,    // IDxcBlobUtf8 or IDxcBlobWide - from Disassemble\n  DXC_OUT_HLSL = 6,           // IDxcBlobUtf8 or IDxcBlobWide - from Preprocessor or Rewriter\n  DXC_OUT_TEXT = 7,           // IDxcBlobUtf8 or IDxcBlobWide - other text, such as -ast-dump or -Odump\n  DXC_OUT_REFLECTION = 8,     // IDxcBlob - RDAT part with reflection data\n  DXC_OUT_ROOT_SIGNATURE = 9, // IDxcBlob - Serialized root signature output\n  DXC_OUT_EXTRA_OUTPUTS  = 10,// IDxcExtraResults - Extra outputs\n  DXC_OUT_REMARKS = 11,       // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout\n  DXC_OUT_TIME_REPORT = 12,   // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout\n  DXC_OUT_TIME_TRACE = 13,   // IDxcBlobUtf8 or IDxcBlobWide - text directed at stdout\n\n  DXC_OUT_LAST = DXC_OUT_TIME_TRACE, // Last value for a counter\n\n  DXC_OUT_NUM_ENUMS,\n  DXC_OUT_FORCE_DWORD = 0xFFFFFFFF\n} DXC_OUT_KIND;\n\nstatic_assert(DXC_OUT_NUM_ENUMS == DXC_OUT_LAST + 1,\n              \"DXC_OUT_* Enum added and last value not updated.\");\n\nCROSS_PLATFORM_UUIDOF(IDxcResult, \"58346CDA-DDE7-4497-9461-6F87AF5E0659\")\nstruct IDxcResult : public IDxcOperationResult {\n  virtual BOOL STDMETHODCALLTYPE HasOutput(_In_ DXC_OUT_KIND dxcOutKind) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ DXC_OUT_KIND dxcOutKind,\n    _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,\n    _COM_Outptr_ IDxcBlobWide **ppOutputName) = 0;\n\n  virtual UINT32 GetNumOutputs() = 0;\n  virtual DXC_OUT_KIND GetOutputByIndex(UINT32 Index) = 0;\n  virtual DXC_OUT_KIND PrimaryOutput() = 0;\n};\n\n// Special names for extra output that should get written to specific streams\n#define DXC_EXTRA_OUTPUT_NAME_STDOUT L\"*stdout*\"\n#define DXC_EXTRA_OUTPUT_NAME_STDERR L\"*stderr*\"\n\nCROSS_PLATFORM_UUIDOF(IDxcExtraOutputs, \"319b37a2-a5c2-494a-a5de-4801b2faf989\")\nstruct IDxcExtraOutputs : public IUnknown {\n\n  virtual UINT32 STDMETHODCALLTYPE GetOutputCount() = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ UINT32 uIndex,\n    _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,\n    _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppOutputType,\n    _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppOutputName) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcCompiler3, \"228B4687-5A6A-4730-900C-9702B2203F54\")\nstruct IDxcCompiler3 : public IUnknown {\n  // Compile a single entry point to the target shader model,\n  // Compile a library to a library target (-T lib_*),\n  // Compile a root signature (-T rootsig_*), or\n  // Preprocess HLSL source (-P)\n  virtual HRESULT STDMETHODCALLTYPE Compile(\n    _In_ const DxcBuffer *pSource,                // Source text to compile\n    _In_opt_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments\n    _In_ UINT32 argCount,                         // Number of arguments\n    _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)\n    _In_ REFIID riid, _Out_ LPVOID *ppResult      // IDxcResult: status, buffer, and errors\n  ) = 0;\n\n  // Disassemble a program.\n  virtual HRESULT STDMETHODCALLTYPE Disassemble(\n    _In_ const DxcBuffer *pObject,                // Program to disassemble: dxil container or bitcode.\n    _In_ REFIID riid, _Out_ LPVOID *ppResult      // IDxcResult: status, disassembly text, and errors\n    ) = 0;\n};\n\nstatic const UINT32 DxcValidatorFlags_Default = 0;\nstatic const UINT32 DxcValidatorFlags_InPlaceEdit = 1;  // Validator is allowed to update shader blob in-place.\nstatic const UINT32 DxcValidatorFlags_RootSignatureOnly = 2;\nstatic const UINT32 DxcValidatorFlags_ModuleOnly = 4;\nstatic const UINT32 DxcValidatorFlags_ValidMask = 0x7;\n\nCROSS_PLATFORM_UUIDOF(IDxcValidator, \"A6E82BD2-1FD7-4826-9811-2857E797F49A\")\nstruct IDxcValidator : public IUnknown {\n  // Validate a shader.\n  virtual HRESULT STDMETHODCALLTYPE Validate(\n    _In_ IDxcBlob *pShader,                       // Shader to validate.\n    _In_ UINT32 Flags,                            // Validation flags.\n    _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors\n    ) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcValidator2, \"458e1fd1-b1b2-4750-a6e1-9c10f03bed92\")\nstruct IDxcValidator2 : public IDxcValidator {\n  // Validate a shader.\n  virtual HRESULT STDMETHODCALLTYPE ValidateWithDebug(\n    _In_ IDxcBlob *pShader,                       // Shader to validate.\n    _In_ UINT32 Flags,                            // Validation flags.\n    _In_opt_ DxcBuffer *pOptDebugBitcode,         // Optional debug module bitcode to provide line numbers\n    _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors\n    ) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcContainerBuilder, \"334b1f50-2292-4b35-99a1-25588d8c17fe\")\nstruct IDxcContainerBuilder : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pDxilContainerHeader) = 0;                // Loads DxilContainer to the builder\n  virtual HRESULT STDMETHODCALLTYPE AddPart(_In_ UINT32 fourCC, _In_ IDxcBlob *pSource) = 0;      // Part to add to the container\n  virtual HRESULT STDMETHODCALLTYPE RemovePart(_In_ UINT32 fourCC) = 0;                           // Remove the part with fourCC\n  virtual HRESULT STDMETHODCALLTYPE SerializeContainer(_Out_ IDxcOperationResult **ppResult) = 0; // Builds a container of the given container builder state\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcAssembler, \"091f7a26-1c1f-4948-904b-e6e3a8a771d5\")\nstruct IDxcAssembler : public IUnknown {\n  // Assemble dxil in ll or llvm bitcode to DXIL container.\n  virtual HRESULT STDMETHODCALLTYPE AssembleToContainer(\n    _In_ IDxcBlob *pShader,                       // Shader to assemble.\n    _COM_Outptr_ IDxcOperationResult **ppResult   // Assembly output status, buffer, and errors\n    ) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcContainerReflection, \"d2c21b26-8350-4bdc-976a-331ce6f4c54c\")\nstruct IDxcContainerReflection : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pContainer) = 0; // Container to load.\n  virtual HRESULT STDMETHODCALLTYPE GetPartCount(_Out_ UINT32 *pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetPartKind(UINT32 idx, _Out_ UINT32 *pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcOptimizerPass, \"AE2CD79F-CC22-453F-9B6B-B124E7A5204C\")\nstruct IDxcOptimizerPass : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE GetOptionName(_COM_Outptr_ LPWSTR *ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDescription(_COM_Outptr_ LPWSTR *ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetOptionArgCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetOptionArgName(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetOptionArgDescription(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcOptimizer, \"25740E2E-9CBA-401B-9119-4FB42F39F270\")\nstruct IDxcOptimizer : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE GetAvailablePassCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetAvailablePass(UINT32 index, _COM_Outptr_ IDxcOptimizerPass** ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE RunOptimizer(IDxcBlob *pBlob,\n    _In_count_(optionCount) LPCWSTR *ppOptions, UINT32 optionCount,\n    _COM_Outptr_ IDxcBlob **pOutputModule,\n    _COM_Outptr_opt_ IDxcBlobEncoding **ppOutputText) = 0;\n};\n\nstatic const UINT32 DxcVersionInfoFlags_None = 0;\nstatic const UINT32 DxcVersionInfoFlags_Debug = 1; // Matches VS_FF_DEBUG\nstatic const UINT32 DxcVersionInfoFlags_Internal = 2; // Internal Validator (non-signing)\n\nCROSS_PLATFORM_UUIDOF(IDxcVersionInfo, \"b04f5b50-2059-4f12-a8ff-a1e0cde1cc7e\")\nstruct IDxcVersionInfo : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcVersionInfo2, \"fb6904c4-42f0-4b62-9c46-983af7da7c83\")\nstruct IDxcVersionInfo2 : public IDxcVersionInfo {\n  virtual HRESULT STDMETHODCALLTYPE GetCommitInfo(\n    _Out_ UINT32 *pCommitCount,           // The total number commits.\n    _Outptr_result_z_ char **pCommitHash  // The SHA of the latest commit. (Must be CoTaskMemFree()'d!)\n  ) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcVersionInfo3, \"5e13e843-9d25-473c-9ad2-03b2d0b44b1e\")\nstruct IDxcVersionInfo3 : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE GetCustomVersionString(\n    _Outptr_result_z_ char **pVersionString // Custom version string for compiler. (Must be CoTaskMemFree()'d!)\n  ) = 0;\n};\n\nstruct DxcArgPair {\n  const WCHAR *pName;\n  const WCHAR *pValue;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcPdbUtils, \"E6C9647E-9D6A-4C3B-B94C-524B5A6C343D\")\nstruct IDxcPdbUtils : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetSourceCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSource(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobEncoding **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSourceName(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetFlagCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFlag(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetArgCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetArg(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetArgPairCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetArgPair(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pName, _Outptr_result_z_ BSTR *pValue) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetDefineCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDefine(_In_ UINT32 uIndex, _Outptr_result_z_ BSTR *pResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetTargetProfile(_Outptr_result_z_ BSTR *pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetEntryPoint(_Outptr_result_z_ BSTR *pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetMainFileName(_Outptr_result_z_ BSTR *pResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetHash(_COM_Outptr_ IDxcBlob **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetName(_Outptr_result_z_ BSTR *pResult) = 0;\n\n  virtual BOOL STDMETHODCALLTYPE IsFullPDB() = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFullPDB(_COM_Outptr_ IDxcBlob **ppFullPDB) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetVersionInfo(_COM_Outptr_ IDxcVersionInfo **ppVersionInfo) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE SetCompiler(_In_ IDxcCompiler3 *pCompiler) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CompileForFullPDB(_COM_Outptr_ IDxcResult **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE OverrideArgs(_In_ DxcArgPair *pArgPairs, UINT32 uNumArgPairs) = 0;\n  virtual HRESULT STDMETHODCALLTYPE OverrideRootSignature(_In_ const WCHAR *pRootSignature) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcPdbUtils2, \"4315D938-F369-4F93-95A2-252017CC3807\")\nstruct IDxcPdbUtils2 : public IUnknown {\n  virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pPdbOrDxil) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetSourceCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSource(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobEncoding **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSourceName(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetLibraryPDBCount(UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLibraryPDB(_In_ UINT32 uIndex, _COM_Outptr_ IDxcPdbUtils2 **ppOutPdbUtils, _COM_Outptr_opt_result_maybenull_ IDxcBlobWide **ppLibraryName) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetFlagCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFlag(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetArgCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetArg(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetArgPairCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetArgPair(_In_ UINT32 uIndex, _COM_Outptr_result_maybenull_ IDxcBlobWide **ppName, _COM_Outptr_result_maybenull_ IDxcBlobWide **ppValue) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetDefineCount(_Out_ UINT32 *pCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDefine(_In_ UINT32 uIndex, _COM_Outptr_ IDxcBlobWide **ppResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetTargetProfile(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetEntryPoint(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetMainFileName(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetHash(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetName(_COM_Outptr_result_maybenull_ IDxcBlobWide **ppResult) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetVersionInfo(_COM_Outptr_result_maybenull_ IDxcVersionInfo **ppVersionInfo) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetCustomToolchainID(_Out_ UINT32 *pID) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCustomToolchainData(_COM_Outptr_result_maybenull_ IDxcBlob **ppBlob) = 0;\n\n  virtual HRESULT STDMETHODCALLTYPE GetWholeDxil(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) = 0;\n\n  virtual BOOL STDMETHODCALLTYPE IsFullPDB() = 0;\n  virtual BOOL STDMETHODCALLTYPE IsPDBRef() = 0;\n};\n\n// Note: __declspec(selectany) requires 'extern'\n// On Linux __declspec(selectany) is removed and using 'extern' results in link error.\n#ifdef _MSC_VER\n#define CLSID_SCOPE __declspec(selectany) extern\n#else\n#define CLSID_SCOPE\n#endif\n\nCLSID_SCOPE const CLSID CLSID_DxcCompiler = {\n    0x73e22d93,\n    0xe6ce,\n    0x47f3,\n    {0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0}};\n\n// {EF6A8087-B0EA-4D56-9E45-D07E1A8B7806}\nCLSID_SCOPE const GUID CLSID_DxcLinker = {\n    0xef6a8087,\n    0xb0ea,\n    0x4d56,\n    {0x9e, 0x45, 0xd0, 0x7e, 0x1a, 0x8b, 0x78, 0x6}};\n\n// {CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F}\nCLSID_SCOPE const CLSID CLSID_DxcDiaDataSource = {\n    0xcd1f6b73,\n    0x2ab0,\n    0x484d,\n    {0x8e, 0xdc, 0xeb, 0xe7, 0xa4, 0x3c, 0xa0, 0x9f}};\n\n// {3E56AE82-224D-470F-A1A1-FE3016EE9F9D}\nCLSID_SCOPE const CLSID CLSID_DxcCompilerArgs = {\n    0x3e56ae82,\n    0x224d,\n    0x470f,\n    {0xa1, 0xa1, 0xfe, 0x30, 0x16, 0xee, 0x9f, 0x9d}};\n\n// {6245D6AF-66E0-48FD-80B4-4D271796748C}\nCLSID_SCOPE const GUID CLSID_DxcLibrary = {\n    0x6245d6af,\n    0x66e0,\n    0x48fd,\n    {0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c}};\n\nCLSID_SCOPE const GUID CLSID_DxcUtils = CLSID_DxcLibrary;\n\n// {8CA3E215-F728-4CF3-8CDD-88AF917587A1}\nCLSID_SCOPE const GUID CLSID_DxcValidator = {\n    0x8ca3e215,\n    0xf728,\n    0x4cf3,\n    {0x8c, 0xdd, 0x88, 0xaf, 0x91, 0x75, 0x87, 0xa1}};\n\n// {D728DB68-F903-4F80-94CD-DCCF76EC7151}\nCLSID_SCOPE const GUID CLSID_DxcAssembler = {\n    0xd728db68,\n    0xf903,\n    0x4f80,\n    {0x94, 0xcd, 0xdc, 0xcf, 0x76, 0xec, 0x71, 0x51}};\n\n// {b9f54489-55b8-400c-ba3a-1675e4728b91}\nCLSID_SCOPE const GUID CLSID_DxcContainerReflection = {\n    0xb9f54489,\n    0x55b8,\n    0x400c,\n    {0xba, 0x3a, 0x16, 0x75, 0xe4, 0x72, 0x8b, 0x91}};\n\n// {AE2CD79F-CC22-453F-9B6B-B124E7A5204C}\nCLSID_SCOPE const GUID CLSID_DxcOptimizer = {\n    0xae2cd79f,\n    0xcc22,\n    0x453f,\n    {0x9b, 0x6b, 0xb1, 0x24, 0xe7, 0xa5, 0x20, 0x4c}};\n\n// {94134294-411f-4574-b4d0-8741e25240d2}\nCLSID_SCOPE const GUID CLSID_DxcContainerBuilder = {\n    0x94134294,\n    0x411f,\n    0x4574,\n    {0xb4, 0xd0, 0x87, 0x41, 0xe2, 0x52, 0x40, 0xd2}};\n\n// {54621dfb-f2ce-457e-ae8c-ec355faeec7c}\nCLSID_SCOPE const GUID CLSID_DxcPdbUtils = {\n    0x54621dfb,\n    0xf2ce,\n    0x457e,\n    {0xae, 0x8c, 0xec, 0x35, 0x5f, 0xae, 0xec, 0x7c}};\n\n#endif\n"
  },
  {
    "path": "Source/External/dxc/inc/dxcerrors.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n//                                                                           //\n// dxcerror.h                                                                //\n// Copyright (C) Microsoft Corporation. All rights reserved.                 //\n// This file is distributed under the University of Illinois Open Source     //\n// License. See LICENSE.TXT for details.                                     //\n//                                                                           //\n// Provides definition of error codes.                                        //\n//                                                                           //\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef __DXC_ERRORS__\n#define __DXC_ERRORS__\n\n#ifndef FACILITY_GRAPHICS\n#define FACILITY_GRAPHICS 36\n#endif\n\n#define DXC_EXCEPTION_CODE(name, status)                                 \\\n    static constexpr DWORD EXCEPTION_##name =                 \\\n    (0xc0000000u | (FACILITY_GRAPHICS << 16) | (0xff00u | (status & 0xffu)));\n\nDXC_EXCEPTION_CODE(LOAD_LIBRARY_FAILED, 0x00u)\nDXC_EXCEPTION_CODE(NO_HMODULE,          0x01u)\nDXC_EXCEPTION_CODE(GET_PROC_FAILED,     0x02u)\n\n#undef DXC_EXCEPTION_CODE\n\n#endif\n"
  },
  {
    "path": "Source/External/dxc/inc/dxcisense.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n//                                                                           //\n// dxcisense.h                                                               //\n// Copyright (C) Microsoft Corporation. All rights reserved.                 //\n// This file is distributed under the University of Illinois Open Source     //\n// License. See LICENSE.TXT for details.                                     //\n//                                                                           //\n// Provides declarations for the DirectX Compiler IntelliSense component.    //\n//                                                                           //\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef __DXC_ISENSE__\n#define __DXC_ISENSE__\n\n#include \"dxcapi.h\"\n#ifndef _WIN32\n#include \"Support/WinAdapter.h\"\n#endif\n\ntypedef enum DxcGlobalOptions\n{\n  DxcGlobalOpt_None = 0x0,\n  DxcGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1,\n  DxcGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2,\n  DxcGlobalOpt_ThreadBackgroundPriorityForAll =\n    DxcGlobalOpt_ThreadBackgroundPriorityForIndexing | DxcGlobalOpt_ThreadBackgroundPriorityForEditing\n} DxcGlobalOptions;\n\ntypedef enum DxcTokenKind\n{\n  DxcTokenKind_Punctuation = 0, // A token that contains some kind of punctuation.\n  DxcTokenKind_Keyword = 1,     // A language keyword.\n  DxcTokenKind_Identifier = 2,  // An identifier (that is not a keyword).\n  DxcTokenKind_Literal = 3,     // A numeric, string, or character literal.\n  DxcTokenKind_Comment = 4,     // A comment.\n  DxcTokenKind_Unknown = 5,     // An unknown token (possibly known to a future version).\n  DxcTokenKind_BuiltInType = 6, // A built-in type like int, void or float3.\n} DxcTokenKind;\n\ntypedef enum DxcTypeKind\n{\n  DxcTypeKind_Invalid = 0, // Reprents an invalid type (e.g., where no type is available).\n  DxcTypeKind_Unexposed = 1, // A type whose specific kind is not exposed via this interface.\n  // Builtin types\n  DxcTypeKind_Void = 2,\n  DxcTypeKind_Bool = 3,\n  DxcTypeKind_Char_U = 4,\n  DxcTypeKind_UChar = 5,\n  DxcTypeKind_Char16 = 6,\n  DxcTypeKind_Char32 = 7,\n  DxcTypeKind_UShort = 8,\n  DxcTypeKind_UInt = 9,\n  DxcTypeKind_ULong = 10,\n  DxcTypeKind_ULongLong = 11,\n  DxcTypeKind_UInt128 = 12,\n  DxcTypeKind_Char_S = 13,\n  DxcTypeKind_SChar = 14,\n  DxcTypeKind_WChar = 15,\n  DxcTypeKind_Short = 16,\n  DxcTypeKind_Int = 17,\n  DxcTypeKind_Long = 18,\n  DxcTypeKind_LongLong = 19,\n  DxcTypeKind_Int128 = 20,\n  DxcTypeKind_Float = 21,\n  DxcTypeKind_Double = 22,\n  DxcTypeKind_LongDouble = 23,\n  DxcTypeKind_NullPtr = 24,\n  DxcTypeKind_Overload = 25,\n  DxcTypeKind_Dependent = 26,\n  DxcTypeKind_ObjCId = 27,\n  DxcTypeKind_ObjCClass = 28,\n  DxcTypeKind_ObjCSel = 29,\n  DxcTypeKind_FirstBuiltin = DxcTypeKind_Void,\n  DxcTypeKind_LastBuiltin = DxcTypeKind_ObjCSel,\n\n  DxcTypeKind_Complex = 100,\n  DxcTypeKind_Pointer = 101,\n  DxcTypeKind_BlockPointer = 102,\n  DxcTypeKind_LValueReference = 103,\n  DxcTypeKind_RValueReference = 104,\n  DxcTypeKind_Record = 105,\n  DxcTypeKind_Enum = 106,\n  DxcTypeKind_Typedef = 107,\n  DxcTypeKind_ObjCInterface = 108,\n  DxcTypeKind_ObjCObjectPointer = 109,\n  DxcTypeKind_FunctionNoProto = 110,\n  DxcTypeKind_FunctionProto = 111,\n  DxcTypeKind_ConstantArray = 112,\n  DxcTypeKind_Vector = 113,\n  DxcTypeKind_IncompleteArray = 114,\n  DxcTypeKind_VariableArray = 115,\n  DxcTypeKind_DependentSizedArray = 116,\n  DxcTypeKind_MemberPointer = 117\n} DxcTypeKind;\n\n// Describes the severity of a particular diagnostic.\ntypedef enum DxcDiagnosticSeverity\n{\n  // A diagnostic that has been suppressed, e.g., by a command-line option.\n  DxcDiagnostic_Ignored = 0,\n\n  // This diagnostic is a note that should be attached to the previous (non-note) diagnostic.\n  DxcDiagnostic_Note = 1,\n\n  // This diagnostic indicates suspicious code that may not be wrong.\n  DxcDiagnostic_Warning = 2,\n\n  // This diagnostic indicates that the code is ill-formed.\n  DxcDiagnostic_Error = 3,\n\n  // This diagnostic indicates that the code is ill-formed such that future\n  // parser rec unlikely to produce useful results.\n  DxcDiagnostic_Fatal = 4\n\n} DxcDiagnosticSeverity;\n\n// Options to control the display of diagnostics.\ntypedef enum DxcDiagnosticDisplayOptions\n{\n  // Display the source-location information where the diagnostic was located.\n  DxcDiagnostic_DisplaySourceLocation = 0x01,\n\n  // If displaying the source-location information of the diagnostic,\n  // also include the column number.\n  DxcDiagnostic_DisplayColumn = 0x02,\n\n  // If displaying the source-location information of the diagnostic,\n  // also include information about source ranges in a machine-parsable format.\n  DxcDiagnostic_DisplaySourceRanges = 0x04,\n\n  // Display the option name associated with this diagnostic, if any.\n  DxcDiagnostic_DisplayOption = 0x08,\n\n  // Display the category number associated with this diagnostic, if any.\n  DxcDiagnostic_DisplayCategoryId = 0x10,\n\n  // Display the category name associated with this diagnostic, if any.\n  DxcDiagnostic_DisplayCategoryName = 0x20,\n\n  // Display the severity of the diagnostic message.\n  DxcDiagnostic_DisplaySeverity = 0x200\n} DxcDiagnosticDisplayOptions;\n\ntypedef enum DxcTranslationUnitFlags\n{\n  // Used to indicate that no special translation-unit options are needed.\n  DxcTranslationUnitFlags_None = 0x0,\n\n  // Used to indicate that the parser should construct a \"detailed\"\n  // preprocessing record, including all macro definitions and instantiations.\n  DxcTranslationUnitFlags_DetailedPreprocessingRecord = 0x01,\n\n  // Used to indicate that the translation unit is incomplete.\n  DxcTranslationUnitFlags_Incomplete = 0x02,\n\n  // Used to indicate that the translation unit should be built with an\n  // implicit precompiled header for the preamble.\n  DxcTranslationUnitFlags_PrecompiledPreamble = 0x04,\n\n  // Used to indicate that the translation unit should cache some\n  // code-completion results with each reparse of the source file.\n  DxcTranslationUnitFlags_CacheCompletionResults = 0x08,\n\n  // Used to indicate that the translation unit will be serialized with\n  // SaveTranslationUnit.\n  DxcTranslationUnitFlags_ForSerialization = 0x10,\n\n  // DEPRECATED\n  DxcTranslationUnitFlags_CXXChainedPCH = 0x20,\n\n  // Used to indicate that function/method bodies should be skipped while parsing.\n  DxcTranslationUnitFlags_SkipFunctionBodies = 0x40,\n\n  // Used to indicate that brief documentation comments should be\n  // included into the set of code completions returned from this translation\n  // unit.\n  DxcTranslationUnitFlags_IncludeBriefCommentsInCodeCompletion = 0x80,\n\n  // Used to indicate that compilation should occur on the caller's thread.\n  DxcTranslationUnitFlags_UseCallerThread = 0x800\n} DxcTranslationUnitFlags;\n\ntypedef enum DxcCursorFormatting\n{\n  DxcCursorFormatting_Default = 0x0,             // Default rules, language-insensitive formatting.\n  DxcCursorFormatting_UseLanguageOptions = 0x1,  // Language-sensitive formatting.\n  DxcCursorFormatting_SuppressSpecifiers = 0x2,  // Supresses type specifiers.\n  DxcCursorFormatting_SuppressTagKeyword = 0x4,  // Suppressed tag keyword (eg, 'class').\n  DxcCursorFormatting_IncludeNamespaceKeyword = 0x8,  // Include namespace keyword.\n} DxcCursorFormatting;\n\nenum DxcCursorKind {\n  /* Declarations */\n  DxcCursor_UnexposedDecl = 1, // A declaration whose specific kind is not exposed via this interface.\n  DxcCursor_StructDecl = 2, // A C or C++ struct.\n  DxcCursor_UnionDecl = 3, // A C or C++ union.\n  DxcCursor_ClassDecl = 4, // A C++ class.\n  DxcCursor_EnumDecl = 5, // An enumeration.\n  DxcCursor_FieldDecl = 6, // A field (in C) or non-static data member (in C++) in a struct, union, or C++ class.\n  DxcCursor_EnumConstantDecl = 7, // An enumerator constant.\n  DxcCursor_FunctionDecl = 8, // A function.\n  DxcCursor_VarDecl = 9, // A variable.\n  DxcCursor_ParmDecl = 10, // A function or method parameter.\n  DxcCursor_ObjCInterfaceDecl = 11, // An Objective-C interface.\n  DxcCursor_ObjCCategoryDecl = 12, // An Objective-C interface for a category.\n  DxcCursor_ObjCProtocolDecl = 13, // An Objective-C protocol declaration.\n  DxcCursor_ObjCPropertyDecl = 14, // An Objective-C property declaration.\n  DxcCursor_ObjCIvarDecl = 15, // An Objective-C instance variable.\n  DxcCursor_ObjCInstanceMethodDecl = 16, // An Objective-C instance method.\n  DxcCursor_ObjCClassMethodDecl = 17, // An Objective-C class method.\n  DxcCursor_ObjCImplementationDecl = 18, // An Objective-C \\@implementation.\n  DxcCursor_ObjCCategoryImplDecl = 19, // An Objective-C \\@implementation for a category.\n  DxcCursor_TypedefDecl = 20, // A typedef\n  DxcCursor_CXXMethod = 21, // A C++ class method.\n  DxcCursor_Namespace = 22, // A C++ namespace.\n  DxcCursor_LinkageSpec = 23, // A linkage specification, e.g. 'extern \"C\"'.\n  DxcCursor_Constructor = 24, // A C++ constructor.\n  DxcCursor_Destructor = 25, // A C++ destructor.\n  DxcCursor_ConversionFunction = 26, // A C++ conversion function.\n  DxcCursor_TemplateTypeParameter = 27, // A C++ template type parameter.\n  DxcCursor_NonTypeTemplateParameter = 28, // A C++ non-type template parameter.\n  DxcCursor_TemplateTemplateParameter = 29, // A C++ template template parameter.\n  DxcCursor_FunctionTemplate = 30, // A C++ function template.\n  DxcCursor_ClassTemplate = 31, // A C++ class template.\n  DxcCursor_ClassTemplatePartialSpecialization = 32, // A C++ class template partial specialization.\n  DxcCursor_NamespaceAlias = 33, // A C++ namespace alias declaration.\n  DxcCursor_UsingDirective = 34, // A C++ using directive.\n  DxcCursor_UsingDeclaration = 35, // A C++ using declaration.\n  DxcCursor_TypeAliasDecl = 36, // A C++ alias declaration\n  DxcCursor_ObjCSynthesizeDecl = 37, // An Objective-C \\@synthesize definition.\n  DxcCursor_ObjCDynamicDecl = 38, // An Objective-C \\@dynamic definition.\n  DxcCursor_CXXAccessSpecifier = 39, // An access specifier.\n\n  DxcCursor_FirstDecl = DxcCursor_UnexposedDecl,\n  DxcCursor_LastDecl = DxcCursor_CXXAccessSpecifier,\n\n  /* References */\n  DxcCursor_FirstRef = 40, /* Decl references */\n  DxcCursor_ObjCSuperClassRef = 40,\n  DxcCursor_ObjCProtocolRef = 41,\n  DxcCursor_ObjCClassRef = 42,\n  /**\n  * \\brief A reference to a type declaration.\n  *\n  * A type reference occurs anywhere where a type is named but not\n  * declared. For example, given:\n  *\n  * \\code\n  * typedef unsigned size_type;\n  * size_type size;\n  * \\endcode\n  *\n  * The typedef is a declaration of size_type (DxcCursor_TypedefDecl),\n  * while the type of the variable \"size\" is referenced. The cursor\n  * referenced by the type of size is the typedef for size_type.\n  */\n  DxcCursor_TypeRef = 43, // A reference to a type declaration.\n  DxcCursor_CXXBaseSpecifier = 44,\n  DxcCursor_TemplateRef = 45, // A reference to a class template, function template, template template parameter, or class template partial specialization.\n  DxcCursor_NamespaceRef = 46, // A reference to a namespace or namespace alias.\n  DxcCursor_MemberRef = 47, // A reference to a member of a struct, union, or class that occurs in some non-expression context, e.g., a designated initializer.\n  /**\n  * \\brief A reference to a labeled statement.\n  *\n  * This cursor kind is used to describe the jump to \"start_over\" in the\n  * goto statement in the following example:\n  *\n  * \\code\n  *   start_over:\n  *     ++counter;\n  *\n  *     goto start_over;\n  * \\endcode\n  *\n  * A label reference cursor refers to a label statement.\n  */\n  DxcCursor_LabelRef = 48, // A reference to a labeled statement.\n\n  // A reference to a set of overloaded functions or function templates\n  // that has not yet been resolved to a specific function or function template.\n  //\n  // An overloaded declaration reference cursor occurs in C++ templates where\n  // a dependent name refers to a function.\n  DxcCursor_OverloadedDeclRef = 49,\n  DxcCursor_VariableRef = 50, // A reference to a variable that occurs in some non-expression context, e.g., a C++ lambda capture list.\n\n  DxcCursor_LastRef = DxcCursor_VariableRef,\n\n  /* Error conditions */\n  DxcCursor_FirstInvalid = 70,\n  DxcCursor_InvalidFile = 70,\n  DxcCursor_NoDeclFound = 71,\n  DxcCursor_NotImplemented = 72,\n  DxcCursor_InvalidCode = 73,\n  DxcCursor_LastInvalid = DxcCursor_InvalidCode,\n\n  /* Expressions */\n  DxcCursor_FirstExpr = 100,\n\n  /**\n  * \\brief An expression whose specific kind is not exposed via this\n  * interface.\n  *\n  * Unexposed expressions have the same operations as any other kind\n  * of expression; one can extract their location information,\n  * spelling, children, etc. However, the specific kind of the\n  * expression is not reported.\n  */\n  DxcCursor_UnexposedExpr = 100, // An expression whose specific kind is not exposed via this interface.\n  DxcCursor_DeclRefExpr = 101, // An expression that refers to some value declaration, such as a function, varible, or enumerator.\n  DxcCursor_MemberRefExpr = 102, // An expression that refers to a member of a struct, union, class, Objective-C class, etc.\n  DxcCursor_CallExpr = 103, // An expression that calls a function.\n  DxcCursor_ObjCMessageExpr = 104, // An expression that sends a message to an Objective-C object or class.\n  DxcCursor_BlockExpr = 105, // An expression that represents a block literal.\n  DxcCursor_IntegerLiteral = 106, // An integer literal.\n  DxcCursor_FloatingLiteral = 107, // A floating point number literal.\n  DxcCursor_ImaginaryLiteral = 108, // An imaginary number literal.\n  DxcCursor_StringLiteral = 109, // A string literal.\n  DxcCursor_CharacterLiteral = 110, // A character literal.\n  DxcCursor_ParenExpr = 111, // A parenthesized expression, e.g. \"(1)\". This AST node is only formed if full location information is requested.\n  DxcCursor_UnaryOperator = 112, // This represents the unary-expression's (except sizeof and alignof).\n  DxcCursor_ArraySubscriptExpr = 113, // [C99 6.5.2.1] Array Subscripting.\n  DxcCursor_BinaryOperator = 114, // A builtin binary operation expression such as \"x + y\" or \"x <= y\".\n  DxcCursor_CompoundAssignOperator = 115, // Compound assignment such as \"+=\".\n  DxcCursor_ConditionalOperator = 116, // The ?: ternary operator.\n  DxcCursor_CStyleCastExpr = 117, // An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr, eg: (int)f.\n  DxcCursor_CompoundLiteralExpr = 118, // [C99 6.5.2.5]\n  DxcCursor_InitListExpr = 119, // Describes an C or C++ initializer list.\n  DxcCursor_AddrLabelExpr = 120, // The GNU address of label extension, representing &&label.\n  DxcCursor_StmtExpr = 121, // This is the GNU Statement Expression extension: ({int X=4; X;})\n  DxcCursor_GenericSelectionExpr = 122, // Represents a C11 generic selection.\n\n  /** \\brief Implements the GNU __null extension, which is a name for a null\n  * pointer constant that has integral type (e.g., int or long) and is the same\n  * size and alignment as a pointer.\n  *\n  * The __null extension is typically only used by system headers, which define\n  * NULL as __null in C++ rather than using 0 (which is an integer that may not\n  * match the size of a pointer).\n  */\n  DxcCursor_GNUNullExpr = 123,\n  DxcCursor_CXXStaticCastExpr = 124, // C++'s static_cast<> expression.\n  DxcCursor_CXXDynamicCastExpr = 125, // C++'s dynamic_cast<> expression.\n  DxcCursor_CXXReinterpretCastExpr = 126, // C++'s reinterpret_cast<> expression.\n  DxcCursor_CXXConstCastExpr = 127, // C++'s const_cast<> expression.\n\n  /** \\brief Represents an explicit C++ type conversion that uses \"functional\"\n  * notion (C++ [expr.type.conv]).\n  *\n  * Example:\n  * \\code\n  *   x = int(0.5);\n  * \\endcode\n  */\n  DxcCursor_CXXFunctionalCastExpr = 128,\n  DxcCursor_CXXTypeidExpr = 129, // A C++ typeid expression (C++ [expr.typeid]).\n  DxcCursor_CXXBoolLiteralExpr = 130, // [C++ 2.13.5] C++ Boolean Literal.\n  DxcCursor_CXXNullPtrLiteralExpr = 131, // [C++0x 2.14.7] C++ Pointer Literal.\n  DxcCursor_CXXThisExpr = 132, // Represents the \"this\" expression in C++\n  DxcCursor_CXXThrowExpr = 133, // [C++ 15] C++ Throw Expression, both 'throw' and 'throw' assignment-expression.\n  DxcCursor_CXXNewExpr = 134, // A new expression for memory allocation and constructor calls, e.g: \"new CXXNewExpr(foo)\".\n  DxcCursor_CXXDeleteExpr = 135, // A delete expression for memory deallocation and destructor calls, e.g. \"delete[] pArray\".\n  DxcCursor_UnaryExpr = 136, // A unary expression.\n  DxcCursor_ObjCStringLiteral = 137, // An Objective-C string literal i.e. @\"foo\".\n  DxcCursor_ObjCEncodeExpr = 138, // An Objective-C \\@encode expression.\n  DxcCursor_ObjCSelectorExpr = 139, // An Objective-C \\@selector expression.\n  DxcCursor_ObjCProtocolExpr = 140, // An Objective-C \\@protocol expression.\n\n  /** \\brief An Objective-C \"bridged\" cast expression, which casts between\n  * Objective-C pointers and C pointers, transferring ownership in the process.\n  *\n  * \\code\n  *   NSString *str = (__bridge_transfer NSString *)CFCreateString();\n  * \\endcode\n  */\n  DxcCursor_ObjCBridgedCastExpr = 141,\n\n  /** \\brief Represents a C++0x pack expansion that produces a sequence of\n  * expressions.\n  *\n  * A pack expansion expression contains a pattern (which itself is an\n  * expression) followed by an ellipsis. For example:\n  *\n  * \\code\n  * template<typename F, typename ...Types>\n  * void forward(F f, Types &&...args) {\n  *  f(static_cast<Types&&>(args)...);\n  * }\n  * \\endcode\n  */\n  DxcCursor_PackExpansionExpr = 142,\n\n  /** \\brief Represents an expression that computes the length of a parameter\n  * pack.\n  *\n  * \\code\n  * template<typename ...Types>\n  * struct count {\n  *   static const unsigned value = sizeof...(Types);\n  * };\n  * \\endcode\n  */\n  DxcCursor_SizeOfPackExpr = 143,\n\n  /* \\brief Represents a C++ lambda expression that produces a local function\n  * object.\n  *\n  * \\code\n  * void abssort(float *x, unsigned N) {\n  *   std::sort(x, x + N,\n  *             [](float a, float b) {\n  *               return std::abs(a) < std::abs(b);\n  *             });\n  * }\n  * \\endcode\n  */\n  DxcCursor_LambdaExpr = 144,\n  DxcCursor_ObjCBoolLiteralExpr = 145, // Objective-c Boolean Literal.\n  DxcCursor_ObjCSelfExpr = 146, // Represents the \"self\" expression in a ObjC method.\n  DxcCursor_LastExpr = DxcCursor_ObjCSelfExpr,\n\n  /* Statements */\n  DxcCursor_FirstStmt = 200,\n  /**\n  * \\brief A statement whose specific kind is not exposed via this\n  * interface.\n  *\n  * Unexposed statements have the same operations as any other kind of\n  * statement; one can extract their location information, spelling,\n  * children, etc. However, the specific kind of the statement is not\n  * reported.\n  */\n  DxcCursor_UnexposedStmt = 200,\n\n  /** \\brief A labelled statement in a function.\n  *\n  * This cursor kind is used to describe the \"start_over:\" label statement in\n  * the following example:\n  *\n  * \\code\n  *   start_over:\n  *     ++counter;\n  * \\endcode\n  *\n  */\n  DxcCursor_LabelStmt = 201,\n  DxcCursor_CompoundStmt = 202, // A group of statements like { stmt stmt }. This cursor kind is used to describe compound statements, e.g. function bodies.\n  DxcCursor_CaseStmt = 203, // A case statement.\n  DxcCursor_DefaultStmt = 204, // A default statement.\n  DxcCursor_IfStmt = 205, // An if statement\n  DxcCursor_SwitchStmt = 206, // A switch statement.\n  DxcCursor_WhileStmt = 207, // A while statement.\n  DxcCursor_DoStmt = 208, // A do statement.\n  DxcCursor_ForStmt = 209, // A for statement.\n  DxcCursor_GotoStmt = 210, // A goto statement.\n  DxcCursor_IndirectGotoStmt = 211, // An indirect goto statement.\n  DxcCursor_ContinueStmt = 212, // A continue statement.\n  DxcCursor_BreakStmt = 213, // A break statement.\n  DxcCursor_ReturnStmt = 214, // A return statement.\n  DxcCursor_GCCAsmStmt = 215, // A GCC inline assembly statement extension.\n  DxcCursor_AsmStmt = DxcCursor_GCCAsmStmt,\n\n  DxcCursor_ObjCAtTryStmt = 216, // Objective-C's overall \\@try-\\@catch-\\@finally statement.\n  DxcCursor_ObjCAtCatchStmt = 217, // Objective-C's \\@catch statement.\n  DxcCursor_ObjCAtFinallyStmt = 218, // Objective-C's \\@finally statement.\n  DxcCursor_ObjCAtThrowStmt = 219, // Objective-C's \\@throw statement.\n  DxcCursor_ObjCAtSynchronizedStmt = 220, // Objective-C's \\@synchronized statement.\n  DxcCursor_ObjCAutoreleasePoolStmt = 221, // Objective-C's autorelease pool statement.\n  DxcCursor_ObjCForCollectionStmt = 222, // Objective-C's collection statement.\n\n  DxcCursor_CXXCatchStmt = 223, // C++'s catch statement.\n  DxcCursor_CXXTryStmt = 224, // C++'s try statement.\n  DxcCursor_CXXForRangeStmt = 225, // C++'s for (* : *) statement.\n\n  DxcCursor_SEHTryStmt = 226, // Windows Structured Exception Handling's try statement.\n  DxcCursor_SEHExceptStmt = 227, // Windows Structured Exception Handling's except statement.\n  DxcCursor_SEHFinallyStmt = 228, // Windows Structured Exception Handling's finally statement.\n\n  DxcCursor_MSAsmStmt = 229, // A MS inline assembly statement extension.\n  DxcCursor_NullStmt = 230, // The null satement \";\": C99 6.8.3p3.\n  DxcCursor_DeclStmt = 231, // Adaptor class for mixing declarations with statements and expressions.\n  DxcCursor_OMPParallelDirective = 232, // OpenMP parallel directive.\n  DxcCursor_OMPSimdDirective = 233,  // OpenMP SIMD directive.\n  DxcCursor_OMPForDirective = 234,  // OpenMP for directive.\n  DxcCursor_OMPSectionsDirective = 235,  // OpenMP sections directive.\n  DxcCursor_OMPSectionDirective = 236,  // OpenMP section directive.\n  DxcCursor_OMPSingleDirective = 237,  // OpenMP single directive.\n  DxcCursor_OMPParallelForDirective = 238,  // OpenMP parallel for directive.\n  DxcCursor_OMPParallelSectionsDirective = 239,  // OpenMP parallel sections directive.\n  DxcCursor_OMPTaskDirective = 240,  // OpenMP task directive.\n  DxcCursor_OMPMasterDirective = 241,  // OpenMP master directive.\n  DxcCursor_OMPCriticalDirective = 242,  // OpenMP critical directive.\n  DxcCursor_OMPTaskyieldDirective = 243,  // OpenMP taskyield directive.\n  DxcCursor_OMPBarrierDirective = 244,  // OpenMP barrier directive.\n  DxcCursor_OMPTaskwaitDirective = 245,  // OpenMP taskwait directive.\n  DxcCursor_OMPFlushDirective = 246,  // OpenMP flush directive.\n  DxcCursor_SEHLeaveStmt = 247,  // Windows Structured Exception Handling's leave statement.\n  DxcCursor_OMPOrderedDirective = 248,  // OpenMP ordered directive.\n  DxcCursor_OMPAtomicDirective = 249,  // OpenMP atomic directive.\n  DxcCursor_OMPForSimdDirective = 250,  // OpenMP for SIMD directive.\n  DxcCursor_OMPParallelForSimdDirective = 251,  // OpenMP parallel for SIMD directive.\n  DxcCursor_OMPTargetDirective = 252,  // OpenMP target directive.\n  DxcCursor_OMPTeamsDirective = 253,  // OpenMP teams directive.\n  DxcCursor_OMPTaskgroupDirective = 254,  // OpenMP taskgroup directive.\n  DxcCursor_OMPCancellationPointDirective = 255,  // OpenMP cancellation point directive.\n  DxcCursor_OMPCancelDirective = 256,  // OpenMP cancel directive.\n  DxcCursor_LastStmt = DxcCursor_OMPCancelDirective,\n\n  DxcCursor_TranslationUnit = 300, // Cursor that represents the translation unit itself.\n\n  /* Attributes */\n  DxcCursor_FirstAttr = 400,\n  /**\n  * \\brief An attribute whose specific kind is not exposed via this\n  * interface.\n  */\n  DxcCursor_UnexposedAttr = 400,\n\n  DxcCursor_IBActionAttr = 401,\n  DxcCursor_IBOutletAttr = 402,\n  DxcCursor_IBOutletCollectionAttr = 403,\n  DxcCursor_CXXFinalAttr = 404,\n  DxcCursor_CXXOverrideAttr = 405,\n  DxcCursor_AnnotateAttr = 406,\n  DxcCursor_AsmLabelAttr = 407,\n  DxcCursor_PackedAttr = 408,\n  DxcCursor_PureAttr = 409,\n  DxcCursor_ConstAttr = 410,\n  DxcCursor_NoDuplicateAttr = 411,\n  DxcCursor_CUDAConstantAttr = 412,\n  DxcCursor_CUDADeviceAttr = 413,\n  DxcCursor_CUDAGlobalAttr = 414,\n  DxcCursor_CUDAHostAttr = 415,\n  DxcCursor_CUDASharedAttr = 416,\n  DxcCursor_LastAttr = DxcCursor_CUDASharedAttr,\n\n  /* Preprocessing */\n  DxcCursor_PreprocessingDirective = 500,\n  DxcCursor_MacroDefinition = 501,\n  DxcCursor_MacroExpansion = 502,\n  DxcCursor_MacroInstantiation = DxcCursor_MacroExpansion,\n  DxcCursor_InclusionDirective = 503,\n  DxcCursor_FirstPreprocessing = DxcCursor_PreprocessingDirective,\n  DxcCursor_LastPreprocessing = DxcCursor_InclusionDirective,\n\n  /* Extra Declarations */\n  /**\n  * \\brief A module import declaration.\n  */\n  DxcCursor_ModuleImportDecl = 600,\n  DxcCursor_FirstExtraDecl = DxcCursor_ModuleImportDecl,\n  DxcCursor_LastExtraDecl = DxcCursor_ModuleImportDecl\n};\n\nenum DxcCursorKindFlags\n{\n  DxcCursorKind_None = 0,\n  DxcCursorKind_Declaration = 0x1,\n  DxcCursorKind_Reference = 0x2,\n  DxcCursorKind_Expression = 0x4,\n  DxcCursorKind_Statement = 0x8,\n  DxcCursorKind_Attribute = 0x10,\n  DxcCursorKind_Invalid = 0x20,\n  DxcCursorKind_TranslationUnit = 0x40,\n  DxcCursorKind_Preprocessing = 0x80,\n  DxcCursorKind_Unexposed = 0x100,\n};\n\nenum DxcCodeCompleteFlags\n{\n  DxcCodeCompleteFlags_None = 0,\n  DxcCodeCompleteFlags_IncludeMacros = 0x1,\n  DxcCodeCompleteFlags_IncludeCodePatterns = 0x2,\n  DxcCodeCompleteFlags_IncludeBriefComments = 0x4,\n};\n\nenum DxcCompletionChunkKind\n{\n  DxcCompletionChunk_Optional = 0,\n  DxcCompletionChunk_TypedText = 1,\n  DxcCompletionChunk_Text = 2,\n  DxcCompletionChunk_Placeholder = 3,\n  DxcCompletionChunk_Informative = 4,\n  DxcCompletionChunk_CurrentParameter = 5,\n  DxcCompletionChunk_LeftParen = 6,\n  DxcCompletionChunk_RightParen = 7,\n  DxcCompletionChunk_LeftBracket = 8,\n  DxcCompletionChunk_RightBracket = 9,\n  DxcCompletionChunk_LeftBrace = 10,\n  DxcCompletionChunk_RightBrace = 11,\n  DxcCompletionChunk_LeftAngle = 12,\n  DxcCompletionChunk_RightAngle = 13,\n  DxcCompletionChunk_Comma = 14,\n  DxcCompletionChunk_ResultType = 15,\n  DxcCompletionChunk_Colon = 16,\n  DxcCompletionChunk_SemiColon = 17,\n  DxcCompletionChunk_Equal = 18,\n  DxcCompletionChunk_HorizontalSpace = 19,\n  DxcCompletionChunk_VerticalSpace = 20,\n};\n\nstruct IDxcCursor;\nstruct IDxcDiagnostic;\nstruct IDxcFile;\nstruct IDxcInclusion;\nstruct IDxcIntelliSense;\nstruct IDxcIndex;\nstruct IDxcSourceLocation;\nstruct IDxcSourceRange;\nstruct IDxcToken;\nstruct IDxcTranslationUnit;\nstruct IDxcType;\nstruct IDxcUnsavedFile;\nstruct IDxcCodeCompleteResults;\nstruct IDxcCompletionResult;\nstruct IDxcCompletionString;\n\nCROSS_PLATFORM_UUIDOF(IDxcCursor, \"1467b985-288d-4d2a-80c1-ef89c42c40bc\")\nstruct IDxcCursor : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetExtent(_Outptr_result_nullonfailure_ IDxcSourceRange** pRange) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLocation(_Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetKind(_Out_ DxcCursorKind* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetKindFlags(_Out_ DxcCursorKindFlags* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSemanticParent(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLexicalParent(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCursorType(_Outptr_result_nullonfailure_ IDxcType** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetNumArguments(_Out_ int* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetArgumentAt(int index, _Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetReferencedCursor(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0;\n  /// <summary>For a cursor that is either a reference to or a declaration of some entity, retrieve a cursor that describes the definition of that entity.</summary>\n  /// <remarks>Some entities can be declared multiple times within a translation unit, but only one of those declarations can also be a definition.</remarks>\n  /// <returns>A cursor to the definition of this entity; nullptr if there is no definition in this translation unit.</returns>\n  virtual HRESULT STDMETHODCALLTYPE GetDefinitionCursor(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE FindReferencesInFile(\n    _In_ IDxcFile* file, unsigned skip, unsigned top,\n    _Out_ unsigned* pResultLength, _Outptr_result_buffer_maybenull_(*pResultLength) IDxcCursor*** pResult) = 0;\n  /// <summary>Gets the name for the entity references by the cursor, e.g. foo for an 'int foo' variable.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Outptr_result_maybenull_ LPSTR* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcCursor* other, _Out_ BOOL* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE IsNull(_Out_ BOOL* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE IsDefinition(_Out_ BOOL* pResult) = 0;\n  /// <summary>Gets the display name for the cursor, including e.g. parameter types for a function.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetDisplayName(_Out_ BSTR* pResult) = 0;\n  /// <summary>Gets the qualified name for the symbol the cursor refers to.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetQualifiedName(BOOL includeTemplateArgs, _Outptr_result_maybenull_ BSTR* pResult) = 0;\n  /// <summary>Gets a name for the cursor, applying the specified formatting flags.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetFormattedName(DxcCursorFormatting formatting , _Outptr_result_maybenull_ BSTR* pResult) = 0;\n  /// <summary>Gets children in pResult up to top elements.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetChildren(\n    unsigned skip, unsigned top,\n    _Out_ unsigned* pResultLength, _Outptr_result_buffer_maybenull_(*pResultLength) IDxcCursor*** pResult) = 0;\n  /// <summary>Gets the cursor following a location within a compound cursor.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetSnappedChild(_In_ IDxcSourceLocation* location, _Outptr_result_maybenull_ IDxcCursor** pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcDiagnostic, \"4f76b234-3659-4d33-99b0-3b0db994b564\")\nstruct IDxcDiagnostic : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE FormatDiagnostic(\n    DxcDiagnosticDisplayOptions options,\n    _Outptr_result_maybenull_ LPSTR* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSeverity(_Out_ DxcDiagnosticSeverity* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLocation(_Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Outptr_result_maybenull_ LPSTR* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCategoryText(_Outptr_result_maybenull_ LPSTR* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetNumRanges(_Out_ unsigned* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetRangeAt(unsigned index, _Outptr_result_nullonfailure_ IDxcSourceRange** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetNumFixIts(_Out_ unsigned* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFixItAt(unsigned index,\n    _Outptr_result_nullonfailure_ IDxcSourceRange** pReplacementRange, _Outptr_result_maybenull_ LPSTR* pText) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcFile, \"bb2fca9e-1478-47ba-b08c-2c502ada4895\")\nstruct IDxcFile : public IUnknown\n{\n  /// <summary>Gets the file name for this file.</summary>\n  virtual HRESULT STDMETHODCALLTYPE GetName(_Outptr_result_maybenull_ LPSTR* pResult) = 0;\n  /// <summary>Checks whether this file is equal to the other specified file.</summary>\n  virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcFile* other, _Out_ BOOL* pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcInclusion, \"0c364d65-df44-4412-888e-4e552fc5e3d6\")\nstruct IDxcInclusion : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetIncludedFile(_Outptr_result_nullonfailure_ IDxcFile** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetStackLength(_Out_ unsigned *pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetStackItem(unsigned index, _Outptr_result_nullonfailure_ IDxcSourceLocation **pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcIntelliSense, \"b1f99513-46d6-4112-8169-dd0d6053f17d\")\nstruct IDxcIntelliSense : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE CreateIndex(_Outptr_result_nullonfailure_ IDxcIndex** index) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetNullLocation(_Outptr_result_nullonfailure_ IDxcSourceLocation** location) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetNullRange(_Outptr_result_nullonfailure_ IDxcSourceRange** location) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetRange(\n    _In_ IDxcSourceLocation* start,\n    _In_ IDxcSourceLocation* end,\n    _Outptr_result_nullonfailure_ IDxcSourceRange** location) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDefaultDiagnosticDisplayOptions(\n    _Out_ DxcDiagnosticDisplayOptions* pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDefaultEditingTUOptions(_Out_ DxcTranslationUnitFlags* pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CreateUnsavedFile(_In_ LPCSTR fileName, _In_ LPCSTR contents, unsigned contentLength, _Outptr_result_nullonfailure_ IDxcUnsavedFile** pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcIndex, \"937824a0-7f5a-4815-9ba7-7fc0424f4173\")\nstruct IDxcIndex : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE SetGlobalOptions(DxcGlobalOptions options) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetGlobalOptions(_Out_ DxcGlobalOptions* options) = 0;\n  virtual HRESULT STDMETHODCALLTYPE ParseTranslationUnit(\n      _In_z_ const char *source_filename,\n      _In_count_(num_command_line_args) const char * const *command_line_args,\n      int num_command_line_args,\n      _In_count_(num_unsaved_files) IDxcUnsavedFile** unsaved_files,\n      unsigned num_unsaved_files,\n      DxcTranslationUnitFlags options,\n      _Out_ IDxcTranslationUnit** pTranslationUnit) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcSourceLocation, \"8e7ddf1c-d7d3-4d69-b286-85fccba1e0cf\")\nstruct IDxcSourceLocation : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcSourceLocation* other, _Out_ BOOL* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSpellingLocation(\n    _Outptr_opt_ IDxcFile** pFile,\n    _Out_opt_ unsigned* pLine,\n    _Out_opt_ unsigned* pCol,\n    _Out_opt_ unsigned* pOffset) = 0;\n  virtual HRESULT STDMETHODCALLTYPE IsNull(_Out_ BOOL* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetPresumedLocation(\n    _Outptr_opt_ LPSTR* pFilename,\n    _Out_opt_ unsigned* pLine,\n    _Out_opt_ unsigned* pCol) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcSourceRange, \"f1359b36-a53f-4e81-b514-b6b84122a13f\")\nstruct IDxcSourceRange : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE IsNull(_Out_ BOOL* pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetStart(_Out_ IDxcSourceLocation** pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetEnd(_Out_ IDxcSourceLocation** pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetOffsets(_Out_ unsigned* startOffset, _Out_ unsigned* endOffset) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcToken, \"7f90b9ff-a275-4932-97d8-3cfd234482a2\")\nstruct IDxcToken : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetKind(_Out_ DxcTokenKind* pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLocation(_Out_ IDxcSourceLocation** pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetExtent(_Out_ IDxcSourceRange** pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Out_ LPSTR* pValue) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcTranslationUnit, \"9677dee0-c0e5-46a1-8b40-3db3168be63d\")\nstruct IDxcTranslationUnit : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetCursor(_Out_ IDxcCursor** pCursor) = 0;\n  virtual HRESULT STDMETHODCALLTYPE Tokenize(\n    _In_ IDxcSourceRange* range,\n    _Outptr_result_buffer_maybenull_(*pTokenCount) IDxcToken*** pTokens,\n    _Out_ unsigned* pTokenCount) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLocation(\n    _In_ IDxcFile* file,\n    unsigned line, unsigned column,\n    _Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetNumDiagnostics(_Out_ unsigned* pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDiagnostic(unsigned index, _Outptr_result_nullonfailure_ IDxcDiagnostic** pValue) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFile(_In_ const char* name, _Outptr_result_nullonfailure_ IDxcFile** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetFileName(_Outptr_result_maybenull_ LPSTR* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE Reparse(\n    _In_count_(num_unsaved_files) IDxcUnsavedFile** unsaved_files,\n    unsigned num_unsaved_files) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCursorForLocation(_In_ IDxcSourceLocation* location, _Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLocationForOffset(_In_ IDxcFile* file, unsigned offset, _Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetSkippedRanges(_In_ IDxcFile* file, _Out_ unsigned* pResultCount, _Outptr_result_buffer_(*pResultCount) IDxcSourceRange*** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetDiagnosticDetails(unsigned index, DxcDiagnosticDisplayOptions options,\n    _Out_ unsigned* errorCode,\n    _Out_ unsigned* errorLine,\n    _Out_ unsigned* errorColumn,\n    _Out_ BSTR* errorFile,\n    _Out_ unsigned* errorOffset,\n    _Out_ unsigned* errorLength,\n    _Out_ BSTR* errorMessage) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetInclusionList(_Out_ unsigned* pResultCount, _Outptr_result_buffer_(*pResultCount) IDxcInclusion*** pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE CodeCompleteAt(\n      _In_ const char *fileName, unsigned line, unsigned column,\n      _In_ IDxcUnsavedFile** pUnsavedFiles, unsigned numUnsavedFiles,\n      _In_ DxcCodeCompleteFlags options,\n      _Outptr_result_nullonfailure_ IDxcCodeCompleteResults **pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcType, \"2ec912fd-b144-4a15-ad0d-1c5439c81e46\")\nstruct IDxcType : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Outptr_result_z_ LPSTR* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcType* other, _Out_ BOOL* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetKind(_Out_ DxcTypeKind* pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcUnsavedFile, \"8ec00f98-07d0-4e60-9d7c-5a50b5b0017f\")\nstruct IDxcUnsavedFile : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetFileName(_Outptr_result_z_ LPSTR* pFileName) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetContents(_Outptr_result_z_ LPSTR* pContents) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetLength(_Out_ unsigned* pLength) = 0;\n};\n\n\nCROSS_PLATFORM_UUIDOF(IDxcCodeCompleteResults, \"1E06466A-FD8B-45F3-A78F-8A3F76EBB552\")\nstruct IDxcCodeCompleteResults : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetNumResults(_Out_ unsigned* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetResultAt(unsigned index, _Outptr_result_nullonfailure_ IDxcCompletionResult** pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcCompletionResult, \"943C0588-22D0-4784-86FC-701F802AC2B6\")\nstruct IDxcCompletionResult : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetCursorKind(_Out_ DxcCursorKind* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCompletionString(_Outptr_result_nullonfailure_ IDxcCompletionString** pResult) = 0;\n};\n\nCROSS_PLATFORM_UUIDOF(IDxcCompletionString, \"06B51E0F-A605-4C69-A110-CD6E14B58EEC\")\nstruct IDxcCompletionString : public IUnknown\n{\n  virtual HRESULT STDMETHODCALLTYPE GetNumCompletionChunks(_Out_ unsigned* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCompletionChunkKind(unsigned chunkNumber, _Out_ DxcCompletionChunkKind* pResult) = 0;\n  virtual HRESULT STDMETHODCALLTYPE GetCompletionChunkText(unsigned chunkNumber, _Out_ LPSTR* pResult) = 0;\n};\n\n// Fun fact: 'extern' is required because const is by default static in C++, so\n// CLSID_DxcIntelliSense is not visible externally (this is OK in C, since const is\n// not by default static in C)\n\n#ifdef _MSC_VER\n#define CLSID_SCOPE __declspec(selectany) extern\n#else\n#define CLSID_SCOPE\n#endif\n\nCLSID_SCOPE const CLSID\n    CLSID_DxcIntelliSense = {/* 3047833c-d1c0-4b8e-9d40-102878605985 */\n                             0x3047833c,\n                             0xd1c0,\n                             0x4b8e,\n                             {0x9d, 0x40, 0x10, 0x28, 0x78, 0x60, 0x59, 0x85}};\n\n#endif\n"
  },
  {
    "path": "Source/External/imgui_tools/IconsFontAwesome/IconsFontAwesome5.h",
    "content": "// Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++\n// from https://github.com/FortAwesome/Font-Awesome/raw/5.x/metadata/icons.yml\n// for use with https://github.com/FortAwesome/Font-Awesome/blob/5.x/webfonts/fa-regular-400.ttf, https://github.com/FortAwesome/Font-Awesome/blob/5.x/webfonts/fa-solid-900.ttf\n#pragma once\n\n#define FONT_ICON_FILE_NAME_FAR \"fa-regular-400.ttf\"\n#define FONT_ICON_FILE_NAME_FAS \"fa-solid-900.ttf\"\n\n#define ICON_MIN_FA 0xe005\n#define ICON_MAX_16_FA 0xf8ff\n#define ICON_MAX_FA 0xf8ff\n#define ICON_FA_AD \"\\xef\\x99\\x81\"\t// U+f641\n#define ICON_FA_ADDRESS_BOOK \"\\xef\\x8a\\xb9\"\t// U+f2b9\n#define ICON_FA_ADDRESS_CARD \"\\xef\\x8a\\xbb\"\t// U+f2bb\n#define ICON_FA_ADJUST \"\\xef\\x81\\x82\"\t// U+f042\n#define ICON_FA_AIR_FRESHENER \"\\xef\\x97\\x90\"\t// U+f5d0\n#define ICON_FA_ALIGN_CENTER \"\\xef\\x80\\xb7\"\t// U+f037\n#define ICON_FA_ALIGN_JUSTIFY \"\\xef\\x80\\xb9\"\t// U+f039\n#define ICON_FA_ALIGN_LEFT \"\\xef\\x80\\xb6\"\t// U+f036\n#define ICON_FA_ALIGN_RIGHT \"\\xef\\x80\\xb8\"\t// U+f038\n#define ICON_FA_ALLERGIES \"\\xef\\x91\\xa1\"\t// U+f461\n#define ICON_FA_AMBULANCE \"\\xef\\x83\\xb9\"\t// U+f0f9\n#define ICON_FA_AMERICAN_SIGN_LANGUAGE_INTERPRETING \"\\xef\\x8a\\xa3\"\t// U+f2a3\n#define ICON_FA_ANCHOR \"\\xef\\x84\\xbd\"\t// U+f13d\n#define ICON_FA_ANGLE_DOUBLE_DOWN \"\\xef\\x84\\x83\"\t// U+f103\n#define ICON_FA_ANGLE_DOUBLE_LEFT \"\\xef\\x84\\x80\"\t// U+f100\n#define ICON_FA_ANGLE_DOUBLE_RIGHT \"\\xef\\x84\\x81\"\t// U+f101\n#define ICON_FA_ANGLE_DOUBLE_UP \"\\xef\\x84\\x82\"\t// U+f102\n#define ICON_FA_ANGLE_DOWN \"\\xef\\x84\\x87\"\t// U+f107\n#define ICON_FA_ANGLE_LEFT \"\\xef\\x84\\x84\"\t// U+f104\n#define ICON_FA_ANGLE_RIGHT \"\\xef\\x84\\x85\"\t// U+f105\n#define ICON_FA_ANGLE_UP \"\\xef\\x84\\x86\"\t// U+f106\n#define ICON_FA_ANGRY \"\\xef\\x95\\x96\"\t// U+f556\n#define ICON_FA_ANKH \"\\xef\\x99\\x84\"\t// U+f644\n#define ICON_FA_APPLE_ALT \"\\xef\\x97\\x91\"\t// U+f5d1\n#define ICON_FA_ARCHIVE \"\\xef\\x86\\x87\"\t// U+f187\n#define ICON_FA_ARCHWAY \"\\xef\\x95\\x97\"\t// U+f557\n#define ICON_FA_ARROW_ALT_CIRCLE_DOWN \"\\xef\\x8d\\x98\"\t// U+f358\n#define ICON_FA_ARROW_ALT_CIRCLE_LEFT \"\\xef\\x8d\\x99\"\t// U+f359\n#define ICON_FA_ARROW_ALT_CIRCLE_RIGHT \"\\xef\\x8d\\x9a\"\t// U+f35a\n#define ICON_FA_ARROW_ALT_CIRCLE_UP \"\\xef\\x8d\\x9b\"\t// U+f35b\n#define ICON_FA_ARROW_CIRCLE_DOWN \"\\xef\\x82\\xab\"\t// U+f0ab\n#define ICON_FA_ARROW_CIRCLE_LEFT \"\\xef\\x82\\xa8\"\t// U+f0a8\n#define ICON_FA_ARROW_CIRCLE_RIGHT \"\\xef\\x82\\xa9\"\t// U+f0a9\n#define ICON_FA_ARROW_CIRCLE_UP \"\\xef\\x82\\xaa\"\t// U+f0aa\n#define ICON_FA_ARROW_DOWN \"\\xef\\x81\\xa3\"\t// U+f063\n#define ICON_FA_ARROW_LEFT \"\\xef\\x81\\xa0\"\t// U+f060\n#define ICON_FA_ARROW_RIGHT \"\\xef\\x81\\xa1\"\t// U+f061\n#define ICON_FA_ARROW_UP \"\\xef\\x81\\xa2\"\t// U+f062\n#define ICON_FA_ARROWS_ALT \"\\xef\\x82\\xb2\"\t// U+f0b2\n#define ICON_FA_ARROWS_ALT_H \"\\xef\\x8c\\xb7\"\t// U+f337\n#define ICON_FA_ARROWS_ALT_V \"\\xef\\x8c\\xb8\"\t// U+f338\n#define ICON_FA_ASSISTIVE_LISTENING_SYSTEMS \"\\xef\\x8a\\xa2\"\t// U+f2a2\n#define ICON_FA_ASTERISK \"\\xef\\x81\\xa9\"\t// U+f069\n#define ICON_FA_AT \"\\xef\\x87\\xba\"\t// U+f1fa\n#define ICON_FA_ATLAS \"\\xef\\x95\\x98\"\t// U+f558\n#define ICON_FA_ATOM \"\\xef\\x97\\x92\"\t// U+f5d2\n#define ICON_FA_AUDIO_DESCRIPTION \"\\xef\\x8a\\x9e\"\t// U+f29e\n#define ICON_FA_AWARD \"\\xef\\x95\\x99\"\t// U+f559\n#define ICON_FA_BABY \"\\xef\\x9d\\xbc\"\t// U+f77c\n#define ICON_FA_BABY_CARRIAGE \"\\xef\\x9d\\xbd\"\t// U+f77d\n#define ICON_FA_BACKSPACE \"\\xef\\x95\\x9a\"\t// U+f55a\n#define ICON_FA_BACKWARD \"\\xef\\x81\\x8a\"\t// U+f04a\n#define ICON_FA_BACON \"\\xef\\x9f\\xa5\"\t// U+f7e5\n#define ICON_FA_BACTERIA \"\\xee\\x81\\x99\"\t// U+e059\n#define ICON_FA_BACTERIUM \"\\xee\\x81\\x9a\"\t// U+e05a\n#define ICON_FA_BAHAI \"\\xef\\x99\\xa6\"\t// U+f666\n#define ICON_FA_BALANCE_SCALE \"\\xef\\x89\\x8e\"\t// U+f24e\n#define ICON_FA_BALANCE_SCALE_LEFT \"\\xef\\x94\\x95\"\t// U+f515\n#define ICON_FA_BALANCE_SCALE_RIGHT \"\\xef\\x94\\x96\"\t// U+f516\n#define ICON_FA_BAN \"\\xef\\x81\\x9e\"\t// U+f05e\n#define ICON_FA_BAND_AID \"\\xef\\x91\\xa2\"\t// U+f462\n#define ICON_FA_BARCODE \"\\xef\\x80\\xaa\"\t// U+f02a\n#define ICON_FA_BARS \"\\xef\\x83\\x89\"\t// U+f0c9\n#define ICON_FA_BASEBALL_BALL \"\\xef\\x90\\xb3\"\t// U+f433\n#define ICON_FA_BASKETBALL_BALL \"\\xef\\x90\\xb4\"\t// U+f434\n#define ICON_FA_BATH \"\\xef\\x8b\\x8d\"\t// U+f2cd\n#define ICON_FA_BATTERY_EMPTY \"\\xef\\x89\\x84\"\t// U+f244\n#define ICON_FA_BATTERY_FULL \"\\xef\\x89\\x80\"\t// U+f240\n#define ICON_FA_BATTERY_HALF \"\\xef\\x89\\x82\"\t// U+f242\n#define ICON_FA_BATTERY_QUARTER \"\\xef\\x89\\x83\"\t// U+f243\n#define ICON_FA_BATTERY_THREE_QUARTERS \"\\xef\\x89\\x81\"\t// U+f241\n#define ICON_FA_BED \"\\xef\\x88\\xb6\"\t// U+f236\n#define ICON_FA_BEER \"\\xef\\x83\\xbc\"\t// U+f0fc\n#define ICON_FA_BELL \"\\xef\\x83\\xb3\"\t// U+f0f3\n#define ICON_FA_BELL_SLASH \"\\xef\\x87\\xb6\"\t// U+f1f6\n#define ICON_FA_BEZIER_CURVE \"\\xef\\x95\\x9b\"\t// U+f55b\n#define ICON_FA_BIBLE \"\\xef\\x99\\x87\"\t// U+f647\n#define ICON_FA_BICYCLE \"\\xef\\x88\\x86\"\t// U+f206\n#define ICON_FA_BIKING \"\\xef\\xa1\\x8a\"\t// U+f84a\n#define ICON_FA_BINOCULARS \"\\xef\\x87\\xa5\"\t// U+f1e5\n#define ICON_FA_BIOHAZARD \"\\xef\\x9e\\x80\"\t// U+f780\n#define ICON_FA_BIRTHDAY_CAKE \"\\xef\\x87\\xbd\"\t// U+f1fd\n#define ICON_FA_BLENDER \"\\xef\\x94\\x97\"\t// U+f517\n#define ICON_FA_BLENDER_PHONE \"\\xef\\x9a\\xb6\"\t// U+f6b6\n#define ICON_FA_BLIND \"\\xef\\x8a\\x9d\"\t// U+f29d\n#define ICON_FA_BLOG \"\\xef\\x9e\\x81\"\t// U+f781\n#define ICON_FA_BOLD \"\\xef\\x80\\xb2\"\t// U+f032\n#define ICON_FA_BOLT \"\\xef\\x83\\xa7\"\t// U+f0e7\n#define ICON_FA_BOMB \"\\xef\\x87\\xa2\"\t// U+f1e2\n#define ICON_FA_BONE \"\\xef\\x97\\x97\"\t// U+f5d7\n#define ICON_FA_BONG \"\\xef\\x95\\x9c\"\t// U+f55c\n#define ICON_FA_BOOK \"\\xef\\x80\\xad\"\t// U+f02d\n#define ICON_FA_BOOK_DEAD \"\\xef\\x9a\\xb7\"\t// U+f6b7\n#define ICON_FA_BOOK_MEDICAL \"\\xef\\x9f\\xa6\"\t// U+f7e6\n#define ICON_FA_BOOK_OPEN \"\\xef\\x94\\x98\"\t// U+f518\n#define ICON_FA_BOOK_READER \"\\xef\\x97\\x9a\"\t// U+f5da\n#define ICON_FA_BOOKMARK \"\\xef\\x80\\xae\"\t// U+f02e\n#define ICON_FA_BORDER_ALL \"\\xef\\xa1\\x8c\"\t// U+f84c\n#define ICON_FA_BORDER_NONE \"\\xef\\xa1\\x90\"\t// U+f850\n#define ICON_FA_BORDER_STYLE \"\\xef\\xa1\\x93\"\t// U+f853\n#define ICON_FA_BOWLING_BALL \"\\xef\\x90\\xb6\"\t// U+f436\n#define ICON_FA_BOX \"\\xef\\x91\\xa6\"\t// U+f466\n#define ICON_FA_BOX_OPEN \"\\xef\\x92\\x9e\"\t// U+f49e\n#define ICON_FA_BOX_TISSUE \"\\xee\\x81\\x9b\"\t// U+e05b\n#define ICON_FA_BOXES \"\\xef\\x91\\xa8\"\t// U+f468\n#define ICON_FA_BRAILLE \"\\xef\\x8a\\xa1\"\t// U+f2a1\n#define ICON_FA_BRAIN \"\\xef\\x97\\x9c\"\t// U+f5dc\n#define ICON_FA_BREAD_SLICE \"\\xef\\x9f\\xac\"\t// U+f7ec\n#define ICON_FA_BRIEFCASE \"\\xef\\x82\\xb1\"\t// U+f0b1\n#define ICON_FA_BRIEFCASE_MEDICAL \"\\xef\\x91\\xa9\"\t// U+f469\n#define ICON_FA_BROADCAST_TOWER \"\\xef\\x94\\x99\"\t// U+f519\n#define ICON_FA_BROOM \"\\xef\\x94\\x9a\"\t// U+f51a\n#define ICON_FA_BRUSH \"\\xef\\x95\\x9d\"\t// U+f55d\n#define ICON_FA_BUG \"\\xef\\x86\\x88\"\t// U+f188\n#define ICON_FA_BUILDING \"\\xef\\x86\\xad\"\t// U+f1ad\n#define ICON_FA_BULLHORN \"\\xef\\x82\\xa1\"\t// U+f0a1\n#define ICON_FA_BULLSEYE \"\\xef\\x85\\x80\"\t// U+f140\n#define ICON_FA_BURN \"\\xef\\x91\\xaa\"\t// U+f46a\n#define ICON_FA_BUS \"\\xef\\x88\\x87\"\t// U+f207\n#define ICON_FA_BUS_ALT \"\\xef\\x95\\x9e\"\t// U+f55e\n#define ICON_FA_BUSINESS_TIME \"\\xef\\x99\\x8a\"\t// U+f64a\n#define ICON_FA_CALCULATOR \"\\xef\\x87\\xac\"\t// U+f1ec\n#define ICON_FA_CALENDAR \"\\xef\\x84\\xb3\"\t// U+f133\n#define ICON_FA_CALENDAR_ALT \"\\xef\\x81\\xb3\"\t// U+f073\n#define ICON_FA_CALENDAR_CHECK \"\\xef\\x89\\xb4\"\t// U+f274\n#define ICON_FA_CALENDAR_DAY \"\\xef\\x9e\\x83\"\t// U+f783\n#define ICON_FA_CALENDAR_MINUS \"\\xef\\x89\\xb2\"\t// U+f272\n#define ICON_FA_CALENDAR_PLUS \"\\xef\\x89\\xb1\"\t// U+f271\n#define ICON_FA_CALENDAR_TIMES \"\\xef\\x89\\xb3\"\t// U+f273\n#define ICON_FA_CALENDAR_WEEK \"\\xef\\x9e\\x84\"\t// U+f784\n#define ICON_FA_CAMERA \"\\xef\\x80\\xb0\"\t// U+f030\n#define ICON_FA_CAMERA_RETRO \"\\xef\\x82\\x83\"\t// U+f083\n#define ICON_FA_CAMPGROUND \"\\xef\\x9a\\xbb\"\t// U+f6bb\n#define ICON_FA_CANDY_CANE \"\\xef\\x9e\\x86\"\t// U+f786\n#define ICON_FA_CANNABIS \"\\xef\\x95\\x9f\"\t// U+f55f\n#define ICON_FA_CAPSULES \"\\xef\\x91\\xab\"\t// U+f46b\n#define ICON_FA_CAR \"\\xef\\x86\\xb9\"\t// U+f1b9\n#define ICON_FA_CAR_ALT \"\\xef\\x97\\x9e\"\t// U+f5de\n#define ICON_FA_CAR_BATTERY \"\\xef\\x97\\x9f\"\t// U+f5df\n#define ICON_FA_CAR_CRASH \"\\xef\\x97\\xa1\"\t// U+f5e1\n#define ICON_FA_CAR_SIDE \"\\xef\\x97\\xa4\"\t// U+f5e4\n#define ICON_FA_CARAVAN \"\\xef\\xa3\\xbf\"\t// U+f8ff\n#define ICON_FA_CARET_DOWN \"\\xef\\x83\\x97\"\t// U+f0d7\n#define ICON_FA_CARET_LEFT \"\\xef\\x83\\x99\"\t// U+f0d9\n#define ICON_FA_CARET_RIGHT \"\\xef\\x83\\x9a\"\t// U+f0da\n#define ICON_FA_CARET_SQUARE_DOWN \"\\xef\\x85\\x90\"\t// U+f150\n#define ICON_FA_CARET_SQUARE_LEFT \"\\xef\\x86\\x91\"\t// U+f191\n#define ICON_FA_CARET_SQUARE_RIGHT \"\\xef\\x85\\x92\"\t// U+f152\n#define ICON_FA_CARET_SQUARE_UP \"\\xef\\x85\\x91\"\t// U+f151\n#define ICON_FA_CARET_UP \"\\xef\\x83\\x98\"\t// U+f0d8\n#define ICON_FA_CARROT \"\\xef\\x9e\\x87\"\t// U+f787\n#define ICON_FA_CART_ARROW_DOWN \"\\xef\\x88\\x98\"\t// U+f218\n#define ICON_FA_CART_PLUS \"\\xef\\x88\\x97\"\t// U+f217\n#define ICON_FA_CASH_REGISTER \"\\xef\\x9e\\x88\"\t// U+f788\n#define ICON_FA_CAT \"\\xef\\x9a\\xbe\"\t// U+f6be\n#define ICON_FA_CERTIFICATE \"\\xef\\x82\\xa3\"\t// U+f0a3\n#define ICON_FA_CHAIR \"\\xef\\x9b\\x80\"\t// U+f6c0\n#define ICON_FA_CHALKBOARD \"\\xef\\x94\\x9b\"\t// U+f51b\n#define ICON_FA_CHALKBOARD_TEACHER \"\\xef\\x94\\x9c\"\t// U+f51c\n#define ICON_FA_CHARGING_STATION \"\\xef\\x97\\xa7\"\t// U+f5e7\n#define ICON_FA_CHART_AREA \"\\xef\\x87\\xbe\"\t// U+f1fe\n#define ICON_FA_CHART_BAR \"\\xef\\x82\\x80\"\t// U+f080\n#define ICON_FA_CHART_LINE \"\\xef\\x88\\x81\"\t// U+f201\n#define ICON_FA_CHART_PIE \"\\xef\\x88\\x80\"\t// U+f200\n#define ICON_FA_CHECK \"\\xef\\x80\\x8c\"\t// U+f00c\n#define ICON_FA_CHECK_CIRCLE \"\\xef\\x81\\x98\"\t// U+f058\n#define ICON_FA_CHECK_DOUBLE \"\\xef\\x95\\xa0\"\t// U+f560\n#define ICON_FA_CHECK_SQUARE \"\\xef\\x85\\x8a\"\t// U+f14a\n#define ICON_FA_CHEESE \"\\xef\\x9f\\xaf\"\t// U+f7ef\n#define ICON_FA_CHESS \"\\xef\\x90\\xb9\"\t// U+f439\n#define ICON_FA_CHESS_BISHOP \"\\xef\\x90\\xba\"\t// U+f43a\n#define ICON_FA_CHESS_BOARD \"\\xef\\x90\\xbc\"\t// U+f43c\n#define ICON_FA_CHESS_KING \"\\xef\\x90\\xbf\"\t// U+f43f\n#define ICON_FA_CHESS_KNIGHT \"\\xef\\x91\\x81\"\t// U+f441\n#define ICON_FA_CHESS_PAWN \"\\xef\\x91\\x83\"\t// U+f443\n#define ICON_FA_CHESS_QUEEN \"\\xef\\x91\\x85\"\t// U+f445\n#define ICON_FA_CHESS_ROOK \"\\xef\\x91\\x87\"\t// U+f447\n#define ICON_FA_CHEVRON_CIRCLE_DOWN \"\\xef\\x84\\xba\"\t// U+f13a\n#define ICON_FA_CHEVRON_CIRCLE_LEFT \"\\xef\\x84\\xb7\"\t// U+f137\n#define ICON_FA_CHEVRON_CIRCLE_RIGHT \"\\xef\\x84\\xb8\"\t// U+f138\n#define ICON_FA_CHEVRON_CIRCLE_UP \"\\xef\\x84\\xb9\"\t// U+f139\n#define ICON_FA_CHEVRON_DOWN \"\\xef\\x81\\xb8\"\t// U+f078\n#define ICON_FA_CHEVRON_LEFT \"\\xef\\x81\\x93\"\t// U+f053\n#define ICON_FA_CHEVRON_RIGHT \"\\xef\\x81\\x94\"\t// U+f054\n#define ICON_FA_CHEVRON_UP \"\\xef\\x81\\xb7\"\t// U+f077\n#define ICON_FA_CHILD \"\\xef\\x86\\xae\"\t// U+f1ae\n#define ICON_FA_CHURCH \"\\xef\\x94\\x9d\"\t// U+f51d\n#define ICON_FA_CIRCLE \"\\xef\\x84\\x91\"\t// U+f111\n#define ICON_FA_CIRCLE_NOTCH \"\\xef\\x87\\x8e\"\t// U+f1ce\n#define ICON_FA_CITY \"\\xef\\x99\\x8f\"\t// U+f64f\n#define ICON_FA_CLINIC_MEDICAL \"\\xef\\x9f\\xb2\"\t// U+f7f2\n#define ICON_FA_CLIPBOARD \"\\xef\\x8c\\xa8\"\t// U+f328\n#define ICON_FA_CLIPBOARD_CHECK \"\\xef\\x91\\xac\"\t// U+f46c\n#define ICON_FA_CLIPBOARD_LIST \"\\xef\\x91\\xad\"\t// U+f46d\n#define ICON_FA_CLOCK \"\\xef\\x80\\x97\"\t// U+f017\n#define ICON_FA_CLONE \"\\xef\\x89\\x8d\"\t// U+f24d\n#define ICON_FA_CLOSED_CAPTIONING \"\\xef\\x88\\x8a\"\t// U+f20a\n#define ICON_FA_CLOUD \"\\xef\\x83\\x82\"\t// U+f0c2\n#define ICON_FA_CLOUD_DOWNLOAD_ALT \"\\xef\\x8e\\x81\"\t// U+f381\n#define ICON_FA_CLOUD_MEATBALL \"\\xef\\x9c\\xbb\"\t// U+f73b\n#define ICON_FA_CLOUD_MOON \"\\xef\\x9b\\x83\"\t// U+f6c3\n#define ICON_FA_CLOUD_MOON_RAIN \"\\xef\\x9c\\xbc\"\t// U+f73c\n#define ICON_FA_CLOUD_RAIN \"\\xef\\x9c\\xbd\"\t// U+f73d\n#define ICON_FA_CLOUD_SHOWERS_HEAVY \"\\xef\\x9d\\x80\"\t// U+f740\n#define ICON_FA_CLOUD_SUN \"\\xef\\x9b\\x84\"\t// U+f6c4\n#define ICON_FA_CLOUD_SUN_RAIN \"\\xef\\x9d\\x83\"\t// U+f743\n#define ICON_FA_CLOUD_UPLOAD_ALT \"\\xef\\x8e\\x82\"\t// U+f382\n#define ICON_FA_COCKTAIL \"\\xef\\x95\\xa1\"\t// U+f561\n#define ICON_FA_CODE \"\\xef\\x84\\xa1\"\t// U+f121\n#define ICON_FA_CODE_BRANCH \"\\xef\\x84\\xa6\"\t// U+f126\n#define ICON_FA_COFFEE \"\\xef\\x83\\xb4\"\t// U+f0f4\n#define ICON_FA_COG \"\\xef\\x80\\x93\"\t// U+f013\n#define ICON_FA_COGS \"\\xef\\x82\\x85\"\t// U+f085\n#define ICON_FA_COINS \"\\xef\\x94\\x9e\"\t// U+f51e\n#define ICON_FA_COLUMNS \"\\xef\\x83\\x9b\"\t// U+f0db\n#define ICON_FA_COMMENT \"\\xef\\x81\\xb5\"\t// U+f075\n#define ICON_FA_COMMENT_ALT \"\\xef\\x89\\xba\"\t// U+f27a\n#define ICON_FA_COMMENT_DOLLAR \"\\xef\\x99\\x91\"\t// U+f651\n#define ICON_FA_COMMENT_DOTS \"\\xef\\x92\\xad\"\t// U+f4ad\n#define ICON_FA_COMMENT_MEDICAL \"\\xef\\x9f\\xb5\"\t// U+f7f5\n#define ICON_FA_COMMENT_SLASH \"\\xef\\x92\\xb3\"\t// U+f4b3\n#define ICON_FA_COMMENTS \"\\xef\\x82\\x86\"\t// U+f086\n#define ICON_FA_COMMENTS_DOLLAR \"\\xef\\x99\\x93\"\t// U+f653\n#define ICON_FA_COMPACT_DISC \"\\xef\\x94\\x9f\"\t// U+f51f\n#define ICON_FA_COMPASS \"\\xef\\x85\\x8e\"\t// U+f14e\n#define ICON_FA_COMPRESS \"\\xef\\x81\\xa6\"\t// U+f066\n#define ICON_FA_COMPRESS_ALT \"\\xef\\x90\\xa2\"\t// U+f422\n#define ICON_FA_COMPRESS_ARROWS_ALT \"\\xef\\x9e\\x8c\"\t// U+f78c\n#define ICON_FA_CONCIERGE_BELL \"\\xef\\x95\\xa2\"\t// U+f562\n#define ICON_FA_COOKIE \"\\xef\\x95\\xa3\"\t// U+f563\n#define ICON_FA_COOKIE_BITE \"\\xef\\x95\\xa4\"\t// U+f564\n#define ICON_FA_COPY \"\\xef\\x83\\x85\"\t// U+f0c5\n#define ICON_FA_COPYRIGHT \"\\xef\\x87\\xb9\"\t// U+f1f9\n#define ICON_FA_COUCH \"\\xef\\x92\\xb8\"\t// U+f4b8\n#define ICON_FA_CREDIT_CARD \"\\xef\\x82\\x9d\"\t// U+f09d\n#define ICON_FA_CROP \"\\xef\\x84\\xa5\"\t// U+f125\n#define ICON_FA_CROP_ALT \"\\xef\\x95\\xa5\"\t// U+f565\n#define ICON_FA_CROSS \"\\xef\\x99\\x94\"\t// U+f654\n#define ICON_FA_CROSSHAIRS \"\\xef\\x81\\x9b\"\t// U+f05b\n#define ICON_FA_CROW \"\\xef\\x94\\xa0\"\t// U+f520\n#define ICON_FA_CROWN \"\\xef\\x94\\xa1\"\t// U+f521\n#define ICON_FA_CRUTCH \"\\xef\\x9f\\xb7\"\t// U+f7f7\n#define ICON_FA_CUBE \"\\xef\\x86\\xb2\"\t// U+f1b2\n#define ICON_FA_CUBES \"\\xef\\x86\\xb3\"\t// U+f1b3\n#define ICON_FA_CUT \"\\xef\\x83\\x84\"\t// U+f0c4\n#define ICON_FA_DATABASE \"\\xef\\x87\\x80\"\t// U+f1c0\n#define ICON_FA_DEAF \"\\xef\\x8a\\xa4\"\t// U+f2a4\n#define ICON_FA_DEMOCRAT \"\\xef\\x9d\\x87\"\t// U+f747\n#define ICON_FA_DESKTOP \"\\xef\\x84\\x88\"\t// U+f108\n#define ICON_FA_DHARMACHAKRA \"\\xef\\x99\\x95\"\t// U+f655\n#define ICON_FA_DIAGNOSES \"\\xef\\x91\\xb0\"\t// U+f470\n#define ICON_FA_DICE \"\\xef\\x94\\xa2\"\t// U+f522\n#define ICON_FA_DICE_D20 \"\\xef\\x9b\\x8f\"\t// U+f6cf\n#define ICON_FA_DICE_D6 \"\\xef\\x9b\\x91\"\t// U+f6d1\n#define ICON_FA_DICE_FIVE \"\\xef\\x94\\xa3\"\t// U+f523\n#define ICON_FA_DICE_FOUR \"\\xef\\x94\\xa4\"\t// U+f524\n#define ICON_FA_DICE_ONE \"\\xef\\x94\\xa5\"\t// U+f525\n#define ICON_FA_DICE_SIX \"\\xef\\x94\\xa6\"\t// U+f526\n#define ICON_FA_DICE_THREE \"\\xef\\x94\\xa7\"\t// U+f527\n#define ICON_FA_DICE_TWO \"\\xef\\x94\\xa8\"\t// U+f528\n#define ICON_FA_DIGITAL_TACHOGRAPH \"\\xef\\x95\\xa6\"\t// U+f566\n#define ICON_FA_DIRECTIONS \"\\xef\\x97\\xab\"\t// U+f5eb\n#define ICON_FA_DISEASE \"\\xef\\x9f\\xba\"\t// U+f7fa\n#define ICON_FA_DIVIDE \"\\xef\\x94\\xa9\"\t// U+f529\n#define ICON_FA_DIZZY \"\\xef\\x95\\xa7\"\t// U+f567\n#define ICON_FA_DNA \"\\xef\\x91\\xb1\"\t// U+f471\n#define ICON_FA_DOG \"\\xef\\x9b\\x93\"\t// U+f6d3\n#define ICON_FA_DOLLAR_SIGN \"\\xef\\x85\\x95\"\t// U+f155\n#define ICON_FA_DOLLY \"\\xef\\x91\\xb2\"\t// U+f472\n#define ICON_FA_DOLLY_FLATBED \"\\xef\\x91\\xb4\"\t// U+f474\n#define ICON_FA_DONATE \"\\xef\\x92\\xb9\"\t// U+f4b9\n#define ICON_FA_DOOR_CLOSED \"\\xef\\x94\\xaa\"\t// U+f52a\n#define ICON_FA_DOOR_OPEN \"\\xef\\x94\\xab\"\t// U+f52b\n#define ICON_FA_DOT_CIRCLE \"\\xef\\x86\\x92\"\t// U+f192\n#define ICON_FA_DOVE \"\\xef\\x92\\xba\"\t// U+f4ba\n#define ICON_FA_DOWNLOAD \"\\xef\\x80\\x99\"\t// U+f019\n#define ICON_FA_DRAFTING_COMPASS \"\\xef\\x95\\xa8\"\t// U+f568\n#define ICON_FA_DRAGON \"\\xef\\x9b\\x95\"\t// U+f6d5\n#define ICON_FA_DRAW_POLYGON \"\\xef\\x97\\xae\"\t// U+f5ee\n#define ICON_FA_DRUM \"\\xef\\x95\\xa9\"\t// U+f569\n#define ICON_FA_DRUM_STEELPAN \"\\xef\\x95\\xaa\"\t// U+f56a\n#define ICON_FA_DRUMSTICK_BITE \"\\xef\\x9b\\x97\"\t// U+f6d7\n#define ICON_FA_DUMBBELL \"\\xef\\x91\\x8b\"\t// U+f44b\n#define ICON_FA_DUMPSTER \"\\xef\\x9e\\x93\"\t// U+f793\n#define ICON_FA_DUMPSTER_FIRE \"\\xef\\x9e\\x94\"\t// U+f794\n#define ICON_FA_DUNGEON \"\\xef\\x9b\\x99\"\t// U+f6d9\n#define ICON_FA_EDIT \"\\xef\\x81\\x84\"\t// U+f044\n#define ICON_FA_EGG \"\\xef\\x9f\\xbb\"\t// U+f7fb\n#define ICON_FA_EJECT \"\\xef\\x81\\x92\"\t// U+f052\n#define ICON_FA_ELLIPSIS_H \"\\xef\\x85\\x81\"\t// U+f141\n#define ICON_FA_ELLIPSIS_V \"\\xef\\x85\\x82\"\t// U+f142\n#define ICON_FA_ENVELOPE \"\\xef\\x83\\xa0\"\t// U+f0e0\n#define ICON_FA_ENVELOPE_OPEN \"\\xef\\x8a\\xb6\"\t// U+f2b6\n#define ICON_FA_ENVELOPE_OPEN_TEXT \"\\xef\\x99\\x98\"\t// U+f658\n#define ICON_FA_ENVELOPE_SQUARE \"\\xef\\x86\\x99\"\t// U+f199\n#define ICON_FA_EQUALS \"\\xef\\x94\\xac\"\t// U+f52c\n#define ICON_FA_ERASER \"\\xef\\x84\\xad\"\t// U+f12d\n#define ICON_FA_ETHERNET \"\\xef\\x9e\\x96\"\t// U+f796\n#define ICON_FA_EURO_SIGN \"\\xef\\x85\\x93\"\t// U+f153\n#define ICON_FA_EXCHANGE_ALT \"\\xef\\x8d\\xa2\"\t// U+f362\n#define ICON_FA_EXCLAMATION \"\\xef\\x84\\xaa\"\t// U+f12a\n#define ICON_FA_EXCLAMATION_CIRCLE \"\\xef\\x81\\xaa\"\t// U+f06a\n#define ICON_FA_EXCLAMATION_TRIANGLE \"\\xef\\x81\\xb1\"\t// U+f071\n#define ICON_FA_EXPAND \"\\xef\\x81\\xa5\"\t// U+f065\n#define ICON_FA_EXPAND_ALT \"\\xef\\x90\\xa4\"\t// U+f424\n#define ICON_FA_EXPAND_ARROWS_ALT \"\\xef\\x8c\\x9e\"\t// U+f31e\n#define ICON_FA_EXTERNAL_LINK_ALT \"\\xef\\x8d\\x9d\"\t// U+f35d\n#define ICON_FA_EXTERNAL_LINK_SQUARE_ALT \"\\xef\\x8d\\xa0\"\t// U+f360\n#define ICON_FA_EYE \"\\xef\\x81\\xae\"\t// U+f06e\n#define ICON_FA_EYE_DROPPER \"\\xef\\x87\\xbb\"\t// U+f1fb\n#define ICON_FA_EYE_SLASH \"\\xef\\x81\\xb0\"\t// U+f070\n#define ICON_FA_FAN \"\\xef\\xa1\\xa3\"\t// U+f863\n#define ICON_FA_FAST_BACKWARD \"\\xef\\x81\\x89\"\t// U+f049\n#define ICON_FA_FAST_FORWARD \"\\xef\\x81\\x90\"\t// U+f050\n#define ICON_FA_FAUCET \"\\xee\\x80\\x85\"\t// U+e005\n#define ICON_FA_FAX \"\\xef\\x86\\xac\"\t// U+f1ac\n#define ICON_FA_FEATHER \"\\xef\\x94\\xad\"\t// U+f52d\n#define ICON_FA_FEATHER_ALT \"\\xef\\x95\\xab\"\t// U+f56b\n#define ICON_FA_FEMALE \"\\xef\\x86\\x82\"\t// U+f182\n#define ICON_FA_FIGHTER_JET \"\\xef\\x83\\xbb\"\t// U+f0fb\n#define ICON_FA_FILE \"\\xef\\x85\\x9b\"\t// U+f15b\n#define ICON_FA_FILE_ALT \"\\xef\\x85\\x9c\"\t// U+f15c\n#define ICON_FA_FILE_ARCHIVE \"\\xef\\x87\\x86\"\t// U+f1c6\n#define ICON_FA_FILE_AUDIO \"\\xef\\x87\\x87\"\t// U+f1c7\n#define ICON_FA_FILE_CODE \"\\xef\\x87\\x89\"\t// U+f1c9\n#define ICON_FA_FILE_CONTRACT \"\\xef\\x95\\xac\"\t// U+f56c\n#define ICON_FA_FILE_CSV \"\\xef\\x9b\\x9d\"\t// U+f6dd\n#define ICON_FA_FILE_DOWNLOAD \"\\xef\\x95\\xad\"\t// U+f56d\n#define ICON_FA_FILE_EXCEL \"\\xef\\x87\\x83\"\t// U+f1c3\n#define ICON_FA_FILE_EXPORT \"\\xef\\x95\\xae\"\t// U+f56e\n#define ICON_FA_FILE_IMAGE \"\\xef\\x87\\x85\"\t// U+f1c5\n#define ICON_FA_FILE_IMPORT \"\\xef\\x95\\xaf\"\t// U+f56f\n#define ICON_FA_FILE_INVOICE \"\\xef\\x95\\xb0\"\t// U+f570\n#define ICON_FA_FILE_INVOICE_DOLLAR \"\\xef\\x95\\xb1\"\t// U+f571\n#define ICON_FA_FILE_MEDICAL \"\\xef\\x91\\xb7\"\t// U+f477\n#define ICON_FA_FILE_MEDICAL_ALT \"\\xef\\x91\\xb8\"\t// U+f478\n#define ICON_FA_FILE_PDF \"\\xef\\x87\\x81\"\t// U+f1c1\n#define ICON_FA_FILE_POWERPOINT \"\\xef\\x87\\x84\"\t// U+f1c4\n#define ICON_FA_FILE_PRESCRIPTION \"\\xef\\x95\\xb2\"\t// U+f572\n#define ICON_FA_FILE_SIGNATURE \"\\xef\\x95\\xb3\"\t// U+f573\n#define ICON_FA_FILE_UPLOAD \"\\xef\\x95\\xb4\"\t// U+f574\n#define ICON_FA_FILE_VIDEO \"\\xef\\x87\\x88\"\t// U+f1c8\n#define ICON_FA_FILE_WORD \"\\xef\\x87\\x82\"\t// U+f1c2\n#define ICON_FA_FILL \"\\xef\\x95\\xb5\"\t// U+f575\n#define ICON_FA_FILL_DRIP \"\\xef\\x95\\xb6\"\t// U+f576\n#define ICON_FA_FILM \"\\xef\\x80\\x88\"\t// U+f008\n#define ICON_FA_FILTER \"\\xef\\x82\\xb0\"\t// U+f0b0\n#define ICON_FA_FINGERPRINT \"\\xef\\x95\\xb7\"\t// U+f577\n#define ICON_FA_FIRE \"\\xef\\x81\\xad\"\t// U+f06d\n#define ICON_FA_FIRE_ALT \"\\xef\\x9f\\xa4\"\t// U+f7e4\n#define ICON_FA_FIRE_EXTINGUISHER \"\\xef\\x84\\xb4\"\t// U+f134\n#define ICON_FA_FIRST_AID \"\\xef\\x91\\xb9\"\t// U+f479\n#define ICON_FA_FISH \"\\xef\\x95\\xb8\"\t// U+f578\n#define ICON_FA_FIST_RAISED \"\\xef\\x9b\\x9e\"\t// U+f6de\n#define ICON_FA_FLAG \"\\xef\\x80\\xa4\"\t// U+f024\n#define ICON_FA_FLAG_CHECKERED \"\\xef\\x84\\x9e\"\t// U+f11e\n#define ICON_FA_FLAG_USA \"\\xef\\x9d\\x8d\"\t// U+f74d\n#define ICON_FA_FLASK \"\\xef\\x83\\x83\"\t// U+f0c3\n#define ICON_FA_FLUSHED \"\\xef\\x95\\xb9\"\t// U+f579\n#define ICON_FA_FOLDER \"\\xef\\x81\\xbb\"\t// U+f07b\n#define ICON_FA_FOLDER_MINUS \"\\xef\\x99\\x9d\"\t// U+f65d\n#define ICON_FA_FOLDER_OPEN \"\\xef\\x81\\xbc\"\t// U+f07c\n#define ICON_FA_FOLDER_PLUS \"\\xef\\x99\\x9e\"\t// U+f65e\n#define ICON_FA_FONT \"\\xef\\x80\\xb1\"\t// U+f031\n#define ICON_FA_FONT_AWESOME_LOGO_FULL \"\\xef\\x93\\xa6\"\t// U+f4e6\n#define ICON_FA_FOOTBALL_BALL \"\\xef\\x91\\x8e\"\t// U+f44e\n#define ICON_FA_FORWARD \"\\xef\\x81\\x8e\"\t// U+f04e\n#define ICON_FA_FROG \"\\xef\\x94\\xae\"\t// U+f52e\n#define ICON_FA_FROWN \"\\xef\\x84\\x99\"\t// U+f119\n#define ICON_FA_FROWN_OPEN \"\\xef\\x95\\xba\"\t// U+f57a\n#define ICON_FA_FUNNEL_DOLLAR \"\\xef\\x99\\xa2\"\t// U+f662\n#define ICON_FA_FUTBOL \"\\xef\\x87\\xa3\"\t// U+f1e3\n#define ICON_FA_GAMEPAD \"\\xef\\x84\\x9b\"\t// U+f11b\n#define ICON_FA_GAS_PUMP \"\\xef\\x94\\xaf\"\t// U+f52f\n#define ICON_FA_GAVEL \"\\xef\\x83\\xa3\"\t// U+f0e3\n#define ICON_FA_GEM \"\\xef\\x8e\\xa5\"\t// U+f3a5\n#define ICON_FA_GENDERLESS \"\\xef\\x88\\xad\"\t// U+f22d\n#define ICON_FA_GHOST \"\\xef\\x9b\\xa2\"\t// U+f6e2\n#define ICON_FA_GIFT \"\\xef\\x81\\xab\"\t// U+f06b\n#define ICON_FA_GIFTS \"\\xef\\x9e\\x9c\"\t// U+f79c\n#define ICON_FA_GLASS_CHEERS \"\\xef\\x9e\\x9f\"\t// U+f79f\n#define ICON_FA_GLASS_MARTINI \"\\xef\\x80\\x80\"\t// U+f000\n#define ICON_FA_GLASS_MARTINI_ALT \"\\xef\\x95\\xbb\"\t// U+f57b\n#define ICON_FA_GLASS_WHISKEY \"\\xef\\x9e\\xa0\"\t// U+f7a0\n#define ICON_FA_GLASSES \"\\xef\\x94\\xb0\"\t// U+f530\n#define ICON_FA_GLOBE \"\\xef\\x82\\xac\"\t// U+f0ac\n#define ICON_FA_GLOBE_AFRICA \"\\xef\\x95\\xbc\"\t// U+f57c\n#define ICON_FA_GLOBE_AMERICAS \"\\xef\\x95\\xbd\"\t// U+f57d\n#define ICON_FA_GLOBE_ASIA \"\\xef\\x95\\xbe\"\t// U+f57e\n#define ICON_FA_GLOBE_EUROPE \"\\xef\\x9e\\xa2\"\t// U+f7a2\n#define ICON_FA_GOLF_BALL \"\\xef\\x91\\x90\"\t// U+f450\n#define ICON_FA_GOPURAM \"\\xef\\x99\\xa4\"\t// U+f664\n#define ICON_FA_GRADUATION_CAP \"\\xef\\x86\\x9d\"\t// U+f19d\n#define ICON_FA_GREATER_THAN \"\\xef\\x94\\xb1\"\t// U+f531\n#define ICON_FA_GREATER_THAN_EQUAL \"\\xef\\x94\\xb2\"\t// U+f532\n#define ICON_FA_GRIMACE \"\\xef\\x95\\xbf\"\t// U+f57f\n#define ICON_FA_GRIN \"\\xef\\x96\\x80\"\t// U+f580\n#define ICON_FA_GRIN_ALT \"\\xef\\x96\\x81\"\t// U+f581\n#define ICON_FA_GRIN_BEAM \"\\xef\\x96\\x82\"\t// U+f582\n#define ICON_FA_GRIN_BEAM_SWEAT \"\\xef\\x96\\x83\"\t// U+f583\n#define ICON_FA_GRIN_HEARTS \"\\xef\\x96\\x84\"\t// U+f584\n#define ICON_FA_GRIN_SQUINT \"\\xef\\x96\\x85\"\t// U+f585\n#define ICON_FA_GRIN_SQUINT_TEARS \"\\xef\\x96\\x86\"\t// U+f586\n#define ICON_FA_GRIN_STARS \"\\xef\\x96\\x87\"\t// U+f587\n#define ICON_FA_GRIN_TEARS \"\\xef\\x96\\x88\"\t// U+f588\n#define ICON_FA_GRIN_TONGUE \"\\xef\\x96\\x89\"\t// U+f589\n#define ICON_FA_GRIN_TONGUE_SQUINT \"\\xef\\x96\\x8a\"\t// U+f58a\n#define ICON_FA_GRIN_TONGUE_WINK \"\\xef\\x96\\x8b\"\t// U+f58b\n#define ICON_FA_GRIN_WINK \"\\xef\\x96\\x8c\"\t// U+f58c\n#define ICON_FA_GRIP_HORIZONTAL \"\\xef\\x96\\x8d\"\t// U+f58d\n#define ICON_FA_GRIP_LINES \"\\xef\\x9e\\xa4\"\t// U+f7a4\n#define ICON_FA_GRIP_LINES_VERTICAL \"\\xef\\x9e\\xa5\"\t// U+f7a5\n#define ICON_FA_GRIP_VERTICAL \"\\xef\\x96\\x8e\"\t// U+f58e\n#define ICON_FA_GUITAR \"\\xef\\x9e\\xa6\"\t// U+f7a6\n#define ICON_FA_H_SQUARE \"\\xef\\x83\\xbd\"\t// U+f0fd\n#define ICON_FA_HAMBURGER \"\\xef\\xa0\\x85\"\t// U+f805\n#define ICON_FA_HAMMER \"\\xef\\x9b\\xa3\"\t// U+f6e3\n#define ICON_FA_HAMSA \"\\xef\\x99\\xa5\"\t// U+f665\n#define ICON_FA_HAND_HOLDING \"\\xef\\x92\\xbd\"\t// U+f4bd\n#define ICON_FA_HAND_HOLDING_HEART \"\\xef\\x92\\xbe\"\t// U+f4be\n#define ICON_FA_HAND_HOLDING_MEDICAL \"\\xee\\x81\\x9c\"\t// U+e05c\n#define ICON_FA_HAND_HOLDING_USD \"\\xef\\x93\\x80\"\t// U+f4c0\n#define ICON_FA_HAND_HOLDING_WATER \"\\xef\\x93\\x81\"\t// U+f4c1\n#define ICON_FA_HAND_LIZARD \"\\xef\\x89\\x98\"\t// U+f258\n#define ICON_FA_HAND_MIDDLE_FINGER \"\\xef\\xa0\\x86\"\t// U+f806\n#define ICON_FA_HAND_PAPER \"\\xef\\x89\\x96\"\t// U+f256\n#define ICON_FA_HAND_PEACE \"\\xef\\x89\\x9b\"\t// U+f25b\n#define ICON_FA_HAND_POINT_DOWN \"\\xef\\x82\\xa7\"\t// U+f0a7\n#define ICON_FA_HAND_POINT_LEFT \"\\xef\\x82\\xa5\"\t// U+f0a5\n#define ICON_FA_HAND_POINT_RIGHT \"\\xef\\x82\\xa4\"\t// U+f0a4\n#define ICON_FA_HAND_POINT_UP \"\\xef\\x82\\xa6\"\t// U+f0a6\n#define ICON_FA_HAND_POINTER \"\\xef\\x89\\x9a\"\t// U+f25a\n#define ICON_FA_HAND_ROCK \"\\xef\\x89\\x95\"\t// U+f255\n#define ICON_FA_HAND_SCISSORS \"\\xef\\x89\\x97\"\t// U+f257\n#define ICON_FA_HAND_SPARKLES \"\\xee\\x81\\x9d\"\t// U+e05d\n#define ICON_FA_HAND_SPOCK \"\\xef\\x89\\x99\"\t// U+f259\n#define ICON_FA_HANDS \"\\xef\\x93\\x82\"\t// U+f4c2\n#define ICON_FA_HANDS_HELPING \"\\xef\\x93\\x84\"\t// U+f4c4\n#define ICON_FA_HANDS_WASH \"\\xee\\x81\\x9e\"\t// U+e05e\n#define ICON_FA_HANDSHAKE \"\\xef\\x8a\\xb5\"\t// U+f2b5\n#define ICON_FA_HANDSHAKE_ALT_SLASH \"\\xee\\x81\\x9f\"\t// U+e05f\n#define ICON_FA_HANDSHAKE_SLASH \"\\xee\\x81\\xa0\"\t// U+e060\n#define ICON_FA_HANUKIAH \"\\xef\\x9b\\xa6\"\t// U+f6e6\n#define ICON_FA_HARD_HAT \"\\xef\\xa0\\x87\"\t// U+f807\n#define ICON_FA_HASHTAG \"\\xef\\x8a\\x92\"\t// U+f292\n#define ICON_FA_HAT_COWBOY \"\\xef\\xa3\\x80\"\t// U+f8c0\n#define ICON_FA_HAT_COWBOY_SIDE \"\\xef\\xa3\\x81\"\t// U+f8c1\n#define ICON_FA_HAT_WIZARD \"\\xef\\x9b\\xa8\"\t// U+f6e8\n#define ICON_FA_HDD \"\\xef\\x82\\xa0\"\t// U+f0a0\n#define ICON_FA_HEAD_SIDE_COUGH \"\\xee\\x81\\xa1\"\t// U+e061\n#define ICON_FA_HEAD_SIDE_COUGH_SLASH \"\\xee\\x81\\xa2\"\t// U+e062\n#define ICON_FA_HEAD_SIDE_MASK \"\\xee\\x81\\xa3\"\t// U+e063\n#define ICON_FA_HEAD_SIDE_VIRUS \"\\xee\\x81\\xa4\"\t// U+e064\n#define ICON_FA_HEADING \"\\xef\\x87\\x9c\"\t// U+f1dc\n#define ICON_FA_HEADPHONES \"\\xef\\x80\\xa5\"\t// U+f025\n#define ICON_FA_HEADPHONES_ALT \"\\xef\\x96\\x8f\"\t// U+f58f\n#define ICON_FA_HEADSET \"\\xef\\x96\\x90\"\t// U+f590\n#define ICON_FA_HEART \"\\xef\\x80\\x84\"\t// U+f004\n#define ICON_FA_HEART_BROKEN \"\\xef\\x9e\\xa9\"\t// U+f7a9\n#define ICON_FA_HEARTBEAT \"\\xef\\x88\\x9e\"\t// U+f21e\n#define ICON_FA_HELICOPTER \"\\xef\\x94\\xb3\"\t// U+f533\n#define ICON_FA_HIGHLIGHTER \"\\xef\\x96\\x91\"\t// U+f591\n#define ICON_FA_HIKING \"\\xef\\x9b\\xac\"\t// U+f6ec\n#define ICON_FA_HIPPO \"\\xef\\x9b\\xad\"\t// U+f6ed\n#define ICON_FA_HISTORY \"\\xef\\x87\\x9a\"\t// U+f1da\n#define ICON_FA_HOCKEY_PUCK \"\\xef\\x91\\x93\"\t// U+f453\n#define ICON_FA_HOLLY_BERRY \"\\xef\\x9e\\xaa\"\t// U+f7aa\n#define ICON_FA_HOME \"\\xef\\x80\\x95\"\t// U+f015\n#define ICON_FA_HORSE \"\\xef\\x9b\\xb0\"\t// U+f6f0\n#define ICON_FA_HORSE_HEAD \"\\xef\\x9e\\xab\"\t// U+f7ab\n#define ICON_FA_HOSPITAL \"\\xef\\x83\\xb8\"\t// U+f0f8\n#define ICON_FA_HOSPITAL_ALT \"\\xef\\x91\\xbd\"\t// U+f47d\n#define ICON_FA_HOSPITAL_SYMBOL \"\\xef\\x91\\xbe\"\t// U+f47e\n#define ICON_FA_HOSPITAL_USER \"\\xef\\xa0\\x8d\"\t// U+f80d\n#define ICON_FA_HOT_TUB \"\\xef\\x96\\x93\"\t// U+f593\n#define ICON_FA_HOTDOG \"\\xef\\xa0\\x8f\"\t// U+f80f\n#define ICON_FA_HOTEL \"\\xef\\x96\\x94\"\t// U+f594\n#define ICON_FA_HOURGLASS \"\\xef\\x89\\x94\"\t// U+f254\n#define ICON_FA_HOURGLASS_END \"\\xef\\x89\\x93\"\t// U+f253\n#define ICON_FA_HOURGLASS_HALF \"\\xef\\x89\\x92\"\t// U+f252\n#define ICON_FA_HOURGLASS_START \"\\xef\\x89\\x91\"\t// U+f251\n#define ICON_FA_HOUSE_DAMAGE \"\\xef\\x9b\\xb1\"\t// U+f6f1\n#define ICON_FA_HOUSE_USER \"\\xee\\x81\\xa5\"\t// U+e065\n#define ICON_FA_HRYVNIA \"\\xef\\x9b\\xb2\"\t// U+f6f2\n#define ICON_FA_I_CURSOR \"\\xef\\x89\\x86\"\t// U+f246\n#define ICON_FA_ICE_CREAM \"\\xef\\xa0\\x90\"\t// U+f810\n#define ICON_FA_ICICLES \"\\xef\\x9e\\xad\"\t// U+f7ad\n#define ICON_FA_ICONS \"\\xef\\xa1\\xad\"\t// U+f86d\n#define ICON_FA_ID_BADGE \"\\xef\\x8b\\x81\"\t// U+f2c1\n#define ICON_FA_ID_CARD \"\\xef\\x8b\\x82\"\t// U+f2c2\n#define ICON_FA_ID_CARD_ALT \"\\xef\\x91\\xbf\"\t// U+f47f\n#define ICON_FA_IGLOO \"\\xef\\x9e\\xae\"\t// U+f7ae\n#define ICON_FA_IMAGE \"\\xef\\x80\\xbe\"\t// U+f03e\n#define ICON_FA_IMAGES \"\\xef\\x8c\\x82\"\t// U+f302\n#define ICON_FA_INBOX \"\\xef\\x80\\x9c\"\t// U+f01c\n#define ICON_FA_INDENT \"\\xef\\x80\\xbc\"\t// U+f03c\n#define ICON_FA_INDUSTRY \"\\xef\\x89\\xb5\"\t// U+f275\n#define ICON_FA_INFINITY \"\\xef\\x94\\xb4\"\t// U+f534\n#define ICON_FA_INFO \"\\xef\\x84\\xa9\"\t// U+f129\n#define ICON_FA_INFO_CIRCLE \"\\xef\\x81\\x9a\"\t// U+f05a\n#define ICON_FA_ITALIC \"\\xef\\x80\\xb3\"\t// U+f033\n#define ICON_FA_JEDI \"\\xef\\x99\\xa9\"\t// U+f669\n#define ICON_FA_JOINT \"\\xef\\x96\\x95\"\t// U+f595\n#define ICON_FA_JOURNAL_WHILLS \"\\xef\\x99\\xaa\"\t// U+f66a\n#define ICON_FA_KAABA \"\\xef\\x99\\xab\"\t// U+f66b\n#define ICON_FA_KEY \"\\xef\\x82\\x84\"\t// U+f084\n#define ICON_FA_KEYBOARD \"\\xef\\x84\\x9c\"\t// U+f11c\n#define ICON_FA_KHANDA \"\\xef\\x99\\xad\"\t// U+f66d\n#define ICON_FA_KISS \"\\xef\\x96\\x96\"\t// U+f596\n#define ICON_FA_KISS_BEAM \"\\xef\\x96\\x97\"\t// U+f597\n#define ICON_FA_KISS_WINK_HEART \"\\xef\\x96\\x98\"\t// U+f598\n#define ICON_FA_KIWI_BIRD \"\\xef\\x94\\xb5\"\t// U+f535\n#define ICON_FA_LANDMARK \"\\xef\\x99\\xaf\"\t// U+f66f\n#define ICON_FA_LANGUAGE \"\\xef\\x86\\xab\"\t// U+f1ab\n#define ICON_FA_LAPTOP \"\\xef\\x84\\x89\"\t// U+f109\n#define ICON_FA_LAPTOP_CODE \"\\xef\\x97\\xbc\"\t// U+f5fc\n#define ICON_FA_LAPTOP_HOUSE \"\\xee\\x81\\xa6\"\t// U+e066\n#define ICON_FA_LAPTOP_MEDICAL \"\\xef\\xa0\\x92\"\t// U+f812\n#define ICON_FA_LAUGH \"\\xef\\x96\\x99\"\t// U+f599\n#define ICON_FA_LAUGH_BEAM \"\\xef\\x96\\x9a\"\t// U+f59a\n#define ICON_FA_LAUGH_SQUINT \"\\xef\\x96\\x9b\"\t// U+f59b\n#define ICON_FA_LAUGH_WINK \"\\xef\\x96\\x9c\"\t// U+f59c\n#define ICON_FA_LAYER_GROUP \"\\xef\\x97\\xbd\"\t// U+f5fd\n#define ICON_FA_LEAF \"\\xef\\x81\\xac\"\t// U+f06c\n#define ICON_FA_LEMON \"\\xef\\x82\\x94\"\t// U+f094\n#define ICON_FA_LESS_THAN \"\\xef\\x94\\xb6\"\t// U+f536\n#define ICON_FA_LESS_THAN_EQUAL \"\\xef\\x94\\xb7\"\t// U+f537\n#define ICON_FA_LEVEL_DOWN_ALT \"\\xef\\x8e\\xbe\"\t// U+f3be\n#define ICON_FA_LEVEL_UP_ALT \"\\xef\\x8e\\xbf\"\t// U+f3bf\n#define ICON_FA_LIFE_RING \"\\xef\\x87\\x8d\"\t// U+f1cd\n#define ICON_FA_LIGHTBULB \"\\xef\\x83\\xab\"\t// U+f0eb\n#define ICON_FA_LINK \"\\xef\\x83\\x81\"\t// U+f0c1\n#define ICON_FA_LIRA_SIGN \"\\xef\\x86\\x95\"\t// U+f195\n#define ICON_FA_LIST \"\\xef\\x80\\xba\"\t// U+f03a\n#define ICON_FA_LIST_ALT \"\\xef\\x80\\xa2\"\t// U+f022\n#define ICON_FA_LIST_OL \"\\xef\\x83\\x8b\"\t// U+f0cb\n#define ICON_FA_LIST_UL \"\\xef\\x83\\x8a\"\t// U+f0ca\n#define ICON_FA_LOCATION_ARROW \"\\xef\\x84\\xa4\"\t// U+f124\n#define ICON_FA_LOCK \"\\xef\\x80\\xa3\"\t// U+f023\n#define ICON_FA_LOCK_OPEN \"\\xef\\x8f\\x81\"\t// U+f3c1\n#define ICON_FA_LONG_ARROW_ALT_DOWN \"\\xef\\x8c\\x89\"\t// U+f309\n#define ICON_FA_LONG_ARROW_ALT_LEFT \"\\xef\\x8c\\x8a\"\t// U+f30a\n#define ICON_FA_LONG_ARROW_ALT_RIGHT \"\\xef\\x8c\\x8b\"\t// U+f30b\n#define ICON_FA_LONG_ARROW_ALT_UP \"\\xef\\x8c\\x8c\"\t// U+f30c\n#define ICON_FA_LOW_VISION \"\\xef\\x8a\\xa8\"\t// U+f2a8\n#define ICON_FA_LUGGAGE_CART \"\\xef\\x96\\x9d\"\t// U+f59d\n#define ICON_FA_LUNGS \"\\xef\\x98\\x84\"\t// U+f604\n#define ICON_FA_LUNGS_VIRUS \"\\xee\\x81\\xa7\"\t// U+e067\n#define ICON_FA_MAGIC \"\\xef\\x83\\x90\"\t// U+f0d0\n#define ICON_FA_MAGNET \"\\xef\\x81\\xb6\"\t// U+f076\n#define ICON_FA_MAIL_BULK \"\\xef\\x99\\xb4\"\t// U+f674\n#define ICON_FA_MALE \"\\xef\\x86\\x83\"\t// U+f183\n#define ICON_FA_MAP \"\\xef\\x89\\xb9\"\t// U+f279\n#define ICON_FA_MAP_MARKED \"\\xef\\x96\\x9f\"\t// U+f59f\n#define ICON_FA_MAP_MARKED_ALT \"\\xef\\x96\\xa0\"\t// U+f5a0\n#define ICON_FA_MAP_MARKER \"\\xef\\x81\\x81\"\t// U+f041\n#define ICON_FA_MAP_MARKER_ALT \"\\xef\\x8f\\x85\"\t// U+f3c5\n#define ICON_FA_MAP_PIN \"\\xef\\x89\\xb6\"\t// U+f276\n#define ICON_FA_MAP_SIGNS \"\\xef\\x89\\xb7\"\t// U+f277\n#define ICON_FA_MARKER \"\\xef\\x96\\xa1\"\t// U+f5a1\n#define ICON_FA_MARS \"\\xef\\x88\\xa2\"\t// U+f222\n#define ICON_FA_MARS_DOUBLE \"\\xef\\x88\\xa7\"\t// U+f227\n#define ICON_FA_MARS_STROKE \"\\xef\\x88\\xa9\"\t// U+f229\n#define ICON_FA_MARS_STROKE_H \"\\xef\\x88\\xab\"\t// U+f22b\n#define ICON_FA_MARS_STROKE_V \"\\xef\\x88\\xaa\"\t// U+f22a\n#define ICON_FA_MASK \"\\xef\\x9b\\xba\"\t// U+f6fa\n#define ICON_FA_MEDAL \"\\xef\\x96\\xa2\"\t// U+f5a2\n#define ICON_FA_MEDKIT \"\\xef\\x83\\xba\"\t// U+f0fa\n#define ICON_FA_MEH \"\\xef\\x84\\x9a\"\t// U+f11a\n#define ICON_FA_MEH_BLANK \"\\xef\\x96\\xa4\"\t// U+f5a4\n#define ICON_FA_MEH_ROLLING_EYES \"\\xef\\x96\\xa5\"\t// U+f5a5\n#define ICON_FA_MEMORY \"\\xef\\x94\\xb8\"\t// U+f538\n#define ICON_FA_MENORAH \"\\xef\\x99\\xb6\"\t// U+f676\n#define ICON_FA_MERCURY \"\\xef\\x88\\xa3\"\t// U+f223\n#define ICON_FA_METEOR \"\\xef\\x9d\\x93\"\t// U+f753\n#define ICON_FA_MICROCHIP \"\\xef\\x8b\\x9b\"\t// U+f2db\n#define ICON_FA_MICROPHONE \"\\xef\\x84\\xb0\"\t// U+f130\n#define ICON_FA_MICROPHONE_ALT \"\\xef\\x8f\\x89\"\t// U+f3c9\n#define ICON_FA_MICROPHONE_ALT_SLASH \"\\xef\\x94\\xb9\"\t// U+f539\n#define ICON_FA_MICROPHONE_SLASH \"\\xef\\x84\\xb1\"\t// U+f131\n#define ICON_FA_MICROSCOPE \"\\xef\\x98\\x90\"\t// U+f610\n#define ICON_FA_MINUS \"\\xef\\x81\\xa8\"\t// U+f068\n#define ICON_FA_MINUS_CIRCLE \"\\xef\\x81\\x96\"\t// U+f056\n#define ICON_FA_MINUS_SQUARE \"\\xef\\x85\\x86\"\t// U+f146\n#define ICON_FA_MITTEN \"\\xef\\x9e\\xb5\"\t// U+f7b5\n#define ICON_FA_MOBILE \"\\xef\\x84\\x8b\"\t// U+f10b\n#define ICON_FA_MOBILE_ALT \"\\xef\\x8f\\x8d\"\t// U+f3cd\n#define ICON_FA_MONEY_BILL \"\\xef\\x83\\x96\"\t// U+f0d6\n#define ICON_FA_MONEY_BILL_ALT \"\\xef\\x8f\\x91\"\t// U+f3d1\n#define ICON_FA_MONEY_BILL_WAVE \"\\xef\\x94\\xba\"\t// U+f53a\n#define ICON_FA_MONEY_BILL_WAVE_ALT \"\\xef\\x94\\xbb\"\t// U+f53b\n#define ICON_FA_MONEY_CHECK \"\\xef\\x94\\xbc\"\t// U+f53c\n#define ICON_FA_MONEY_CHECK_ALT \"\\xef\\x94\\xbd\"\t// U+f53d\n#define ICON_FA_MONUMENT \"\\xef\\x96\\xa6\"\t// U+f5a6\n#define ICON_FA_MOON \"\\xef\\x86\\x86\"\t// U+f186\n#define ICON_FA_MORTAR_PESTLE \"\\xef\\x96\\xa7\"\t// U+f5a7\n#define ICON_FA_MOSQUE \"\\xef\\x99\\xb8\"\t// U+f678\n#define ICON_FA_MOTORCYCLE \"\\xef\\x88\\x9c\"\t// U+f21c\n#define ICON_FA_MOUNTAIN \"\\xef\\x9b\\xbc\"\t// U+f6fc\n#define ICON_FA_MOUSE \"\\xef\\xa3\\x8c\"\t// U+f8cc\n#define ICON_FA_MOUSE_POINTER \"\\xef\\x89\\x85\"\t// U+f245\n#define ICON_FA_MUG_HOT \"\\xef\\x9e\\xb6\"\t// U+f7b6\n#define ICON_FA_MUSIC \"\\xef\\x80\\x81\"\t// U+f001\n#define ICON_FA_NETWORK_WIRED \"\\xef\\x9b\\xbf\"\t// U+f6ff\n#define ICON_FA_NEUTER \"\\xef\\x88\\xac\"\t// U+f22c\n#define ICON_FA_NEWSPAPER \"\\xef\\x87\\xaa\"\t// U+f1ea\n#define ICON_FA_NOT_EQUAL \"\\xef\\x94\\xbe\"\t// U+f53e\n#define ICON_FA_NOTES_MEDICAL \"\\xef\\x92\\x81\"\t// U+f481\n#define ICON_FA_OBJECT_GROUP \"\\xef\\x89\\x87\"\t// U+f247\n#define ICON_FA_OBJECT_UNGROUP \"\\xef\\x89\\x88\"\t// U+f248\n#define ICON_FA_OIL_CAN \"\\xef\\x98\\x93\"\t// U+f613\n#define ICON_FA_OM \"\\xef\\x99\\xb9\"\t// U+f679\n#define ICON_FA_OTTER \"\\xef\\x9c\\x80\"\t// U+f700\n#define ICON_FA_OUTDENT \"\\xef\\x80\\xbb\"\t// U+f03b\n#define ICON_FA_PAGER \"\\xef\\xa0\\x95\"\t// U+f815\n#define ICON_FA_PAINT_BRUSH \"\\xef\\x87\\xbc\"\t// U+f1fc\n#define ICON_FA_PAINT_ROLLER \"\\xef\\x96\\xaa\"\t// U+f5aa\n#define ICON_FA_PALETTE \"\\xef\\x94\\xbf\"\t// U+f53f\n#define ICON_FA_PALLET \"\\xef\\x92\\x82\"\t// U+f482\n#define ICON_FA_PAPER_PLANE \"\\xef\\x87\\x98\"\t// U+f1d8\n#define ICON_FA_PAPERCLIP \"\\xef\\x83\\x86\"\t// U+f0c6\n#define ICON_FA_PARACHUTE_BOX \"\\xef\\x93\\x8d\"\t// U+f4cd\n#define ICON_FA_PARAGRAPH \"\\xef\\x87\\x9d\"\t// U+f1dd\n#define ICON_FA_PARKING \"\\xef\\x95\\x80\"\t// U+f540\n#define ICON_FA_PASSPORT \"\\xef\\x96\\xab\"\t// U+f5ab\n#define ICON_FA_PASTAFARIANISM \"\\xef\\x99\\xbb\"\t// U+f67b\n#define ICON_FA_PASTE \"\\xef\\x83\\xaa\"\t// U+f0ea\n#define ICON_FA_PAUSE \"\\xef\\x81\\x8c\"\t// U+f04c\n#define ICON_FA_PAUSE_CIRCLE \"\\xef\\x8a\\x8b\"\t// U+f28b\n#define ICON_FA_PAW \"\\xef\\x86\\xb0\"\t// U+f1b0\n#define ICON_FA_PEACE \"\\xef\\x99\\xbc\"\t// U+f67c\n#define ICON_FA_PEN \"\\xef\\x8c\\x84\"\t// U+f304\n#define ICON_FA_PEN_ALT \"\\xef\\x8c\\x85\"\t// U+f305\n#define ICON_FA_PEN_FANCY \"\\xef\\x96\\xac\"\t// U+f5ac\n#define ICON_FA_PEN_NIB \"\\xef\\x96\\xad\"\t// U+f5ad\n#define ICON_FA_PEN_SQUARE \"\\xef\\x85\\x8b\"\t// U+f14b\n#define ICON_FA_PENCIL_ALT \"\\xef\\x8c\\x83\"\t// U+f303\n#define ICON_FA_PENCIL_RULER \"\\xef\\x96\\xae\"\t// U+f5ae\n#define ICON_FA_PEOPLE_ARROWS \"\\xee\\x81\\xa8\"\t// U+e068\n#define ICON_FA_PEOPLE_CARRY \"\\xef\\x93\\x8e\"\t// U+f4ce\n#define ICON_FA_PEPPER_HOT \"\\xef\\xa0\\x96\"\t// U+f816\n#define ICON_FA_PERCENT \"\\xef\\x8a\\x95\"\t// U+f295\n#define ICON_FA_PERCENTAGE \"\\xef\\x95\\x81\"\t// U+f541\n#define ICON_FA_PERSON_BOOTH \"\\xef\\x9d\\x96\"\t// U+f756\n#define ICON_FA_PHONE \"\\xef\\x82\\x95\"\t// U+f095\n#define ICON_FA_PHONE_ALT \"\\xef\\xa1\\xb9\"\t// U+f879\n#define ICON_FA_PHONE_SLASH \"\\xef\\x8f\\x9d\"\t// U+f3dd\n#define ICON_FA_PHONE_SQUARE \"\\xef\\x82\\x98\"\t// U+f098\n#define ICON_FA_PHONE_SQUARE_ALT \"\\xef\\xa1\\xbb\"\t// U+f87b\n#define ICON_FA_PHONE_VOLUME \"\\xef\\x8a\\xa0\"\t// U+f2a0\n#define ICON_FA_PHOTO_VIDEO \"\\xef\\xa1\\xbc\"\t// U+f87c\n#define ICON_FA_PIGGY_BANK \"\\xef\\x93\\x93\"\t// U+f4d3\n#define ICON_FA_PILLS \"\\xef\\x92\\x84\"\t// U+f484\n#define ICON_FA_PIZZA_SLICE \"\\xef\\xa0\\x98\"\t// U+f818\n#define ICON_FA_PLACE_OF_WORSHIP \"\\xef\\x99\\xbf\"\t// U+f67f\n#define ICON_FA_PLANE \"\\xef\\x81\\xb2\"\t// U+f072\n#define ICON_FA_PLANE_ARRIVAL \"\\xef\\x96\\xaf\"\t// U+f5af\n#define ICON_FA_PLANE_DEPARTURE \"\\xef\\x96\\xb0\"\t// U+f5b0\n#define ICON_FA_PLANE_SLASH \"\\xee\\x81\\xa9\"\t// U+e069\n#define ICON_FA_PLAY \"\\xef\\x81\\x8b\"\t// U+f04b\n#define ICON_FA_PLAY_CIRCLE \"\\xef\\x85\\x84\"\t// U+f144\n#define ICON_FA_PLUG \"\\xef\\x87\\xa6\"\t// U+f1e6\n#define ICON_FA_PLUS \"\\xef\\x81\\xa7\"\t// U+f067\n#define ICON_FA_PLUS_CIRCLE \"\\xef\\x81\\x95\"\t// U+f055\n#define ICON_FA_PLUS_SQUARE \"\\xef\\x83\\xbe\"\t// U+f0fe\n#define ICON_FA_PODCAST \"\\xef\\x8b\\x8e\"\t// U+f2ce\n#define ICON_FA_POLL \"\\xef\\x9a\\x81\"\t// U+f681\n#define ICON_FA_POLL_H \"\\xef\\x9a\\x82\"\t// U+f682\n#define ICON_FA_POO \"\\xef\\x8b\\xbe\"\t// U+f2fe\n#define ICON_FA_POO_STORM \"\\xef\\x9d\\x9a\"\t// U+f75a\n#define ICON_FA_POOP \"\\xef\\x98\\x99\"\t// U+f619\n#define ICON_FA_PORTRAIT \"\\xef\\x8f\\xa0\"\t// U+f3e0\n#define ICON_FA_POUND_SIGN \"\\xef\\x85\\x94\"\t// U+f154\n#define ICON_FA_POWER_OFF \"\\xef\\x80\\x91\"\t// U+f011\n#define ICON_FA_PRAY \"\\xef\\x9a\\x83\"\t// U+f683\n#define ICON_FA_PRAYING_HANDS \"\\xef\\x9a\\x84\"\t// U+f684\n#define ICON_FA_PRESCRIPTION \"\\xef\\x96\\xb1\"\t// U+f5b1\n#define ICON_FA_PRESCRIPTION_BOTTLE \"\\xef\\x92\\x85\"\t// U+f485\n#define ICON_FA_PRESCRIPTION_BOTTLE_ALT \"\\xef\\x92\\x86\"\t// U+f486\n#define ICON_FA_PRINT \"\\xef\\x80\\xaf\"\t// U+f02f\n#define ICON_FA_PROCEDURES \"\\xef\\x92\\x87\"\t// U+f487\n#define ICON_FA_PROJECT_DIAGRAM \"\\xef\\x95\\x82\"\t// U+f542\n#define ICON_FA_PUMP_MEDICAL \"\\xee\\x81\\xaa\"\t// U+e06a\n#define ICON_FA_PUMP_SOAP \"\\xee\\x81\\xab\"\t// U+e06b\n#define ICON_FA_PUZZLE_PIECE \"\\xef\\x84\\xae\"\t// U+f12e\n#define ICON_FA_QRCODE \"\\xef\\x80\\xa9\"\t// U+f029\n#define ICON_FA_QUESTION \"\\xef\\x84\\xa8\"\t// U+f128\n#define ICON_FA_QUESTION_CIRCLE \"\\xef\\x81\\x99\"\t// U+f059\n#define ICON_FA_QUIDDITCH \"\\xef\\x91\\x98\"\t// U+f458\n#define ICON_FA_QUOTE_LEFT \"\\xef\\x84\\x8d\"\t// U+f10d\n#define ICON_FA_QUOTE_RIGHT \"\\xef\\x84\\x8e\"\t// U+f10e\n#define ICON_FA_QURAN \"\\xef\\x9a\\x87\"\t// U+f687\n#define ICON_FA_RADIATION \"\\xef\\x9e\\xb9\"\t// U+f7b9\n#define ICON_FA_RADIATION_ALT \"\\xef\\x9e\\xba\"\t// U+f7ba\n#define ICON_FA_RAINBOW \"\\xef\\x9d\\x9b\"\t// U+f75b\n#define ICON_FA_RANDOM \"\\xef\\x81\\xb4\"\t// U+f074\n#define ICON_FA_RECEIPT \"\\xef\\x95\\x83\"\t// U+f543\n#define ICON_FA_RECORD_VINYL \"\\xef\\xa3\\x99\"\t// U+f8d9\n#define ICON_FA_RECYCLE \"\\xef\\x86\\xb8\"\t// U+f1b8\n#define ICON_FA_REDO \"\\xef\\x80\\x9e\"\t// U+f01e\n#define ICON_FA_REDO_ALT \"\\xef\\x8b\\xb9\"\t// U+f2f9\n#define ICON_FA_REGISTERED \"\\xef\\x89\\x9d\"\t// U+f25d\n#define ICON_FA_REMOVE_FORMAT \"\\xef\\xa1\\xbd\"\t// U+f87d\n#define ICON_FA_REPLY \"\\xef\\x8f\\xa5\"\t// U+f3e5\n#define ICON_FA_REPLY_ALL \"\\xef\\x84\\xa2\"\t// U+f122\n#define ICON_FA_REPUBLICAN \"\\xef\\x9d\\x9e\"\t// U+f75e\n#define ICON_FA_RESTROOM \"\\xef\\x9e\\xbd\"\t// U+f7bd\n#define ICON_FA_RETWEET \"\\xef\\x81\\xb9\"\t// U+f079\n#define ICON_FA_RIBBON \"\\xef\\x93\\x96\"\t// U+f4d6\n#define ICON_FA_RING \"\\xef\\x9c\\x8b\"\t// U+f70b\n#define ICON_FA_ROAD \"\\xef\\x80\\x98\"\t// U+f018\n#define ICON_FA_ROBOT \"\\xef\\x95\\x84\"\t// U+f544\n#define ICON_FA_ROCKET \"\\xef\\x84\\xb5\"\t// U+f135\n#define ICON_FA_ROUTE \"\\xef\\x93\\x97\"\t// U+f4d7\n#define ICON_FA_RSS \"\\xef\\x82\\x9e\"\t// U+f09e\n#define ICON_FA_RSS_SQUARE \"\\xef\\x85\\x83\"\t// U+f143\n#define ICON_FA_RUBLE_SIGN \"\\xef\\x85\\x98\"\t// U+f158\n#define ICON_FA_RULER \"\\xef\\x95\\x85\"\t// U+f545\n#define ICON_FA_RULER_COMBINED \"\\xef\\x95\\x86\"\t// U+f546\n#define ICON_FA_RULER_HORIZONTAL \"\\xef\\x95\\x87\"\t// U+f547\n#define ICON_FA_RULER_VERTICAL \"\\xef\\x95\\x88\"\t// U+f548\n#define ICON_FA_RUNNING \"\\xef\\x9c\\x8c\"\t// U+f70c\n#define ICON_FA_RUPEE_SIGN \"\\xef\\x85\\x96\"\t// U+f156\n#define ICON_FA_SAD_CRY \"\\xef\\x96\\xb3\"\t// U+f5b3\n#define ICON_FA_SAD_TEAR \"\\xef\\x96\\xb4\"\t// U+f5b4\n#define ICON_FA_SATELLITE \"\\xef\\x9e\\xbf\"\t// U+f7bf\n#define ICON_FA_SATELLITE_DISH \"\\xef\\x9f\\x80\"\t// U+f7c0\n#define ICON_FA_SAVE \"\\xef\\x83\\x87\"\t// U+f0c7\n#define ICON_FA_SCHOOL \"\\xef\\x95\\x89\"\t// U+f549\n#define ICON_FA_SCREWDRIVER \"\\xef\\x95\\x8a\"\t// U+f54a\n#define ICON_FA_SCROLL \"\\xef\\x9c\\x8e\"\t// U+f70e\n#define ICON_FA_SD_CARD \"\\xef\\x9f\\x82\"\t// U+f7c2\n#define ICON_FA_SEARCH \"\\xef\\x80\\x82\"\t// U+f002\n#define ICON_FA_SEARCH_DOLLAR \"\\xef\\x9a\\x88\"\t// U+f688\n#define ICON_FA_SEARCH_LOCATION \"\\xef\\x9a\\x89\"\t// U+f689\n#define ICON_FA_SEARCH_MINUS \"\\xef\\x80\\x90\"\t// U+f010\n#define ICON_FA_SEARCH_PLUS \"\\xef\\x80\\x8e\"\t// U+f00e\n#define ICON_FA_SEEDLING \"\\xef\\x93\\x98\"\t// U+f4d8\n#define ICON_FA_SERVER \"\\xef\\x88\\xb3\"\t// U+f233\n#define ICON_FA_SHAPES \"\\xef\\x98\\x9f\"\t// U+f61f\n#define ICON_FA_SHARE \"\\xef\\x81\\xa4\"\t// U+f064\n#define ICON_FA_SHARE_ALT \"\\xef\\x87\\xa0\"\t// U+f1e0\n#define ICON_FA_SHARE_ALT_SQUARE \"\\xef\\x87\\xa1\"\t// U+f1e1\n#define ICON_FA_SHARE_SQUARE \"\\xef\\x85\\x8d\"\t// U+f14d\n#define ICON_FA_SHEKEL_SIGN \"\\xef\\x88\\x8b\"\t// U+f20b\n#define ICON_FA_SHIELD_ALT \"\\xef\\x8f\\xad\"\t// U+f3ed\n#define ICON_FA_SHIELD_VIRUS \"\\xee\\x81\\xac\"\t// U+e06c\n#define ICON_FA_SHIP \"\\xef\\x88\\x9a\"\t// U+f21a\n#define ICON_FA_SHIPPING_FAST \"\\xef\\x92\\x8b\"\t// U+f48b\n#define ICON_FA_SHOE_PRINTS \"\\xef\\x95\\x8b\"\t// U+f54b\n#define ICON_FA_SHOPPING_BAG \"\\xef\\x8a\\x90\"\t// U+f290\n#define ICON_FA_SHOPPING_BASKET \"\\xef\\x8a\\x91\"\t// U+f291\n#define ICON_FA_SHOPPING_CART \"\\xef\\x81\\xba\"\t// U+f07a\n#define ICON_FA_SHOWER \"\\xef\\x8b\\x8c\"\t// U+f2cc\n#define ICON_FA_SHUTTLE_VAN \"\\xef\\x96\\xb6\"\t// U+f5b6\n#define ICON_FA_SIGN \"\\xef\\x93\\x99\"\t// U+f4d9\n#define ICON_FA_SIGN_IN_ALT \"\\xef\\x8b\\xb6\"\t// U+f2f6\n#define ICON_FA_SIGN_LANGUAGE \"\\xef\\x8a\\xa7\"\t// U+f2a7\n#define ICON_FA_SIGN_OUT_ALT \"\\xef\\x8b\\xb5\"\t// U+f2f5\n#define ICON_FA_SIGNAL \"\\xef\\x80\\x92\"\t// U+f012\n#define ICON_FA_SIGNATURE \"\\xef\\x96\\xb7\"\t// U+f5b7\n#define ICON_FA_SIM_CARD \"\\xef\\x9f\\x84\"\t// U+f7c4\n#define ICON_FA_SINK \"\\xee\\x81\\xad\"\t// U+e06d\n#define ICON_FA_SITEMAP \"\\xef\\x83\\xa8\"\t// U+f0e8\n#define ICON_FA_SKATING \"\\xef\\x9f\\x85\"\t// U+f7c5\n#define ICON_FA_SKIING \"\\xef\\x9f\\x89\"\t// U+f7c9\n#define ICON_FA_SKIING_NORDIC \"\\xef\\x9f\\x8a\"\t// U+f7ca\n#define ICON_FA_SKULL \"\\xef\\x95\\x8c\"\t// U+f54c\n#define ICON_FA_SKULL_CROSSBONES \"\\xef\\x9c\\x94\"\t// U+f714\n#define ICON_FA_SLASH \"\\xef\\x9c\\x95\"\t// U+f715\n#define ICON_FA_SLEIGH \"\\xef\\x9f\\x8c\"\t// U+f7cc\n#define ICON_FA_SLIDERS_H \"\\xef\\x87\\x9e\"\t// U+f1de\n#define ICON_FA_SMILE \"\\xef\\x84\\x98\"\t// U+f118\n#define ICON_FA_SMILE_BEAM \"\\xef\\x96\\xb8\"\t// U+f5b8\n#define ICON_FA_SMILE_WINK \"\\xef\\x93\\x9a\"\t// U+f4da\n#define ICON_FA_SMOG \"\\xef\\x9d\\x9f\"\t// U+f75f\n#define ICON_FA_SMOKING \"\\xef\\x92\\x8d\"\t// U+f48d\n#define ICON_FA_SMOKING_BAN \"\\xef\\x95\\x8d\"\t// U+f54d\n#define ICON_FA_SMS \"\\xef\\x9f\\x8d\"\t// U+f7cd\n#define ICON_FA_SNOWBOARDING \"\\xef\\x9f\\x8e\"\t// U+f7ce\n#define ICON_FA_SNOWFLAKE \"\\xef\\x8b\\x9c\"\t// U+f2dc\n#define ICON_FA_SNOWMAN \"\\xef\\x9f\\x90\"\t// U+f7d0\n#define ICON_FA_SNOWPLOW \"\\xef\\x9f\\x92\"\t// U+f7d2\n#define ICON_FA_SOAP \"\\xee\\x81\\xae\"\t// U+e06e\n#define ICON_FA_SOCKS \"\\xef\\x9a\\x96\"\t// U+f696\n#define ICON_FA_SOLAR_PANEL \"\\xef\\x96\\xba\"\t// U+f5ba\n#define ICON_FA_SORT \"\\xef\\x83\\x9c\"\t// U+f0dc\n#define ICON_FA_SORT_ALPHA_DOWN \"\\xef\\x85\\x9d\"\t// U+f15d\n#define ICON_FA_SORT_ALPHA_DOWN_ALT \"\\xef\\xa2\\x81\"\t// U+f881\n#define ICON_FA_SORT_ALPHA_UP \"\\xef\\x85\\x9e\"\t// U+f15e\n#define ICON_FA_SORT_ALPHA_UP_ALT \"\\xef\\xa2\\x82\"\t// U+f882\n#define ICON_FA_SORT_AMOUNT_DOWN \"\\xef\\x85\\xa0\"\t// U+f160\n#define ICON_FA_SORT_AMOUNT_DOWN_ALT \"\\xef\\xa2\\x84\"\t// U+f884\n#define ICON_FA_SORT_AMOUNT_UP \"\\xef\\x85\\xa1\"\t// U+f161\n#define ICON_FA_SORT_AMOUNT_UP_ALT \"\\xef\\xa2\\x85\"\t// U+f885\n#define ICON_FA_SORT_DOWN \"\\xef\\x83\\x9d\"\t// U+f0dd\n#define ICON_FA_SORT_NUMERIC_DOWN \"\\xef\\x85\\xa2\"\t// U+f162\n#define ICON_FA_SORT_NUMERIC_DOWN_ALT \"\\xef\\xa2\\x86\"\t// U+f886\n#define ICON_FA_SORT_NUMERIC_UP \"\\xef\\x85\\xa3\"\t// U+f163\n#define ICON_FA_SORT_NUMERIC_UP_ALT \"\\xef\\xa2\\x87\"\t// U+f887\n#define ICON_FA_SORT_UP \"\\xef\\x83\\x9e\"\t// U+f0de\n#define ICON_FA_SPA \"\\xef\\x96\\xbb\"\t// U+f5bb\n#define ICON_FA_SPACE_SHUTTLE \"\\xef\\x86\\x97\"\t// U+f197\n#define ICON_FA_SPELL_CHECK \"\\xef\\xa2\\x91\"\t// U+f891\n#define ICON_FA_SPIDER \"\\xef\\x9c\\x97\"\t// U+f717\n#define ICON_FA_SPINNER \"\\xef\\x84\\x90\"\t// U+f110\n#define ICON_FA_SPLOTCH \"\\xef\\x96\\xbc\"\t// U+f5bc\n#define ICON_FA_SPRAY_CAN \"\\xef\\x96\\xbd\"\t// U+f5bd\n#define ICON_FA_SQUARE \"\\xef\\x83\\x88\"\t// U+f0c8\n#define ICON_FA_SQUARE_FULL \"\\xef\\x91\\x9c\"\t// U+f45c\n#define ICON_FA_SQUARE_ROOT_ALT \"\\xef\\x9a\\x98\"\t// U+f698\n#define ICON_FA_STAMP \"\\xef\\x96\\xbf\"\t// U+f5bf\n#define ICON_FA_STAR \"\\xef\\x80\\x85\"\t// U+f005\n#define ICON_FA_STAR_AND_CRESCENT \"\\xef\\x9a\\x99\"\t// U+f699\n#define ICON_FA_STAR_HALF \"\\xef\\x82\\x89\"\t// U+f089\n#define ICON_FA_STAR_HALF_ALT \"\\xef\\x97\\x80\"\t// U+f5c0\n#define ICON_FA_STAR_OF_DAVID \"\\xef\\x9a\\x9a\"\t// U+f69a\n#define ICON_FA_STAR_OF_LIFE \"\\xef\\x98\\xa1\"\t// U+f621\n#define ICON_FA_STEP_BACKWARD \"\\xef\\x81\\x88\"\t// U+f048\n#define ICON_FA_STEP_FORWARD \"\\xef\\x81\\x91\"\t// U+f051\n#define ICON_FA_STETHOSCOPE \"\\xef\\x83\\xb1\"\t// U+f0f1\n#define ICON_FA_STICKY_NOTE \"\\xef\\x89\\x89\"\t// U+f249\n#define ICON_FA_STOP \"\\xef\\x81\\x8d\"\t// U+f04d\n#define ICON_FA_STOP_CIRCLE \"\\xef\\x8a\\x8d\"\t// U+f28d\n#define ICON_FA_STOPWATCH \"\\xef\\x8b\\xb2\"\t// U+f2f2\n#define ICON_FA_STOPWATCH_20 \"\\xee\\x81\\xaf\"\t// U+e06f\n#define ICON_FA_STORE \"\\xef\\x95\\x8e\"\t// U+f54e\n#define ICON_FA_STORE_ALT \"\\xef\\x95\\x8f\"\t// U+f54f\n#define ICON_FA_STORE_ALT_SLASH \"\\xee\\x81\\xb0\"\t// U+e070\n#define ICON_FA_STORE_SLASH \"\\xee\\x81\\xb1\"\t// U+e071\n#define ICON_FA_STREAM \"\\xef\\x95\\x90\"\t// U+f550\n#define ICON_FA_STREET_VIEW \"\\xef\\x88\\x9d\"\t// U+f21d\n#define ICON_FA_STRIKETHROUGH \"\\xef\\x83\\x8c\"\t// U+f0cc\n#define ICON_FA_STROOPWAFEL \"\\xef\\x95\\x91\"\t// U+f551\n#define ICON_FA_SUBSCRIPT \"\\xef\\x84\\xac\"\t// U+f12c\n#define ICON_FA_SUBWAY \"\\xef\\x88\\xb9\"\t// U+f239\n#define ICON_FA_SUITCASE \"\\xef\\x83\\xb2\"\t// U+f0f2\n#define ICON_FA_SUITCASE_ROLLING \"\\xef\\x97\\x81\"\t// U+f5c1\n#define ICON_FA_SUN \"\\xef\\x86\\x85\"\t// U+f185\n#define ICON_FA_SUPERSCRIPT \"\\xef\\x84\\xab\"\t// U+f12b\n#define ICON_FA_SURPRISE \"\\xef\\x97\\x82\"\t// U+f5c2\n#define ICON_FA_SWATCHBOOK \"\\xef\\x97\\x83\"\t// U+f5c3\n#define ICON_FA_SWIMMER \"\\xef\\x97\\x84\"\t// U+f5c4\n#define ICON_FA_SWIMMING_POOL \"\\xef\\x97\\x85\"\t// U+f5c5\n#define ICON_FA_SYNAGOGUE \"\\xef\\x9a\\x9b\"\t// U+f69b\n#define ICON_FA_SYNC \"\\xef\\x80\\xa1\"\t// U+f021\n#define ICON_FA_SYNC_ALT \"\\xef\\x8b\\xb1\"\t// U+f2f1\n#define ICON_FA_SYRINGE \"\\xef\\x92\\x8e\"\t// U+f48e\n#define ICON_FA_TABLE \"\\xef\\x83\\x8e\"\t// U+f0ce\n#define ICON_FA_TABLE_TENNIS \"\\xef\\x91\\x9d\"\t// U+f45d\n#define ICON_FA_TABLET \"\\xef\\x84\\x8a\"\t// U+f10a\n#define ICON_FA_TABLET_ALT \"\\xef\\x8f\\xba\"\t// U+f3fa\n#define ICON_FA_TABLETS \"\\xef\\x92\\x90\"\t// U+f490\n#define ICON_FA_TACHOMETER_ALT \"\\xef\\x8f\\xbd\"\t// U+f3fd\n#define ICON_FA_TAG \"\\xef\\x80\\xab\"\t// U+f02b\n#define ICON_FA_TAGS \"\\xef\\x80\\xac\"\t// U+f02c\n#define ICON_FA_TAPE \"\\xef\\x93\\x9b\"\t// U+f4db\n#define ICON_FA_TASKS \"\\xef\\x82\\xae\"\t// U+f0ae\n#define ICON_FA_TAXI \"\\xef\\x86\\xba\"\t// U+f1ba\n#define ICON_FA_TEETH \"\\xef\\x98\\xae\"\t// U+f62e\n#define ICON_FA_TEETH_OPEN \"\\xef\\x98\\xaf\"\t// U+f62f\n#define ICON_FA_TEMPERATURE_HIGH \"\\xef\\x9d\\xa9\"\t// U+f769\n#define ICON_FA_TEMPERATURE_LOW \"\\xef\\x9d\\xab\"\t// U+f76b\n#define ICON_FA_TENGE \"\\xef\\x9f\\x97\"\t// U+f7d7\n#define ICON_FA_TERMINAL \"\\xef\\x84\\xa0\"\t// U+f120\n#define ICON_FA_TEXT_HEIGHT \"\\xef\\x80\\xb4\"\t// U+f034\n#define ICON_FA_TEXT_WIDTH \"\\xef\\x80\\xb5\"\t// U+f035\n#define ICON_FA_TH \"\\xef\\x80\\x8a\"\t// U+f00a\n#define ICON_FA_TH_LARGE \"\\xef\\x80\\x89\"\t// U+f009\n#define ICON_FA_TH_LIST \"\\xef\\x80\\x8b\"\t// U+f00b\n#define ICON_FA_THEATER_MASKS \"\\xef\\x98\\xb0\"\t// U+f630\n#define ICON_FA_THERMOMETER \"\\xef\\x92\\x91\"\t// U+f491\n#define ICON_FA_THERMOMETER_EMPTY \"\\xef\\x8b\\x8b\"\t// U+f2cb\n#define ICON_FA_THERMOMETER_FULL \"\\xef\\x8b\\x87\"\t// U+f2c7\n#define ICON_FA_THERMOMETER_HALF \"\\xef\\x8b\\x89\"\t// U+f2c9\n#define ICON_FA_THERMOMETER_QUARTER \"\\xef\\x8b\\x8a\"\t// U+f2ca\n#define ICON_FA_THERMOMETER_THREE_QUARTERS \"\\xef\\x8b\\x88\"\t// U+f2c8\n#define ICON_FA_THUMBS_DOWN \"\\xef\\x85\\xa5\"\t// U+f165\n#define ICON_FA_THUMBS_UP \"\\xef\\x85\\xa4\"\t// U+f164\n#define ICON_FA_THUMBTACK \"\\xef\\x82\\x8d\"\t// U+f08d\n#define ICON_FA_TICKET_ALT \"\\xef\\x8f\\xbf\"\t// U+f3ff\n#define ICON_FA_TIMES \"\\xef\\x80\\x8d\"\t// U+f00d\n#define ICON_FA_TIMES_CIRCLE \"\\xef\\x81\\x97\"\t// U+f057\n#define ICON_FA_TINT \"\\xef\\x81\\x83\"\t// U+f043\n#define ICON_FA_TINT_SLASH \"\\xef\\x97\\x87\"\t// U+f5c7\n#define ICON_FA_TIRED \"\\xef\\x97\\x88\"\t// U+f5c8\n#define ICON_FA_TOGGLE_OFF \"\\xef\\x88\\x84\"\t// U+f204\n#define ICON_FA_TOGGLE_ON \"\\xef\\x88\\x85\"\t// U+f205\n#define ICON_FA_TOILET \"\\xef\\x9f\\x98\"\t// U+f7d8\n#define ICON_FA_TOILET_PAPER \"\\xef\\x9c\\x9e\"\t// U+f71e\n#define ICON_FA_TOILET_PAPER_SLASH \"\\xee\\x81\\xb2\"\t// U+e072\n#define ICON_FA_TOOLBOX \"\\xef\\x95\\x92\"\t// U+f552\n#define ICON_FA_TOOLS \"\\xef\\x9f\\x99\"\t// U+f7d9\n#define ICON_FA_TOOTH \"\\xef\\x97\\x89\"\t// U+f5c9\n#define ICON_FA_TORAH \"\\xef\\x9a\\xa0\"\t// U+f6a0\n#define ICON_FA_TORII_GATE \"\\xef\\x9a\\xa1\"\t// U+f6a1\n#define ICON_FA_TRACTOR \"\\xef\\x9c\\xa2\"\t// U+f722\n#define ICON_FA_TRADEMARK \"\\xef\\x89\\x9c\"\t// U+f25c\n#define ICON_FA_TRAFFIC_LIGHT \"\\xef\\x98\\xb7\"\t// U+f637\n#define ICON_FA_TRAILER \"\\xee\\x81\\x81\"\t// U+e041\n#define ICON_FA_TRAIN \"\\xef\\x88\\xb8\"\t// U+f238\n#define ICON_FA_TRAM \"\\xef\\x9f\\x9a\"\t// U+f7da\n#define ICON_FA_TRANSGENDER \"\\xef\\x88\\xa4\"\t// U+f224\n#define ICON_FA_TRANSGENDER_ALT \"\\xef\\x88\\xa5\"\t// U+f225\n#define ICON_FA_TRASH \"\\xef\\x87\\xb8\"\t// U+f1f8\n#define ICON_FA_TRASH_ALT \"\\xef\\x8b\\xad\"\t// U+f2ed\n#define ICON_FA_TRASH_RESTORE \"\\xef\\xa0\\xa9\"\t// U+f829\n#define ICON_FA_TRASH_RESTORE_ALT \"\\xef\\xa0\\xaa\"\t// U+f82a\n#define ICON_FA_TREE \"\\xef\\x86\\xbb\"\t// U+f1bb\n#define ICON_FA_TROPHY \"\\xef\\x82\\x91\"\t// U+f091\n#define ICON_FA_TRUCK \"\\xef\\x83\\x91\"\t// U+f0d1\n#define ICON_FA_TRUCK_LOADING \"\\xef\\x93\\x9e\"\t// U+f4de\n#define ICON_FA_TRUCK_MONSTER \"\\xef\\x98\\xbb\"\t// U+f63b\n#define ICON_FA_TRUCK_MOVING \"\\xef\\x93\\x9f\"\t// U+f4df\n#define ICON_FA_TRUCK_PICKUP \"\\xef\\x98\\xbc\"\t// U+f63c\n#define ICON_FA_TSHIRT \"\\xef\\x95\\x93\"\t// U+f553\n#define ICON_FA_TTY \"\\xef\\x87\\xa4\"\t// U+f1e4\n#define ICON_FA_TV \"\\xef\\x89\\xac\"\t// U+f26c\n#define ICON_FA_UMBRELLA \"\\xef\\x83\\xa9\"\t// U+f0e9\n#define ICON_FA_UMBRELLA_BEACH \"\\xef\\x97\\x8a\"\t// U+f5ca\n#define ICON_FA_UNDERLINE \"\\xef\\x83\\x8d\"\t// U+f0cd\n#define ICON_FA_UNDO \"\\xef\\x83\\xa2\"\t// U+f0e2\n#define ICON_FA_UNDO_ALT \"\\xef\\x8b\\xaa\"\t// U+f2ea\n#define ICON_FA_UNIVERSAL_ACCESS \"\\xef\\x8a\\x9a\"\t// U+f29a\n#define ICON_FA_UNIVERSITY \"\\xef\\x86\\x9c\"\t// U+f19c\n#define ICON_FA_UNLINK \"\\xef\\x84\\xa7\"\t// U+f127\n#define ICON_FA_UNLOCK \"\\xef\\x82\\x9c\"\t// U+f09c\n#define ICON_FA_UNLOCK_ALT \"\\xef\\x84\\xbe\"\t// U+f13e\n#define ICON_FA_UPLOAD \"\\xef\\x82\\x93\"\t// U+f093\n#define ICON_FA_USER \"\\xef\\x80\\x87\"\t// U+f007\n#define ICON_FA_USER_ALT \"\\xef\\x90\\x86\"\t// U+f406\n#define ICON_FA_USER_ALT_SLASH \"\\xef\\x93\\xba\"\t// U+f4fa\n#define ICON_FA_USER_ASTRONAUT \"\\xef\\x93\\xbb\"\t// U+f4fb\n#define ICON_FA_USER_CHECK \"\\xef\\x93\\xbc\"\t// U+f4fc\n#define ICON_FA_USER_CIRCLE \"\\xef\\x8a\\xbd\"\t// U+f2bd\n#define ICON_FA_USER_CLOCK \"\\xef\\x93\\xbd\"\t// U+f4fd\n#define ICON_FA_USER_COG \"\\xef\\x93\\xbe\"\t// U+f4fe\n#define ICON_FA_USER_EDIT \"\\xef\\x93\\xbf\"\t// U+f4ff\n#define ICON_FA_USER_FRIENDS \"\\xef\\x94\\x80\"\t// U+f500\n#define ICON_FA_USER_GRADUATE \"\\xef\\x94\\x81\"\t// U+f501\n#define ICON_FA_USER_INJURED \"\\xef\\x9c\\xa8\"\t// U+f728\n#define ICON_FA_USER_LOCK \"\\xef\\x94\\x82\"\t// U+f502\n#define ICON_FA_USER_MD \"\\xef\\x83\\xb0\"\t// U+f0f0\n#define ICON_FA_USER_MINUS \"\\xef\\x94\\x83\"\t// U+f503\n#define ICON_FA_USER_NINJA \"\\xef\\x94\\x84\"\t// U+f504\n#define ICON_FA_USER_NURSE \"\\xef\\xa0\\xaf\"\t// U+f82f\n#define ICON_FA_USER_PLUS \"\\xef\\x88\\xb4\"\t// U+f234\n#define ICON_FA_USER_SECRET \"\\xef\\x88\\x9b\"\t// U+f21b\n#define ICON_FA_USER_SHIELD \"\\xef\\x94\\x85\"\t// U+f505\n#define ICON_FA_USER_SLASH \"\\xef\\x94\\x86\"\t// U+f506\n#define ICON_FA_USER_TAG \"\\xef\\x94\\x87\"\t// U+f507\n#define ICON_FA_USER_TIE \"\\xef\\x94\\x88\"\t// U+f508\n#define ICON_FA_USER_TIMES \"\\xef\\x88\\xb5\"\t// U+f235\n#define ICON_FA_USERS \"\\xef\\x83\\x80\"\t// U+f0c0\n#define ICON_FA_USERS_COG \"\\xef\\x94\\x89\"\t// U+f509\n#define ICON_FA_USERS_SLASH \"\\xee\\x81\\xb3\"\t// U+e073\n#define ICON_FA_UTENSIL_SPOON \"\\xef\\x8b\\xa5\"\t// U+f2e5\n#define ICON_FA_UTENSILS \"\\xef\\x8b\\xa7\"\t// U+f2e7\n#define ICON_FA_VECTOR_SQUARE \"\\xef\\x97\\x8b\"\t// U+f5cb\n#define ICON_FA_VENUS \"\\xef\\x88\\xa1\"\t// U+f221\n#define ICON_FA_VENUS_DOUBLE \"\\xef\\x88\\xa6\"\t// U+f226\n#define ICON_FA_VENUS_MARS \"\\xef\\x88\\xa8\"\t// U+f228\n#define ICON_FA_VEST \"\\xee\\x82\\x85\"\t// U+e085\n#define ICON_FA_VEST_PATCHES \"\\xee\\x82\\x86\"\t// U+e086\n#define ICON_FA_VIAL \"\\xef\\x92\\x92\"\t// U+f492\n#define ICON_FA_VIALS \"\\xef\\x92\\x93\"\t// U+f493\n#define ICON_FA_VIDEO \"\\xef\\x80\\xbd\"\t// U+f03d\n#define ICON_FA_VIDEO_SLASH \"\\xef\\x93\\xa2\"\t// U+f4e2\n#define ICON_FA_VIHARA \"\\xef\\x9a\\xa7\"\t// U+f6a7\n#define ICON_FA_VIRUS \"\\xee\\x81\\xb4\"\t// U+e074\n#define ICON_FA_VIRUS_SLASH \"\\xee\\x81\\xb5\"\t// U+e075\n#define ICON_FA_VIRUSES \"\\xee\\x81\\xb6\"\t// U+e076\n#define ICON_FA_VOICEMAIL \"\\xef\\xa2\\x97\"\t// U+f897\n#define ICON_FA_VOLLEYBALL_BALL \"\\xef\\x91\\x9f\"\t// U+f45f\n#define ICON_FA_VOLUME_DOWN \"\\xef\\x80\\xa7\"\t// U+f027\n#define ICON_FA_VOLUME_MUTE \"\\xef\\x9a\\xa9\"\t// U+f6a9\n#define ICON_FA_VOLUME_OFF \"\\xef\\x80\\xa6\"\t// U+f026\n#define ICON_FA_VOLUME_UP \"\\xef\\x80\\xa8\"\t// U+f028\n#define ICON_FA_VOTE_YEA \"\\xef\\x9d\\xb2\"\t// U+f772\n#define ICON_FA_VR_CARDBOARD \"\\xef\\x9c\\xa9\"\t// U+f729\n#define ICON_FA_WALKING \"\\xef\\x95\\x94\"\t// U+f554\n#define ICON_FA_WALLET \"\\xef\\x95\\x95\"\t// U+f555\n#define ICON_FA_WAREHOUSE \"\\xef\\x92\\x94\"\t// U+f494\n#define ICON_FA_WATER \"\\xef\\x9d\\xb3\"\t// U+f773\n#define ICON_FA_WAVE_SQUARE \"\\xef\\xa0\\xbe\"\t// U+f83e\n#define ICON_FA_WEIGHT \"\\xef\\x92\\x96\"\t// U+f496\n#define ICON_FA_WEIGHT_HANGING \"\\xef\\x97\\x8d\"\t// U+f5cd\n#define ICON_FA_WHEELCHAIR \"\\xef\\x86\\x93\"\t// U+f193\n#define ICON_FA_WIFI \"\\xef\\x87\\xab\"\t// U+f1eb\n#define ICON_FA_WIND \"\\xef\\x9c\\xae\"\t// U+f72e\n#define ICON_FA_WINDOW_CLOSE \"\\xef\\x90\\x90\"\t// U+f410\n#define ICON_FA_WINDOW_MAXIMIZE \"\\xef\\x8b\\x90\"\t// U+f2d0\n#define ICON_FA_WINDOW_MINIMIZE \"\\xef\\x8b\\x91\"\t// U+f2d1\n#define ICON_FA_WINDOW_RESTORE \"\\xef\\x8b\\x92\"\t// U+f2d2\n#define ICON_FA_WINE_BOTTLE \"\\xef\\x9c\\xaf\"\t// U+f72f\n#define ICON_FA_WINE_GLASS \"\\xef\\x93\\xa3\"\t// U+f4e3\n#define ICON_FA_WINE_GLASS_ALT \"\\xef\\x97\\x8e\"\t// U+f5ce\n#define ICON_FA_WON_SIGN \"\\xef\\x85\\x99\"\t// U+f159\n#define ICON_FA_WRENCH \"\\xef\\x82\\xad\"\t// U+f0ad\n#define ICON_FA_X_RAY \"\\xef\\x92\\x97\"\t// U+f497\n#define ICON_FA_YEN_SIGN \"\\xef\\x85\\x97\"\t// U+f157\n#define ICON_FA_YIN_YANG \"\\xef\\x9a\\xad\"\t// U+f6ad\n"
  },
  {
    "path": "Source/External/imgui_tools/imgui_impl_glfw.cpp",
    "content": "// dear imgui: Platform Backend for GLFW\n// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)\n// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)\n// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)\n\n// Implemented features:\n//  [X] Platform: Clipboard support.\n//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]\n//  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.\n//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).\n//  [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.\n\n// Issues:\n//  [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).\n\n// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.\n// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.\n// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.\n// Read online: https://github.com/ocornut/imgui/tree/master/docs\n\n// CHANGELOG\n// (minor and older changes stripped away, please see git history for details)\n//  2022-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.\n//  2022-11-22: Perform a dummy glfwGetError() read to cancel missing names with glfwGetKeyName(). (#5908)\n//  2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785)\n//  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.\n//  2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).\n//  2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position.\n//  2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX.\n//  2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11.\n//  2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend.\n//  2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.\n//  2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].\n//  2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).\n//  2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.\n//  2022-01-12: *BREAKING CHANGE*: Now using glfwSetCursorPosCallback(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetCursorPosCallback() and forward it to the backend via ImGui_ImplGlfw_CursorPosCallback().\n//  2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.\n//  2022-01-05: Inputs: Converting GLFW untranslated keycodes back to translated keycodes (in the ImGui_ImplGlfw_KeyCallback() function) in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API.\n//  2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback().\n//  2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback().\n//  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).\n//  2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.\n//  2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).\n//  2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.\n//  2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.\n//  2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().\n//  2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.\n//  2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.\n//  2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.\n//  2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.\n//  2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.\n//  2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.\n//  2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.\n//  2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).\n//  2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.\n//  2018-02-06: Inputs: Added mapping for ImGuiKey_Space.\n//  2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.\n//  2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).\n//  2018-01-20: Inputs: Added Horizontal Mouse Wheel support.\n//  2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.\n//  2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).\n//  2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.\n\n#include \"imgui.h\"\n#include \"imgui_impl_glfw.h\"\n\n// Clang warnings with -Weverything\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wold-style-cast\"     // warning: use of old-style cast\n#pragma clang diagnostic ignored \"-Wsign-conversion\"    // warning: implicit conversion changes signedness\n#endif\n\n// GLFW\n#include <GLFW/glfw3.h>\n\n#ifdef _WIN32\n#undef APIENTRY\n#define GLFW_EXPOSE_NATIVE_WIN32\n#include <GLFW/glfw3native.h>   // for glfwGetWin32Window()\n#endif\n#ifdef __APPLE__\n#define GLFW_EXPOSE_NATIVE_COCOA\n#include <GLFW/glfw3native.h>   // for glfwGetCocoaWindow()\n#endif\n\n// We gather version tests as define in order to easily see which features are version-dependent.\n#define GLFW_VERSION_COMBINED           (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)\n#define GLFW_HAS_WINDOW_TOPMOST         (GLFW_VERSION_COMBINED >= 3200) // 3.2+ GLFW_FLOATING\n#define GLFW_HAS_WINDOW_HOVERED         (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_HOVERED\n#define GLFW_HAS_WINDOW_ALPHA           (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwSetWindowOpacity\n#define GLFW_HAS_PER_MONITOR_DPI        (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale\n#define GLFW_HAS_VULKAN                 (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwCreateWindowSurface\n#define GLFW_HAS_FOCUS_WINDOW           (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwFocusWindow\n#define GLFW_HAS_FOCUS_ON_SHOW          (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW\n#define GLFW_HAS_MONITOR_WORK_AREA      (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorWorkarea\n#define GLFW_HAS_OSX_WINDOW_POS_FIX     (GLFW_VERSION_COMBINED >= 3301) // 3.3.1+ Fixed: Resizing window repositions it on MacOS #1553\n#ifdef GLFW_RESIZE_NESW_CURSOR          // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?\n#define GLFW_HAS_NEW_CURSORS            (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR\n#else\n#define GLFW_HAS_NEW_CURSORS            (0)\n#endif\n#ifdef GLFW_MOUSE_PASSTHROUGH           // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2020-07-17 (passthrough)\n#define GLFW_HAS_MOUSE_PASSTHROUGH      (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_MOUSE_PASSTHROUGH\n#else\n#define GLFW_HAS_MOUSE_PASSTHROUGH      (0)\n#endif\n#define GLFW_HAS_GAMEPAD_API            (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api\n#define GLFW_HAS_GETKEYNAME             (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()\n\n// GLFW data\nenum GlfwClientApi\n{\n    GlfwClientApi_Unknown,\n    GlfwClientApi_OpenGL,\n    GlfwClientApi_Vulkan\n};\n\nstruct ImGui_ImplGlfw_Data\n{\n    GLFWwindow*             Window;\n    GlfwClientApi           ClientApi;\n    double                  Time;\n    GLFWwindow*             MouseWindow;\n    GLFWcursor*             MouseCursors[ImGuiMouseCursor_COUNT];\n    ImVec2                  LastValidMousePos;\n    GLFWwindow*             KeyOwnerWindows[GLFW_KEY_LAST];\n    bool                    InstalledCallbacks;\n    bool                    WantUpdateMonitors;\n#ifdef _WIN32\n    WNDPROC                 GlfwWndProc;\n#endif\n\n    // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.\n    GLFWwindowfocusfun      PrevUserCallbackWindowFocus;\n    GLFWcursorposfun        PrevUserCallbackCursorPos;\n    GLFWcursorenterfun      PrevUserCallbackCursorEnter;\n    GLFWmousebuttonfun      PrevUserCallbackMousebutton;\n    GLFWscrollfun           PrevUserCallbackScroll;\n    GLFWkeyfun              PrevUserCallbackKey;\n    GLFWcharfun             PrevUserCallbackChar;\n    GLFWmonitorfun          PrevUserCallbackMonitor;\n\n    ImGui_ImplGlfw_Data()   { memset((void*)this, 0, sizeof(*this)); }\n};\n\n// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts\n// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.\n// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.\n// - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks\n//   (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.\n// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.\n// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.\nstatic ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()\n{\n    return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;\n}\n\n// Forward Declarations\nstatic void ImGui_ImplGlfw_UpdateMonitors();\nstatic void ImGui_ImplGlfw_InitPlatformInterface();\nstatic void ImGui_ImplGlfw_ShutdownPlatformInterface();\n\n// Functions\nstatic const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)\n{\n    return glfwGetClipboardString((GLFWwindow*)user_data);\n}\n\nstatic void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)\n{\n    glfwSetClipboardString((GLFWwindow*)user_data, text);\n}\n\nstatic ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)\n{\n    switch (key)\n    {\n        case GLFW_KEY_TAB: return ImGuiKey_Tab;\n        case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;\n        case GLFW_KEY_RIGHT: return ImGuiKey_RightArrow;\n        case GLFW_KEY_UP: return ImGuiKey_UpArrow;\n        case GLFW_KEY_DOWN: return ImGuiKey_DownArrow;\n        case GLFW_KEY_PAGE_UP: return ImGuiKey_PageUp;\n        case GLFW_KEY_PAGE_DOWN: return ImGuiKey_PageDown;\n        case GLFW_KEY_HOME: return ImGuiKey_Home;\n        case GLFW_KEY_END: return ImGuiKey_End;\n        case GLFW_KEY_INSERT: return ImGuiKey_Insert;\n        case GLFW_KEY_DELETE: return ImGuiKey_Delete;\n        case GLFW_KEY_BACKSPACE: return ImGuiKey_Backspace;\n        case GLFW_KEY_SPACE: return ImGuiKey_Space;\n        case GLFW_KEY_ENTER: return ImGuiKey_Enter;\n        case GLFW_KEY_ESCAPE: return ImGuiKey_Escape;\n        case GLFW_KEY_APOSTROPHE: return ImGuiKey_Apostrophe;\n        case GLFW_KEY_COMMA: return ImGuiKey_Comma;\n        case GLFW_KEY_MINUS: return ImGuiKey_Minus;\n        case GLFW_KEY_PERIOD: return ImGuiKey_Period;\n        case GLFW_KEY_SLASH: return ImGuiKey_Slash;\n        case GLFW_KEY_SEMICOLON: return ImGuiKey_Semicolon;\n        case GLFW_KEY_EQUAL: return ImGuiKey_Equal;\n        case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket;\n        case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash;\n        case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket;\n        case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent;\n        case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock;\n        case GLFW_KEY_SCROLL_LOCK: return ImGuiKey_ScrollLock;\n        case GLFW_KEY_NUM_LOCK: return ImGuiKey_NumLock;\n        case GLFW_KEY_PRINT_SCREEN: return ImGuiKey_PrintScreen;\n        case GLFW_KEY_PAUSE: return ImGuiKey_Pause;\n        case GLFW_KEY_KP_0: return ImGuiKey_Keypad0;\n        case GLFW_KEY_KP_1: return ImGuiKey_Keypad1;\n        case GLFW_KEY_KP_2: return ImGuiKey_Keypad2;\n        case GLFW_KEY_KP_3: return ImGuiKey_Keypad3;\n        case GLFW_KEY_KP_4: return ImGuiKey_Keypad4;\n        case GLFW_KEY_KP_5: return ImGuiKey_Keypad5;\n        case GLFW_KEY_KP_6: return ImGuiKey_Keypad6;\n        case GLFW_KEY_KP_7: return ImGuiKey_Keypad7;\n        case GLFW_KEY_KP_8: return ImGuiKey_Keypad8;\n        case GLFW_KEY_KP_9: return ImGuiKey_Keypad9;\n        case GLFW_KEY_KP_DECIMAL: return ImGuiKey_KeypadDecimal;\n        case GLFW_KEY_KP_DIVIDE: return ImGuiKey_KeypadDivide;\n        case GLFW_KEY_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;\n        case GLFW_KEY_KP_SUBTRACT: return ImGuiKey_KeypadSubtract;\n        case GLFW_KEY_KP_ADD: return ImGuiKey_KeypadAdd;\n        case GLFW_KEY_KP_ENTER: return ImGuiKey_KeypadEnter;\n        case GLFW_KEY_KP_EQUAL: return ImGuiKey_KeypadEqual;\n        case GLFW_KEY_LEFT_SHIFT: return ImGuiKey_LeftShift;\n        case GLFW_KEY_LEFT_CONTROL: return ImGuiKey_LeftCtrl;\n        case GLFW_KEY_LEFT_ALT: return ImGuiKey_LeftAlt;\n        case GLFW_KEY_LEFT_SUPER: return ImGuiKey_LeftSuper;\n        case GLFW_KEY_RIGHT_SHIFT: return ImGuiKey_RightShift;\n        case GLFW_KEY_RIGHT_CONTROL: return ImGuiKey_RightCtrl;\n        case GLFW_KEY_RIGHT_ALT: return ImGuiKey_RightAlt;\n        case GLFW_KEY_RIGHT_SUPER: return ImGuiKey_RightSuper;\n        case GLFW_KEY_MENU: return ImGuiKey_Menu;\n        case GLFW_KEY_0: return ImGuiKey_0;\n        case GLFW_KEY_1: return ImGuiKey_1;\n        case GLFW_KEY_2: return ImGuiKey_2;\n        case GLFW_KEY_3: return ImGuiKey_3;\n        case GLFW_KEY_4: return ImGuiKey_4;\n        case GLFW_KEY_5: return ImGuiKey_5;\n        case GLFW_KEY_6: return ImGuiKey_6;\n        case GLFW_KEY_7: return ImGuiKey_7;\n        case GLFW_KEY_8: return ImGuiKey_8;\n        case GLFW_KEY_9: return ImGuiKey_9;\n        case GLFW_KEY_A: return ImGuiKey_A;\n        case GLFW_KEY_B: return ImGuiKey_B;\n        case GLFW_KEY_C: return ImGuiKey_C;\n        case GLFW_KEY_D: return ImGuiKey_D;\n        case GLFW_KEY_E: return ImGuiKey_E;\n        case GLFW_KEY_F: return ImGuiKey_F;\n        case GLFW_KEY_G: return ImGuiKey_G;\n        case GLFW_KEY_H: return ImGuiKey_H;\n        case GLFW_KEY_I: return ImGuiKey_I;\n        case GLFW_KEY_J: return ImGuiKey_J;\n        case GLFW_KEY_K: return ImGuiKey_K;\n        case GLFW_KEY_L: return ImGuiKey_L;\n        case GLFW_KEY_M: return ImGuiKey_M;\n        case GLFW_KEY_N: return ImGuiKey_N;\n        case GLFW_KEY_O: return ImGuiKey_O;\n        case GLFW_KEY_P: return ImGuiKey_P;\n        case GLFW_KEY_Q: return ImGuiKey_Q;\n        case GLFW_KEY_R: return ImGuiKey_R;\n        case GLFW_KEY_S: return ImGuiKey_S;\n        case GLFW_KEY_T: return ImGuiKey_T;\n        case GLFW_KEY_U: return ImGuiKey_U;\n        case GLFW_KEY_V: return ImGuiKey_V;\n        case GLFW_KEY_W: return ImGuiKey_W;\n        case GLFW_KEY_X: return ImGuiKey_X;\n        case GLFW_KEY_Y: return ImGuiKey_Y;\n        case GLFW_KEY_Z: return ImGuiKey_Z;\n        case GLFW_KEY_F1: return ImGuiKey_F1;\n        case GLFW_KEY_F2: return ImGuiKey_F2;\n        case GLFW_KEY_F3: return ImGuiKey_F3;\n        case GLFW_KEY_F4: return ImGuiKey_F4;\n        case GLFW_KEY_F5: return ImGuiKey_F5;\n        case GLFW_KEY_F6: return ImGuiKey_F6;\n        case GLFW_KEY_F7: return ImGuiKey_F7;\n        case GLFW_KEY_F8: return ImGuiKey_F8;\n        case GLFW_KEY_F9: return ImGuiKey_F9;\n        case GLFW_KEY_F10: return ImGuiKey_F10;\n        case GLFW_KEY_F11: return ImGuiKey_F11;\n        case GLFW_KEY_F12: return ImGuiKey_F12;\n        default: return ImGuiKey_None;\n    }\n}\n\nstatic int ImGui_ImplGlfw_KeyToModifier(int key)\n{\n    if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL)\n        return GLFW_MOD_CONTROL;\n    if (key == GLFW_KEY_LEFT_SHIFT || key == GLFW_KEY_RIGHT_SHIFT)\n        return GLFW_MOD_SHIFT;\n    if (key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_RIGHT_ALT)\n        return GLFW_MOD_ALT;\n    if (key == GLFW_KEY_LEFT_SUPER || key == GLFW_KEY_RIGHT_SUPER)\n        return GLFW_MOD_SUPER;\n    return 0;\n}\n\nstatic void ImGui_ImplGlfw_UpdateKeyModifiers(int mods)\n{\n    ImGuiIO& io = ImGui::GetIO();\n    io.AddKeyEvent(ImGuiMod_Ctrl, (mods & GLFW_MOD_CONTROL) != 0);\n    io.AddKeyEvent(ImGuiMod_Shift, (mods & GLFW_MOD_SHIFT) != 0);\n    io.AddKeyEvent(ImGuiMod_Alt, (mods & GLFW_MOD_ALT) != 0);\n    io.AddKeyEvent(ImGuiMod_Super, (mods & GLFW_MOD_SUPER) != 0);\n}\n\nvoid ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackMousebutton != nullptr && window == bd->Window)\n        bd->PrevUserCallbackMousebutton(window, button, action, mods);\n\n    ImGui_ImplGlfw_UpdateKeyModifiers(mods);\n\n    ImGuiIO& io = ImGui::GetIO();\n    if (button >= 0 && button < ImGuiMouseButton_COUNT)\n        io.AddMouseButtonEvent(button, action == GLFW_PRESS);\n}\n\nvoid ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackScroll != nullptr && window == bd->Window)\n        bd->PrevUserCallbackScroll(window, xoffset, yoffset);\n\n    ImGuiIO& io = ImGui::GetIO();\n    io.AddMouseWheelEvent((float)xoffset, (float)yoffset);\n}\n\nstatic int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)\n{\n#if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__)\n    // GLFW 3.1+ attempts to \"untranslate\" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.\n    // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)\n    // See https://github.com/glfw/glfw/issues/1502 for details.\n    // Adding a workaround to undo this (so our keys are translated->untranslated->translated, likely a lossy process).\n    // This won't cover edge cases but this is at least going to cover common cases.\n    if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_EQUAL)\n        return key;\n    GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);\n    const char* key_name = glfwGetKeyName(key, scancode);\n    glfwSetErrorCallback(prev_error_callback);\n#if (GLFW_VERSION_COMBINED >= 3300) // Eat errors (see #5908)\n    (void)glfwGetError(NULL);\n#endif\n    if (key_name && key_name[0] != 0 && key_name[1] == 0)\n    {\n        const char char_names[] = \"`-=[]\\\\,;\\'./\";\n        const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 };\n        IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys));\n        if (key_name[0] >= '0' && key_name[0] <= '9')               { key = GLFW_KEY_0 + (key_name[0] - '0'); }\n        else if (key_name[0] >= 'A' && key_name[0] <= 'Z')          { key = GLFW_KEY_A + (key_name[0] - 'A'); }\n        else if (key_name[0] >= 'a' && key_name[0] <= 'z')          { key = GLFW_KEY_A + (key_name[0] - 'a'); }\n        else if (const char* p = strchr(char_names, key_name[0]))   { key = char_keys[p - char_names]; }\n    }\n    // if (action == GLFW_PRESS) printf(\"key %d scancode %d name '%s'\\n\", key, scancode, key_name);\n#else\n    IM_UNUSED(scancode);\n#endif\n    return key;\n}\n\nvoid ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackKey != nullptr && window == bd->Window)\n        bd->PrevUserCallbackKey(window, keycode, scancode, action, mods);\n\n    if (action != GLFW_PRESS && action != GLFW_RELEASE)\n        return;\n\n    // Workaround: X11 does not include current pressed/released modifier key in 'mods' flags. https://github.com/glfw/glfw/issues/1630\n    if (int keycode_to_mod = ImGui_ImplGlfw_KeyToModifier(keycode))\n        mods = (action == GLFW_PRESS) ? (mods | keycode_to_mod) : (mods & ~keycode_to_mod);\n    ImGui_ImplGlfw_UpdateKeyModifiers(mods);\n\n    if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))\n        bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;\n\n    keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);\n\n    ImGuiIO& io = ImGui::GetIO();\n    ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode);\n    io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));\n    io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)\n}\n\nvoid ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackWindowFocus != nullptr && window == bd->Window)\n        bd->PrevUserCallbackWindowFocus(window, focused);\n\n    ImGuiIO& io = ImGui::GetIO();\n    io.AddFocusEvent(focused != 0);\n}\n\nvoid ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackCursorPos != nullptr && window == bd->Window)\n        bd->PrevUserCallbackCursorPos(window, x, y);\n    if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)\n        return;\n\n    ImGuiIO& io = ImGui::GetIO();\n    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)\n    {\n        int window_x, window_y;\n        glfwGetWindowPos(window, &window_x, &window_y);\n        x += window_x;\n        y += window_y;\n    }\n    io.AddMousePosEvent((float)x, (float)y);\n    bd->LastValidMousePos = ImVec2((float)x, (float)y);\n}\n\n// Workaround: X11 seems to send spurious Leave/Enter events which would make us lose our position,\n// so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984)\nvoid ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackCursorEnter != nullptr && window == bd->Window)\n        bd->PrevUserCallbackCursorEnter(window, entered);\n    if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)\n        return;\n\n    ImGuiIO& io = ImGui::GetIO();\n    if (entered)\n    {\n        bd->MouseWindow = window;\n        io.AddMousePosEvent(bd->LastValidMousePos.x, bd->LastValidMousePos.y);\n    }\n    else if (!entered && bd->MouseWindow == window)\n    {\n        bd->LastValidMousePos = io.MousePos;\n        bd->MouseWindow = nullptr;\n        io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);\n    }\n}\n\nvoid ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (bd->PrevUserCallbackChar != nullptr && window == bd->Window)\n        bd->PrevUserCallbackChar(window, c);\n\n    ImGuiIO& io = ImGui::GetIO();\n    io.AddInputCharacter(c);\n}\n\nvoid ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    bd->WantUpdateMonitors = true;\n}\n\nvoid ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    IM_ASSERT(bd->InstalledCallbacks == false && \"Callbacks already installed!\");\n    IM_ASSERT(bd->Window == window);\n\n    bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback);\n    bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback);\n    bd->PrevUserCallbackCursorPos = glfwSetCursorPosCallback(window, ImGui_ImplGlfw_CursorPosCallback);\n    bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);\n    bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);\n    bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);\n    bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);\n    bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);\n    bd->InstalledCallbacks = true;\n}\n\nvoid ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    IM_ASSERT(bd->InstalledCallbacks == true && \"Callbacks not installed!\");\n    IM_ASSERT(bd->Window == window);\n\n    glfwSetWindowFocusCallback(window, bd->PrevUserCallbackWindowFocus);\n    glfwSetCursorEnterCallback(window, bd->PrevUserCallbackCursorEnter);\n    glfwSetCursorPosCallback(window, bd->PrevUserCallbackCursorPos);\n    glfwSetMouseButtonCallback(window, bd->PrevUserCallbackMousebutton);\n    glfwSetScrollCallback(window, bd->PrevUserCallbackScroll);\n    glfwSetKeyCallback(window, bd->PrevUserCallbackKey);\n    glfwSetCharCallback(window, bd->PrevUserCallbackChar);\n    glfwSetMonitorCallback(bd->PrevUserCallbackMonitor);\n    bd->InstalledCallbacks = false;\n    bd->PrevUserCallbackWindowFocus = nullptr;\n    bd->PrevUserCallbackCursorEnter = nullptr;\n    bd->PrevUserCallbackCursorPos = nullptr;\n    bd->PrevUserCallbackMousebutton = nullptr;\n    bd->PrevUserCallbackScroll = nullptr;\n    bd->PrevUserCallbackKey = nullptr;\n    bd->PrevUserCallbackChar = nullptr;\n    bd->PrevUserCallbackMonitor = nullptr;\n}\n\nstatic bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)\n{\n    ImGuiIO& io = ImGui::GetIO();\n    IM_ASSERT(io.BackendPlatformUserData == nullptr && \"Already initialized a platform backend!\");\n    //printf(\"GLFW_VERSION: %d.%d.%d (%d)\", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);\n\n    // Setup backend capabilities flags\n    ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();\n    io.BackendPlatformUserData = (void*)bd;\n    io.BackendPlatformName = \"imgui_impl_glfw\";\n    io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;         // We can honor GetMouseCursor() values (optional)\n    io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;          // We can honor io.WantSetMousePos requests (optional, rarely used)\n    io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports;    // We can create multi-viewports on the Platform side (optional)\n#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))\n    io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)\n#endif\n\n    bd->Window = window;\n    bd->Time = 0.0;\n    bd->WantUpdateMonitors = true;\n\n    io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;\n    io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;\n    io.ClipboardUserData = bd->Window;\n\n    // Create mouse cursors\n    // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,\n    // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.\n    // Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.)\n    GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);\n    bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);\n#if GLFW_HAS_NEW_CURSORS\n    bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR);\n#else\n    bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);\n    bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);\n#endif\n    glfwSetErrorCallback(prev_error_callback);\n#if (GLFW_VERSION_COMBINED >= 3300) // Eat errors (see #5785)\n    (void)glfwGetError(NULL);\n#endif\n\n    // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.\n    if (install_callbacks)\n        ImGui_ImplGlfw_InstallCallbacks(window);\n\n    // Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)\n    ImGui_ImplGlfw_UpdateMonitors();\n    glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);\n\n    // Our mouse update function expect PlatformHandle to be filled for the main viewport\n    ImGuiViewport* main_viewport = ImGui::GetMainViewport();\n    main_viewport->PlatformHandle = (void*)bd->Window;\n#ifdef _WIN32\n    main_viewport->PlatformHandleRaw = glfwGetWin32Window(bd->Window);\n#elif defined(__APPLE__)\n    main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window);\n#endif\n    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)\n        ImGui_ImplGlfw_InitPlatformInterface();\n\n    bd->ClientApi = client_api;\n    return true;\n}\n\nbool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks)\n{\n    return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL);\n}\n\nbool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks)\n{\n    return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan);\n}\n\nbool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks)\n{\n    return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Unknown);\n}\n\nvoid ImGui_ImplGlfw_Shutdown()\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    IM_ASSERT(bd != nullptr && \"No platform backend to shutdown, or already shutdown?\");\n    ImGuiIO& io = ImGui::GetIO();\n\n    ImGui_ImplGlfw_ShutdownPlatformInterface();\n\n    if (bd->InstalledCallbacks)\n        ImGui_ImplGlfw_RestoreCallbacks(bd->Window);\n\n    for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)\n        glfwDestroyCursor(bd->MouseCursors[cursor_n]);\n\n    io.BackendPlatformName = nullptr;\n    io.BackendPlatformUserData = nullptr;\n    IM_DELETE(bd);\n}\n\nstatic void ImGui_ImplGlfw_UpdateMouseData()\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGuiIO& io = ImGui::GetIO();\n    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();\n\n    if (glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)\n    {\n        io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);\n        return;\n    }\n\n    ImGuiID mouse_viewport_id = 0;\n    const ImVec2 mouse_pos_prev = io.MousePos;\n    for (int n = 0; n < platform_io.Viewports.Size; n++)\n    {\n        ImGuiViewport* viewport = platform_io.Viewports[n];\n        GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;\n\n#ifdef __EMSCRIPTEN__\n        const bool is_window_focused = true;\n#else\n        const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;\n#endif\n        if (is_window_focused)\n        {\n            // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)\n            // When multi-viewports are enabled, all Dear ImGui positions are same as OS positions.\n            if (io.WantSetMousePos)\n                glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y));\n\n            // (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured)\n            if (bd->MouseWindow == nullptr)\n            {\n                double mouse_x, mouse_y;\n                glfwGetCursorPos(window, &mouse_x, &mouse_y);\n                if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)\n                {\n                    // Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)\n                    // Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)\n                    int window_x, window_y;\n                    glfwGetWindowPos(window, &window_x, &window_y);\n                    mouse_x += window_x;\n                    mouse_y += window_y;\n                }\n                bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y);\n                io.AddMousePosEvent((float)mouse_x, (float)mouse_y);\n            }\n        }\n\n        // (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering.\n        // If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, Dear imGui will ignore this field and infer the information using its flawed heuristic.\n        // - [X] GLFW >= 3.3 backend ON WINDOWS ONLY does correctly ignore viewports with the _NoInputs flag.\n        // - [!] GLFW <= 3.2 backend CANNOT correctly ignore viewports with the _NoInputs flag, and CANNOT reported Hovered Viewport because of mouse capture.\n        //       Some backend are not able to handle that correctly. If a backend report an hovered viewport that has the _NoInputs flag (e.g. when dragging a window\n        //       for docking, the viewport has the _NoInputs flag in order to allow us to find the viewport under), then Dear ImGui is forced to ignore the value reported\n        //       by the backend, and use its flawed heuristic to guess the viewport behind.\n        // - [X] GLFW backend correctly reports this regardless of another viewport behind focused and dragged from (we need this to find a useful drag and drop target).\n        // FIXME: This is currently only correct on Win32. See what we do below with the WM_NCHITTEST, missing an equivalent for other systems.\n        // See https://github.com/glfw/glfw/issues/1236 if you want to help in making this a GLFW feature.\n#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))\n        const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;\n#if GLFW_HAS_MOUSE_PASSTHROUGH\n        glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, window_no_input);\n#endif\n        if (glfwGetWindowAttrib(window, GLFW_HOVERED) && !window_no_input)\n            mouse_viewport_id = viewport->ID;\n#else\n        // We cannot use bd->MouseWindow maintained from CursorEnter/Leave callbacks, because it is locked to the window capturing mouse.\n#endif\n    }\n\n    if (io.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)\n        io.AddMouseViewportEvent(mouse_viewport_id);\n}\n\nstatic void ImGui_ImplGlfw_UpdateMouseCursor()\n{\n    ImGuiIO& io = ImGui::GetIO();\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)\n        return;\n\n    ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();\n    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();\n    for (int n = 0; n < platform_io.Viewports.Size; n++)\n    {\n        GLFWwindow* window = (GLFWwindow*)platform_io.Viewports[n]->PlatformHandle;\n        if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)\n        {\n            // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor\n            glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);\n        }\n        else\n        {\n            // Show OS mouse cursor\n            // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.\n            glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);\n            glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);\n        }\n    }\n}\n\n// Update gamepad inputs\nstatic inline float Saturate(float v) { return v < 0.0f ? 0.0f : v  > 1.0f ? 1.0f : v; }\nstatic void ImGui_ImplGlfw_UpdateGamepads()\n{\n    ImGuiIO& io = ImGui::GetIO();\n    if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.\n        return;\n\n    io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;\n#if GLFW_HAS_GAMEPAD_API\n    GLFWgamepadstate gamepad;\n    if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))\n        return;\n    #define MAP_BUTTON(KEY_NO, BUTTON_NO, _UNUSED)          do { io.AddKeyEvent(KEY_NO, gamepad.buttons[BUTTON_NO] != 0); } while (0)\n    #define MAP_ANALOG(KEY_NO, AXIS_NO, _UNUSED, V0, V1)    do { float v = gamepad.axes[AXIS_NO]; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0)\n#else\n    int axes_count = 0, buttons_count = 0;\n    const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);\n    const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);\n    if (axes_count == 0 || buttons_count == 0)\n        return;\n    #define MAP_BUTTON(KEY_NO, _UNUSED, BUTTON_NO)          do { io.AddKeyEvent(KEY_NO, (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS)); } while (0)\n    #define MAP_ANALOG(KEY_NO, _UNUSED, AXIS_NO, V0, V1)    do { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0)\n#endif\n    io.BackendFlags |= ImGuiBackendFlags_HasGamepad;\n    MAP_BUTTON(ImGuiKey_GamepadStart,       GLFW_GAMEPAD_BUTTON_START,          7);\n    MAP_BUTTON(ImGuiKey_GamepadBack,        GLFW_GAMEPAD_BUTTON_BACK,           6);\n    MAP_BUTTON(ImGuiKey_GamepadFaceLeft,    GLFW_GAMEPAD_BUTTON_X,              2);     // Xbox X, PS Square\n    MAP_BUTTON(ImGuiKey_GamepadFaceRight,   GLFW_GAMEPAD_BUTTON_B,              1);     // Xbox B, PS Circle\n    MAP_BUTTON(ImGuiKey_GamepadFaceUp,      GLFW_GAMEPAD_BUTTON_Y,              3);     // Xbox Y, PS Triangle\n    MAP_BUTTON(ImGuiKey_GamepadFaceDown,    GLFW_GAMEPAD_BUTTON_A,              0);     // Xbox A, PS Cross\n    MAP_BUTTON(ImGuiKey_GamepadDpadLeft,    GLFW_GAMEPAD_BUTTON_DPAD_LEFT,      13);\n    MAP_BUTTON(ImGuiKey_GamepadDpadRight,   GLFW_GAMEPAD_BUTTON_DPAD_RIGHT,     11);\n    MAP_BUTTON(ImGuiKey_GamepadDpadUp,      GLFW_GAMEPAD_BUTTON_DPAD_UP,        10);\n    MAP_BUTTON(ImGuiKey_GamepadDpadDown,    GLFW_GAMEPAD_BUTTON_DPAD_DOWN,      12);\n    MAP_BUTTON(ImGuiKey_GamepadL1,          GLFW_GAMEPAD_BUTTON_LEFT_BUMPER,    4);\n    MAP_BUTTON(ImGuiKey_GamepadR1,          GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER,   5);\n    MAP_ANALOG(ImGuiKey_GamepadL2,          GLFW_GAMEPAD_AXIS_LEFT_TRIGGER,     4,      -0.75f,  +1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadR2,          GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER,    5,      -0.75f,  +1.0f);\n    MAP_BUTTON(ImGuiKey_GamepadL3,          GLFW_GAMEPAD_BUTTON_LEFT_THUMB,     8);\n    MAP_BUTTON(ImGuiKey_GamepadR3,          GLFW_GAMEPAD_BUTTON_RIGHT_THUMB,    9);\n    MAP_ANALOG(ImGuiKey_GamepadLStickLeft,  GLFW_GAMEPAD_AXIS_LEFT_X,           0,      -0.25f,  -1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadLStickRight, GLFW_GAMEPAD_AXIS_LEFT_X,           0,      +0.25f,  +1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadLStickUp,    GLFW_GAMEPAD_AXIS_LEFT_Y,           1,      -0.25f,  -1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadLStickDown,  GLFW_GAMEPAD_AXIS_LEFT_Y,           1,      +0.25f,  +1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadRStickLeft,  GLFW_GAMEPAD_AXIS_RIGHT_X,          2,      -0.25f,  -1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadRStickRight, GLFW_GAMEPAD_AXIS_RIGHT_X,          2,      +0.25f,  +1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadRStickUp,    GLFW_GAMEPAD_AXIS_RIGHT_Y,          3,      -0.25f,  -1.0f);\n    MAP_ANALOG(ImGuiKey_GamepadRStickDown,  GLFW_GAMEPAD_AXIS_RIGHT_Y,          3,      +0.25f,  +1.0f);\n    #undef MAP_BUTTON\n    #undef MAP_ANALOG\n}\n\nstatic void ImGui_ImplGlfw_UpdateMonitors()\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();\n    int monitors_count = 0;\n    GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);\n    platform_io.Monitors.resize(0);\n    for (int n = 0; n < monitors_count; n++)\n    {\n        ImGuiPlatformMonitor monitor;\n        int x, y;\n        glfwGetMonitorPos(glfw_monitors[n], &x, &y);\n        const GLFWvidmode* vid_mode = glfwGetVideoMode(glfw_monitors[n]);\n        monitor.MainPos = monitor.WorkPos = ImVec2((float)x, (float)y);\n        monitor.MainSize = monitor.WorkSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);\n#if GLFW_HAS_MONITOR_WORK_AREA\n        int w, h;\n        glfwGetMonitorWorkarea(glfw_monitors[n], &x, &y, &w, &h);\n        if (w > 0 && h > 0) // Workaround a small GLFW issue reporting zero on monitor changes: https://github.com/glfw/glfw/pull/1761\n        {\n            monitor.WorkPos = ImVec2((float)x, (float)y);\n            monitor.WorkSize = ImVec2((float)w, (float)h);\n        }\n#endif\n#if GLFW_HAS_PER_MONITOR_DPI\n        // Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.\n        float x_scale, y_scale;\n        glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);\n        monitor.DpiScale = x_scale;\n#endif\n        platform_io.Monitors.push_back(monitor);\n    }\n    bd->WantUpdateMonitors = false;\n}\n\nvoid ImGui_ImplGlfw_NewFrame()\n{\n    ImGuiIO& io = ImGui::GetIO();\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    IM_ASSERT(bd != nullptr && \"Did you call ImGui_ImplGlfw_InitForXXX()?\");\n\n    // Setup display size (every frame to accommodate for window resizing)\n    int w, h;\n    int display_w, display_h;\n    glfwGetWindowSize(bd->Window, &w, &h);\n    glfwGetFramebufferSize(bd->Window, &display_w, &display_h);\n    io.DisplaySize = ImVec2((float)w, (float)h);\n    if (w > 0 && h > 0)\n        io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);\n    if (bd->WantUpdateMonitors)\n        ImGui_ImplGlfw_UpdateMonitors();\n\n    // Setup time step\n    double current_time = glfwGetTime();\n    io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);\n    bd->Time = current_time;\n\n    ImGui_ImplGlfw_UpdateMouseData();\n    ImGui_ImplGlfw_UpdateMouseCursor();\n\n    // Update game controllers (if enabled and available)\n    ImGui_ImplGlfw_UpdateGamepads();\n}\n\n//--------------------------------------------------------------------------------------------------------\n// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT\n// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.\n// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..\n//--------------------------------------------------------------------------------------------------------\n\n// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.\nstruct ImGui_ImplGlfw_ViewportData\n{\n    GLFWwindow* Window;\n    bool        WindowOwned;\n    int         IgnoreWindowPosEventFrame;\n    int         IgnoreWindowSizeEventFrame;\n\n    ImGui_ImplGlfw_ViewportData()  { Window = nullptr; WindowOwned = false; IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = -1; }\n    ~ImGui_ImplGlfw_ViewportData() { IM_ASSERT(Window == nullptr); }\n};\n\nstatic void ImGui_ImplGlfw_WindowCloseCallback(GLFWwindow* window)\n{\n    if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))\n        viewport->PlatformRequestClose = true;\n}\n\n// GLFW may dispatch window pos/size events after calling glfwSetWindowPos()/glfwSetWindowSize().\n// However: depending on the platform the callback may be invoked at different time:\n// - on Windows it appears to be called within the glfwSetWindowPos()/glfwSetWindowSize() call\n// - on Linux it is queued and invoked during glfwPollEvents()\n// Because the event doesn't always fire on glfwSetWindowXXX() we use a frame counter tag to only\n// ignore recent glfwSetWindowXXX() calls.\nstatic void ImGui_ImplGlfw_WindowPosCallback(GLFWwindow* window, int, int)\n{\n    if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))\n    {\n        if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData)\n        {\n            bool ignore_event = (ImGui::GetFrameCount() <= vd->IgnoreWindowPosEventFrame + 1);\n            //data->IgnoreWindowPosEventFrame = -1;\n            if (ignore_event)\n                return;\n        }\n        viewport->PlatformRequestMove = true;\n    }\n}\n\nstatic void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)\n{\n    if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))\n    {\n        if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData)\n        {\n            bool ignore_event = (ImGui::GetFrameCount() <= vd->IgnoreWindowSizeEventFrame + 1);\n            //data->IgnoreWindowSizeEventFrame = -1;\n            if (ignore_event)\n                return;\n        }\n        viewport->PlatformRequestResize = true;\n    }\n}\n\nstatic void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();\n    viewport->PlatformUserData = vd;\n\n    // GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED\n    // With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem\n    glfwWindowHint(GLFW_VISIBLE, false);\n    glfwWindowHint(GLFW_FOCUSED, false);\n#if GLFW_HAS_FOCUS_ON_SHOW\n    glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);\n #endif\n    glfwWindowHint(GLFW_DECORATED, (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? false : true);\n#if GLFW_HAS_WINDOW_TOPMOST\n    glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);\n#endif\n    GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;\n    vd->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, \"No Title Yet\", nullptr, share_window);\n    vd->WindowOwned = true;\n    viewport->PlatformHandle = (void*)vd->Window;\n#ifdef _WIN32\n    viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);\n#elif defined(__APPLE__)\n    viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(vd->Window);\n#endif\n    glfwSetWindowPos(vd->Window, (int)viewport->Pos.x, (int)viewport->Pos.y);\n\n    // Install GLFW callbacks for secondary viewports\n    glfwSetWindowFocusCallback(vd->Window, ImGui_ImplGlfw_WindowFocusCallback);\n    glfwSetCursorEnterCallback(vd->Window, ImGui_ImplGlfw_CursorEnterCallback);\n    glfwSetCursorPosCallback(vd->Window, ImGui_ImplGlfw_CursorPosCallback);\n    glfwSetMouseButtonCallback(vd->Window, ImGui_ImplGlfw_MouseButtonCallback);\n    glfwSetScrollCallback(vd->Window, ImGui_ImplGlfw_ScrollCallback);\n    glfwSetKeyCallback(vd->Window, ImGui_ImplGlfw_KeyCallback);\n    glfwSetCharCallback(vd->Window, ImGui_ImplGlfw_CharCallback);\n    glfwSetWindowCloseCallback(vd->Window, ImGui_ImplGlfw_WindowCloseCallback);\n    glfwSetWindowPosCallback(vd->Window, ImGui_ImplGlfw_WindowPosCallback);\n    glfwSetWindowSizeCallback(vd->Window, ImGui_ImplGlfw_WindowSizeCallback);\n    if (bd->ClientApi == GlfwClientApi_OpenGL)\n    {\n        glfwMakeContextCurrent(vd->Window);\n        glfwSwapInterval(0);\n    }\n}\n\nstatic void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData)\n    {\n        if (vd->WindowOwned)\n        {\n#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)\n            HWND hwnd = (HWND)viewport->PlatformHandleRaw;\n            ::RemovePropA(hwnd, \"IMGUI_VIEWPORT\");\n#endif\n\n            // Release any keys that were pressed in the window being destroyed and are still held down,\n            // because we will not receive any release events after window is destroyed.\n            for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++)\n                if (bd->KeyOwnerWindows[i] == vd->Window)\n                    ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.\n\n            glfwDestroyWindow(vd->Window);\n        }\n        vd->Window = nullptr;\n        IM_DELETE(vd);\n    }\n    viewport->PlatformUserData = viewport->PlatformHandle = nullptr;\n}\n\n// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support \"transparent inputs\".\n// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)\n#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)\nstatic LRESULT CALLBACK WndProcNoInputs(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    if (msg == WM_NCHITTEST)\n    {\n        // Let mouse pass-through the window. This will allow the backend to call io.AddMouseViewportEvent() properly (which is OPTIONAL).\n        // The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.\n        // If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in\n        // your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.\n        ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, \"IMGUI_VIEWPORT\");\n        if (viewport->Flags & ImGuiViewportFlags_NoInputs)\n            return HTTRANSPARENT;\n    }\n    return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam);\n}\n#endif\n\nstatic void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n\n#if defined(_WIN32)\n    // GLFW hack: Hide icon from task bar\n    HWND hwnd = (HWND)viewport->PlatformHandleRaw;\n    if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon)\n    {\n        LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);\n        ex_style &= ~WS_EX_APPWINDOW;\n        ex_style |= WS_EX_TOOLWINDOW;\n        ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);\n    }\n\n    // GLFW hack: install hook for WM_NCHITTEST message handler\n#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ::SetPropA(hwnd, \"IMGUI_VIEWPORT\", viewport);\n    if (bd->GlfwWndProc == nullptr)\n        bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC);\n    ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WndProcNoInputs);\n#endif\n\n#if !GLFW_HAS_FOCUS_ON_SHOW\n    // GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.\n    // The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3 via a GLFW_FOCUS_ON_SHOW window attribute.\n    // See https://github.com/glfw/glfw/issues/1189\n    // FIXME-VIEWPORT: Implement same work-around for Linux/OSX in the meanwhile.\n    if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)\n    {\n        ::ShowWindow(hwnd, SW_SHOWNA);\n        return;\n    }\n#endif\n#endif\n\n    glfwShowWindow(vd->Window);\n}\n\nstatic ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    int x = 0, y = 0;\n    glfwGetWindowPos(vd->Window, &x, &y);\n    return ImVec2((float)x, (float)y);\n}\n\nstatic void ImGui_ImplGlfw_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    vd->IgnoreWindowPosEventFrame = ImGui::GetFrameCount();\n    glfwSetWindowPos(vd->Window, (int)pos.x, (int)pos.y);\n}\n\nstatic ImVec2 ImGui_ImplGlfw_GetWindowSize(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    int w = 0, h = 0;\n    glfwGetWindowSize(vd->Window, &w, &h);\n    return ImVec2((float)w, (float)h);\n}\n\nstatic void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n#if __APPLE__ && !GLFW_HAS_OSX_WINDOW_POS_FIX\n    // Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are\n    // positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it\n    // doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based\n    // on the upper-left corner.\n    int x, y, width, height;\n    glfwGetWindowPos(vd->Window, &x, &y);\n    glfwGetWindowSize(vd->Window, &width, &height);\n    glfwSetWindowPos(vd->Window, x, y - height + size.y);\n#endif\n    vd->IgnoreWindowSizeEventFrame = ImGui::GetFrameCount();\n    glfwSetWindowSize(vd->Window, (int)size.x, (int)size.y);\n}\n\nstatic void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* title)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    glfwSetWindowTitle(vd->Window, title);\n}\n\nstatic void ImGui_ImplGlfw_SetWindowFocus(ImGuiViewport* viewport)\n{\n#if GLFW_HAS_FOCUS_WINDOW\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    glfwFocusWindow(vd->Window);\n#else\n    // FIXME: What are the effect of not having this function? At the moment imgui doesn't actually call SetWindowFocus - we set that up ahead, will answer that question later.\n    (void)viewport;\n#endif\n}\n\nstatic bool ImGui_ImplGlfw_GetWindowFocus(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    return glfwGetWindowAttrib(vd->Window, GLFW_FOCUSED) != 0;\n}\n\nstatic bool ImGui_ImplGlfw_GetWindowMinimized(ImGuiViewport* viewport)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    return glfwGetWindowAttrib(vd->Window, GLFW_ICONIFIED) != 0;\n}\n\n#if GLFW_HAS_WINDOW_ALPHA\nstatic void ImGui_ImplGlfw_SetWindowAlpha(ImGuiViewport* viewport, float alpha)\n{\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    glfwSetWindowOpacity(vd->Window, alpha);\n}\n#endif\n\nstatic void ImGui_ImplGlfw_RenderWindow(ImGuiViewport* viewport, void*)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    if (bd->ClientApi == GlfwClientApi_OpenGL)\n        glfwMakeContextCurrent(vd->Window);\n}\n\nstatic void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport, void*)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    if (bd->ClientApi == GlfwClientApi_OpenGL)\n    {\n        glfwMakeContextCurrent(vd->Window);\n        glfwSwapBuffers(vd->Window);\n    }\n}\n\n//--------------------------------------------------------------------------------------------------------\n// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)\n//--------------------------------------------------------------------------------------------------------\n\n// Avoid including <vulkan.h> so we can build without it\n#if GLFW_HAS_VULKAN\n#ifndef VULKAN_H_\n#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;\n#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)\n#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;\n#else\n#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;\n#endif\nVK_DEFINE_HANDLE(VkInstance)\nVK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)\nstruct VkAllocationCallbacks;\nenum VkResult { VK_RESULT_MAX_ENUM = 0x7FFFFFFF };\n#endif // VULKAN_H_\nextern \"C\" { extern GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); }\nstatic int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)\n{\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;\n    IM_UNUSED(bd);\n    IM_ASSERT(bd->ClientApi == GlfwClientApi_Vulkan);\n    VkResult err = glfwCreateWindowSurface((VkInstance)vk_instance, vd->Window, (const VkAllocationCallbacks*)vk_allocator, (VkSurfaceKHR*)out_vk_surface);\n    return (int)err;\n}\n#endif // GLFW_HAS_VULKAN\n\nstatic void ImGui_ImplGlfw_InitPlatformInterface()\n{\n    // Register platform interface (will be coupled with a renderer interface)\n    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();\n    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();\n    platform_io.Platform_CreateWindow = ImGui_ImplGlfw_CreateWindow;\n    platform_io.Platform_DestroyWindow = ImGui_ImplGlfw_DestroyWindow;\n    platform_io.Platform_ShowWindow = ImGui_ImplGlfw_ShowWindow;\n    platform_io.Platform_SetWindowPos = ImGui_ImplGlfw_SetWindowPos;\n    platform_io.Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos;\n    platform_io.Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize;\n    platform_io.Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize;\n    platform_io.Platform_SetWindowFocus = ImGui_ImplGlfw_SetWindowFocus;\n    platform_io.Platform_GetWindowFocus = ImGui_ImplGlfw_GetWindowFocus;\n    platform_io.Platform_GetWindowMinimized = ImGui_ImplGlfw_GetWindowMinimized;\n    platform_io.Platform_SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle;\n    platform_io.Platform_RenderWindow = ImGui_ImplGlfw_RenderWindow;\n    platform_io.Platform_SwapBuffers = ImGui_ImplGlfw_SwapBuffers;\n#if GLFW_HAS_WINDOW_ALPHA\n    platform_io.Platform_SetWindowAlpha = ImGui_ImplGlfw_SetWindowAlpha;\n#endif\n#if GLFW_HAS_VULKAN\n    platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface;\n#endif\n\n    // Register main window handle (which is owned by the main application, not by us)\n    // This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.\n    ImGuiViewport* main_viewport = ImGui::GetMainViewport();\n    ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();\n    vd->Window = bd->Window;\n    vd->WindowOwned = false;\n    main_viewport->PlatformUserData = vd;\n    main_viewport->PlatformHandle = (void*)bd->Window;\n}\n\nstatic void ImGui_ImplGlfw_ShutdownPlatformInterface()\n{\n    ImGui::DestroyPlatformWindows();\n}\n\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n"
  },
  {
    "path": "Source/External/imgui_tools/imgui_impl_glfw.h",
    "content": "// dear imgui: Platform Backend for GLFW\n// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)\n// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)\n// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)\n\n// Implemented features:\n//  [X] Platform: Clipboard support.\n//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]\n//  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.\n//  [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).\n//  [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.\n\n// Issues:\n//  [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).\n\n// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.\n// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.\n// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.\n// Read online: https://github.com/ocornut/imgui/tree/master/docs\n\n#pragma once\n#include \"imgui.h\"      // IMGUI_IMPL_API\n\nstruct GLFWwindow;\nstruct GLFWmonitor;\n\nIMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);\nIMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);\nIMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);\nIMGUI_IMPL_API void     ImGui_ImplGlfw_Shutdown();\nIMGUI_IMPL_API void     ImGui_ImplGlfw_NewFrame();\n\n// GLFW callbacks (installer)\n// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.\n// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.\nIMGUI_IMPL_API void     ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);\nIMGUI_IMPL_API void     ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);\n\n// GLFW callbacks (individual callbacks to call if you didn't install callbacks)\nIMGUI_IMPL_API void     ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);        // Since 1.84\nIMGUI_IMPL_API void     ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);        // Since 1.84\nIMGUI_IMPL_API void     ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y);   // Since 1.87\nIMGUI_IMPL_API void     ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);\nIMGUI_IMPL_API void     ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);\nIMGUI_IMPL_API void     ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);\nIMGUI_IMPL_API void     ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);\nIMGUI_IMPL_API void     ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/GraphEditor.cpp",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n#define IMGUI_DEFINE_MATH_OPERATORS\n#include \"imgui.h\"\n#include \"imgui_internal.h\"\n#include <math.h>\n#include <vector>\n#include <float.h>\n#include <array>\n#include \"GraphEditor.h\"\n\nnamespace GraphEditor {\n\nstatic inline float Distance(const ImVec2& a, const ImVec2& b)\n{\n    return sqrtf((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));\n}\n\nstatic inline float sign(float v)\n{\n    return (v >= 0.f) ? 1.f : -1.f;\n}\n\nstatic ImVec2 GetInputSlotPos(Delegate& delegate, const Node& node, SlotIndex slotIndex, float factor)\n{\n    ImVec2 Size = node.mRect.GetSize() * factor;\n    size_t InputsCount = delegate.GetTemplate(node.mTemplateIndex).mInputCount;\n    return ImVec2(node.mRect.Min.x * factor,\n                  node.mRect.Min.y * factor + Size.y * ((float)slotIndex + 1) / ((float)InputsCount + 1) + 8.f);\n}\n\nstatic ImVec2 GetOutputSlotPos(Delegate& delegate, const Node& node, SlotIndex slotIndex, float factor)\n{\n    ImVec2 Size = node.mRect.GetSize() * factor;\n    size_t OutputsCount = delegate.GetTemplate(node.mTemplateIndex).mOutputCount;\n    return ImVec2(node.mRect.Min.x * factor + Size.x,\n                  node.mRect.Min.y * factor + Size.y * ((float)slotIndex + 1) / ((float)OutputsCount + 1) + 8.f);\n}\n\nstatic ImRect GetNodeRect(const Node& node, float factor)\n{\n    ImVec2 Size = node.mRect.GetSize() * factor;\n    return ImRect(node.mRect.Min * factor, node.mRect.Min * factor + Size);\n}\n\nstatic ImVec2 editingNodeSource;\nstatic bool editingInput = false;\nstatic ImVec2 captureOffset;\n\nenum NodeOperation\n{\n    NO_None,\n    NO_EditingLink,\n    NO_QuadSelecting,\n    NO_MovingNodes,\n    NO_EditInput,\n    NO_PanView,\n};\nstatic NodeOperation nodeOperation = NO_None;\n\nstatic void HandleZoomScroll(ImRect regionRect, ViewState& viewState, const Options& options)\n{\n    ImGuiIO& io = ImGui::GetIO();\n\n    if (regionRect.Contains(io.MousePos))\n    {\n        if (io.MouseWheel < -FLT_EPSILON)\n        {\n            viewState.mFactorTarget *= 1.f - options.mZoomRatio;\n        }\n\n        if (io.MouseWheel > FLT_EPSILON)\n        {\n            viewState.mFactorTarget *= 1.0f + options.mZoomRatio;\n        }\n    }\n\n    ImVec2 mouseWPosPre = (io.MousePos - ImGui::GetCursorScreenPos()) / viewState.mFactor;\n    viewState.mFactorTarget = ImClamp(viewState.mFactorTarget, options.mMinZoom, options.mMaxZoom);\n    viewState.mFactor = ImLerp(viewState.mFactor, viewState.mFactorTarget, options.mZoomLerpFactor);\n    ImVec2 mouseWPosPost = (io.MousePos - ImGui::GetCursorScreenPos()) / viewState.mFactor;\n    if (ImGui::IsMousePosValid())\n    {\n        viewState.mPosition += mouseWPosPost - mouseWPosPre;\n    }\n}\n\nvoid GraphEditorClear()\n{\n    nodeOperation = NO_None;\n}\n\nstatic void FitNodes(Delegate& delegate, ViewState& viewState, const ImVec2 viewSize, bool selectedNodesOnly)\n{\n    const size_t nodeCount = delegate.GetNodeCount();\n\n    if (!nodeCount)\n    {\n        return;\n    }\n\n    bool validNode = false;\n    ImVec2 min(FLT_MAX, FLT_MAX);\n    ImVec2 max(-FLT_MAX, -FLT_MAX);\n    for (NodeIndex nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)\n    {\n        const Node& node = delegate.GetNode(nodeIndex);\n        \n        if (selectedNodesOnly && !node.mSelected)\n        {\n            continue;\n        }\n        \n        min = ImMin(min, node.mRect.Min);\n        min = ImMin(min, node.mRect.Max);\n        max = ImMax(max, node.mRect.Min);\n        max = ImMax(max, node.mRect.Max);\n        validNode = true;\n    }\n    \n    if (!validNode)\n    {\n        return;\n    }\n    \n    min -= viewSize * 0.05f;\n    max += viewSize * 0.05f;\n    ImVec2 nodesSize = max - min;\n    ImVec2 nodeCenter = (max + min) * 0.5f;\n    \n    float ratioY = viewSize.y / nodesSize.y;\n    float ratioX = viewSize.x / nodesSize.x;\n\n    viewState.mFactor = viewState.mFactorTarget = ImMin(ImMin(ratioY, ratioX), 1.f);\n    viewState.mPosition = ImVec2(-nodeCenter.x, -nodeCenter.y) + (viewSize * 0.5f) / viewState.mFactorTarget;\n}\n\nstatic void DisplayLinks(Delegate& delegate,\n                         ImDrawList* drawList,\n                         const ImVec2 offset,\n                         const float factor,\n                         const ImRect regionRect,\n                         NodeIndex hoveredNode,\n                         const Options& options)\n{\n    const size_t linkCount = delegate.GetLinkCount();\n    for (LinkIndex linkIndex = 0; linkIndex < linkCount; linkIndex++)\n    {\n        const auto link = delegate.GetLink(linkIndex);\n        const auto nodeInput = delegate.GetNode(link.mInputNodeIndex);\n        const auto nodeOutput = delegate.GetNode(link.mOutputNodeIndex);\n        ImVec2 p1 = offset + GetOutputSlotPos(delegate, nodeInput, link.mInputSlotIndex, factor);\n        ImVec2 p2 = offset + GetInputSlotPos(delegate, nodeOutput, link.mOutputSlotIndex, factor);\n\n        // con. view clipping\n        if ((p1.y < 0.f && p2.y < 0.f) || (p1.y > regionRect.Max.y && p2.y > regionRect.Max.y) ||\n            (p1.x < 0.f && p2.x < 0.f) || (p1.x > regionRect.Max.x && p2.x > regionRect.Max.x))\n            continue;\n\n        bool highlightCons = hoveredNode == link.mInputNodeIndex || hoveredNode == link.mOutputNodeIndex;\n        uint32_t col = delegate.GetTemplate(nodeInput.mTemplateIndex).mHeaderColor | (highlightCons ? 0xF0F0F0 : 0);\n        if (options.mDisplayLinksAsCurves)\n        {\n            // curves\n             drawList->AddBezierCubic(p1, p1 + ImVec2(50, 0) * factor, p2 + ImVec2(-50, 0) * factor, p2, 0xFF000000, options.mLineThickness * 1.5f * factor);\n             drawList->AddBezierCubic(p1, p1 + ImVec2(50, 0) * factor, p2 + ImVec2(-50, 0) * factor, p2, col, options.mLineThickness * 1.5f * factor);\n             /*\n            ImVec2 p10 = p1 + ImVec2(20.f * factor, 0.f);\n            ImVec2 p20 = p2 - ImVec2(20.f * factor, 0.f);\n\n            ImVec2 dif = p20 - p10;\n            ImVec2 p1a, p1b;\n            if (fabsf(dif.x) > fabsf(dif.y))\n            {\n                p1a = p10 + ImVec2(fabsf(fabsf(dif.x) - fabsf(dif.y)) * 0.5 * sign(dif.x), 0.f);\n                p1b = p1a + ImVec2(fabsf(dif.y) * sign(dif.x) , dif.y);\n            }\n            else\n            {\n                p1a = p10 + ImVec2(0.f, fabsf(fabsf(dif.y) - fabsf(dif.x)) * 0.5 * sign(dif.y));\n                p1b = p1a + ImVec2(dif.x, fabsf(dif.x) * sign(dif.y));\n            }\n            drawList->AddLine(p1,  p10, col, 3.f * factor);\n            drawList->AddLine(p10, p1a, col, 3.f * factor);\n            drawList->AddLine(p1a, p1b, col, 3.f * factor);\n            drawList->AddLine(p1b, p20, col, 3.f * factor);\n            drawList->AddLine(p20,  p2, col, 3.f * factor);\n            */\n        }\n        else\n        {\n            // straight lines\n            std::array<ImVec2, 6> pts;\n            int ptCount = 0;\n            ImVec2 dif = p2 - p1;\n\n            ImVec2 p1a, p1b;\n            const float limitx = 12.f * factor;\n            if (dif.x < limitx)\n            {\n                ImVec2 p10 = p1 + ImVec2(limitx, 0.f);\n                ImVec2 p20 = p2 - ImVec2(limitx, 0.f);\n\n                dif = p20 - p10;\n                p1a = p10 + ImVec2(0.f, dif.y * 0.5f);\n                p1b = p1a + ImVec2(dif.x, 0.f);\n\n                pts = { p1, p10, p1a, p1b, p20, p2 };\n                ptCount = 6;\n            }\n            else\n            {\n                if (fabsf(dif.y) < 1.f)\n                {\n                    pts = { p1, (p1 + p2) * 0.5f, p2 };\n                    ptCount = 3;\n                }\n                else\n                {\n                    if (fabsf(dif.y) < 10.f)\n                    {\n                        if (fabsf(dif.x) > fabsf(dif.y))\n                        {\n                            p1a = p1 + ImVec2(fabsf(fabsf(dif.x) - fabsf(dif.y)) * 0.5f * sign(dif.x), 0.f);\n                            p1b = p1a + ImVec2(fabsf(dif.y) * sign(dif.x), dif.y);\n                        }\n                        else\n                        {\n                            p1a = p1 + ImVec2(0.f, fabsf(fabsf(dif.y) - fabsf(dif.x)) * 0.5f * sign(dif.y));\n                            p1b = p1a + ImVec2(dif.x, fabsf(dif.x) * sign(dif.y));\n                        }\n                    }\n                    else\n                    {\n                        if (fabsf(dif.x) > fabsf(dif.y))\n                        {\n                            float d = fabsf(dif.y) * sign(dif.x) * 0.5f;\n                            p1a = p1 + ImVec2(d, dif.y * 0.5f);\n                            p1b = p1a + ImVec2(fabsf(fabsf(dif.x) - fabsf(d) * 2.f) * sign(dif.x), 0.f);\n                        }\n                        else\n                        {\n                            float d = fabsf(dif.x) * sign(dif.y) * 0.5f;\n                            p1a = p1 + ImVec2(dif.x * 0.5f, d);\n                            p1b = p1a + ImVec2(0.f, fabsf(fabsf(dif.y) - fabsf(d) * 2.f) * sign(dif.y));\n                        }\n                    }\n                    pts = { p1, p1a, p1b, p2 };\n                    ptCount = 4;\n                }\n            }\n            float highLightFactor = factor * (highlightCons ? 2.0f : 1.f);\n            for (int pass = 0; pass < 2; pass++)\n            {\n                drawList->AddPolyline(pts.data(), ptCount, pass ? col : 0xFF000000, false, (pass ? options.mLineThickness : (options.mLineThickness * 1.5f)) * highLightFactor);\n            }\n        }\n    }\n}\n\nstatic void HandleQuadSelection(Delegate& delegate, ImDrawList* drawList, const ImVec2 offset, const float factor, ImRect contentRect, const Options& options)\n{\n    if (!options.mAllowQuadSelection)\n    {\n        return;\n    }\n    ImGuiIO& io = ImGui::GetIO();\n    static ImVec2 quadSelectPos;\n    //auto& nodes = delegate->GetNodes();\n    auto nodeCount = delegate.GetNodeCount();\n\n    if (nodeOperation == NO_QuadSelecting && ImGui::IsWindowFocused())\n    {\n        const ImVec2 bmin = ImMin(quadSelectPos, io.MousePos);\n        const ImVec2 bmax = ImMax(quadSelectPos, io.MousePos);\n        drawList->AddRectFilled(bmin, bmax, options.mQuadSelection, 1.f);\n        drawList->AddRect(bmin, bmax, options.mQuadSelectionBorder, 1.f);\n        if (!io.MouseDown[0])\n        {\n            if (!io.KeyCtrl && !io.KeyShift)\n            {\n                for (size_t nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)\n                {\n                    delegate.SelectNode(nodeIndex, false);\n                }\n            }\n\n            nodeOperation = NO_None;\n            ImRect selectionRect(bmin, bmax);\n            for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)\n            {\n                const auto node = delegate.GetNode(nodeIndex);\n                ImVec2 nodeRectangleMin = offset + node.mRect.Min * factor;\n                ImVec2 nodeRectangleMax = nodeRectangleMin + node.mRect.GetSize() * factor;\n                if (selectionRect.Overlaps(ImRect(nodeRectangleMin, nodeRectangleMax)))\n                {\n                    if (io.KeyCtrl)\n                    {\n                        delegate.SelectNode(nodeIndex, false);\n                    }\n                    else\n                    {\n                        delegate.SelectNode(nodeIndex, true);\n                    }\n                }\n                else\n                {\n                    if (!io.KeyShift)\n                    {\n                        delegate.SelectNode(nodeIndex, false);\n                    }\n                }\n            }\n        }\n    }\n    else if (nodeOperation == NO_None && io.MouseDown[0] && ImGui::IsWindowFocused() &&\n             contentRect.Contains(io.MousePos))\n    {\n        nodeOperation = NO_QuadSelecting;\n        quadSelectPos = io.MousePos;\n    }\n}\n\nstatic bool HandleConnections(ImDrawList* drawList,\n                       NodeIndex nodeIndex,\n                       const ImVec2 offset,\n                       const float factor,\n                       Delegate& delegate,\n                       const Options& options,\n                       bool bDrawOnly,\n                       SlotIndex& inputSlotOver,\n                       SlotIndex& outputSlotOver,\n                       const bool inMinimap)\n{\n    static NodeIndex editingNodeIndex;\n    static SlotIndex editingSlotIndex;\n\n    ImGuiIO& io = ImGui::GetIO();\n    const auto node = delegate.GetNode(nodeIndex);\n    const auto nodeTemplate = delegate.GetTemplate(node.mTemplateIndex);\n    const auto linkCount = delegate.GetLinkCount();\n\n    size_t InputsCount = nodeTemplate.mInputCount;\n    size_t OutputsCount = nodeTemplate.mOutputCount;\n    inputSlotOver = -1;\n    outputSlotOver = -1;\n\n    // draw/use inputs/outputs\n    bool hoverSlot = false;\n    for (int i = 0; i < 2; i++)\n    {\n        float closestDistance = FLT_MAX;\n        SlotIndex closestConn = -1;\n        ImVec2 closestTextPos;\n        ImVec2 closestPos;\n        const size_t slotCount[2] = {InputsCount, OutputsCount};\n        \n        for (SlotIndex slotIndex = 0; slotIndex < slotCount[i]; slotIndex++)\n        {\n            const char** con = i ? nodeTemplate.mOutputNames : nodeTemplate.mInputNames;\n            const char* conText = (con && con[slotIndex]) ? con[slotIndex] : \"\";\n\n            ImVec2 p =\n                offset + (i ? GetOutputSlotPos(delegate, node, slotIndex, factor) : GetInputSlotPos(delegate, node, slotIndex, factor));\n            float distance = Distance(p, io.MousePos);\n            bool overCon = (nodeOperation == NO_None || nodeOperation == NO_EditingLink) &&\n                           (distance < options.mNodeSlotRadius * 2.f) && (distance < closestDistance);\n\n            \n            ImVec2 textSize;\n            textSize = ImGui::CalcTextSize(conText);\n            ImVec2 textPos =\n                p + ImVec2(-options.mNodeSlotRadius * (i ? -1.f : 1.f) * (overCon ? 3.f : 2.f) - (i ? 0 : textSize.x),\n                           -textSize.y / 2);\n\n            ImRect nodeRect = GetNodeRect(node, factor);\n            if (!inMinimap && (overCon || (nodeRect.Contains(io.MousePos - offset) && closestConn == -1 &&\n                            (editingInput == (i != 0)) && nodeOperation == NO_EditingLink)))\n            {\n                closestDistance = distance;\n                closestConn = slotIndex;\n                closestTextPos = textPos;\n                closestPos = p;\n                \n                if (i)\n                {\n                    outputSlotOver = slotIndex;\n                }\n                else\n                {\n                    inputSlotOver = slotIndex;\n                }\n            }\n            else\n            {\n               const ImU32* slotColorSource = i ? nodeTemplate.mOutputColors : nodeTemplate.mInputColors;\n               const ImU32 slotColor = slotColorSource ? slotColorSource[slotIndex] : options.mDefaultSlotColor;\n               drawList->AddCircleFilled(p, options.mNodeSlotRadius, IM_COL32(0, 0, 0, 200));\n               drawList->AddCircleFilled(p, options.mNodeSlotRadius * 0.75f, slotColor);\n               if (!options.mDrawIONameOnHover)\n               {\n                    drawList->AddText(io.FontDefault, 14, textPos + ImVec2(2, 2), IM_COL32(0, 0, 0, 255), conText);\n                    drawList->AddText(io.FontDefault, 14, textPos, IM_COL32(150, 150, 150, 255), conText);\n               }\n            }\n        }\n\n        if (closestConn != -1)\n        {\n            const char** con = i ? nodeTemplate.mOutputNames : nodeTemplate.mInputNames;\n            const char* conText = (con && con[closestConn]) ? con[closestConn] : \"\";\n            const ImU32* slotColorSource = i ? nodeTemplate.mOutputColors : nodeTemplate.mInputColors;\n            const ImU32 slotColor = slotColorSource ? slotColorSource[closestConn] : options.mDefaultSlotColor;\n            hoverSlot = true;\n            drawList->AddCircleFilled(closestPos, options.mNodeSlotRadius * options.mNodeSlotHoverFactor * 0.75f, IM_COL32(0, 0, 0, 200));\n            drawList->AddCircleFilled(closestPos, options.mNodeSlotRadius * options.mNodeSlotHoverFactor, slotColor);\n            drawList->AddText(io.FontDefault, 16, closestTextPos + ImVec2(1, 1), IM_COL32(0, 0, 0, 255), conText);\n            drawList->AddText(io.FontDefault, 16, closestTextPos, IM_COL32(250, 250, 250, 255), conText);\n            bool inputToOutput = (!editingInput && !i) || (editingInput && i);\n            if (nodeOperation == NO_EditingLink && !io.MouseDown[0] && !bDrawOnly)\n            {\n                if (inputToOutput)\n                {\n                    // check loopback\n                    Link nl;\n                    if (editingInput)\n                        nl = Link{nodeIndex, closestConn, editingNodeIndex, editingSlotIndex};\n                    else\n                        nl = Link{editingNodeIndex, editingSlotIndex, nodeIndex, closestConn};\n\n                    if (!delegate.AllowedLink(nl.mOutputNodeIndex, nl.mInputNodeIndex))\n                    {\n                        break;\n                    }\n                    bool alreadyExisting = false;\n                    for (size_t linkIndex = 0; linkIndex < linkCount; linkIndex++)\n                    {\n                        const auto link = delegate.GetLink(linkIndex);\n                        if (!memcmp(&link, &nl, sizeof(Link)))\n                        {\n                            alreadyExisting = true;\n                            break;\n                        }\n                    }\n\n                    if (!alreadyExisting)\n                    {\n                        for (int linkIndex = 0; linkIndex < linkCount; linkIndex++)\n                        {\n                            const auto link = delegate.GetLink(linkIndex);\n                            if (link.mOutputNodeIndex == nl.mOutputNodeIndex && link.mOutputSlotIndex == nl.mOutputSlotIndex)\n                            {\n                                delegate.DelLink(linkIndex);\n                                \n                                break;\n                            }\n                        }\n\n                        delegate.AddLink(nl.mInputNodeIndex, nl.mInputSlotIndex, nl.mOutputNodeIndex, nl.mOutputSlotIndex);\n                    }\n                }\n            }\n            // when ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() is uncommented, one can't click the node\n            // input/output when mouse is over the node itself.\n            if (nodeOperation == NO_None &&\n                /*ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() &&*/ io.MouseClicked[0] && !bDrawOnly)\n            {\n                nodeOperation = NO_EditingLink;\n                editingInput = i == 0;\n                editingNodeSource = closestPos;\n                editingNodeIndex = nodeIndex;\n                editingSlotIndex = closestConn;\n                if (editingInput)\n                {\n                    // remove existing link\n                    for (int linkIndex = 0; linkIndex < linkCount; linkIndex++)\n                    {\n                        const auto link = delegate.GetLink(linkIndex);\n                        if (link.mOutputNodeIndex == nodeIndex && link.mOutputSlotIndex == closestConn)\n                        {\n                            delegate.DelLink(linkIndex);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return hoverSlot;\n}\n\nstatic void DrawGrid(ImDrawList* drawList, ImVec2 windowPos, const ViewState& viewState, const ImVec2 canvasSize, ImU32 gridColor, ImU32 gridColor2, float gridSize)\n{\n    float gridSpace = gridSize * viewState.mFactor;\n    int divx = static_cast<int>(-viewState.mPosition.x / gridSize);\n    int divy = static_cast<int>(-viewState.mPosition.y / gridSize);\n    for (float x = fmodf(viewState.mPosition.x * viewState.mFactor, gridSpace); x < canvasSize.x; x += gridSpace, divx ++)\n    {\n        bool tenth = !(divx % 10);\n        drawList->AddLine(ImVec2(x, 0.0f) + windowPos, ImVec2(x, canvasSize.y) + windowPos, tenth ? gridColor2 : gridColor);\n    }\n    for (float y = fmodf(viewState.mPosition.y * viewState.mFactor, gridSpace); y < canvasSize.y; y += gridSpace, divy ++)\n    {\n        bool tenth = !(divy % 10);\n        drawList->AddLine(ImVec2(0.0f, y) + windowPos, ImVec2(canvasSize.x, y) + windowPos, tenth ? gridColor2 : gridColor);\n    }\n}\n\n// return true if node is hovered\nstatic bool DrawNode(ImDrawList* drawList,\n                     NodeIndex nodeIndex,\n                     const ImVec2 offset,\n                     const float factor,\n                     Delegate& delegate,\n                     bool overInput,\n                     const Options& options,\n                     const bool inMinimap,\n                     const ImRect& viewPort)\n{\n    ImGuiIO& io = ImGui::GetIO();\n    const auto node = delegate.GetNode(nodeIndex);\n    IM_ASSERT((node.mRect.GetWidth() != 0.f) && (node.mRect.GetHeight() != 0.f) && \"Nodes must have a non-zero rect.\");\n    const auto nodeTemplate = delegate.GetTemplate(node.mTemplateIndex);\n    const ImVec2 nodeRectangleMin = offset + node.mRect.Min * factor;\n\n    const bool old_any_active = ImGui::IsAnyItemActive();\n    ImGui::SetCursorScreenPos(nodeRectangleMin);\n    const ImVec2 nodeSize = node.mRect.GetSize() * factor;\n\n    // test nested IO\n    drawList->ChannelsSetCurrent(1); // Background\n    const size_t InputsCount = nodeTemplate.mInputCount;\n    const size_t OutputsCount = nodeTemplate.mOutputCount;\n\n    /*\n    for (int i = 0; i < 2; i++)\n    {\n        const size_t slotCount[2] = {InputsCount, OutputsCount};\n        \n        for (size_t slotIndex = 0; slotIndex < slotCount[i]; slotIndex++)\n        {\n            const char* con = i ? nodeTemplate.mOutputNames[slotIndex] : nodeTemplate.mInputNames[slotIndex];//node.mOutputs[slot_idx] : node->mInputs[slot_idx];\n            if (!delegate->IsIOPinned(nodeIndex, slot_idx, i == 1))\n            {\n               \n            }\n            continue;\n\n            ImVec2 p = offset + (i ? GetOutputSlotPos(delegate, node, slotIndex, factor) : GetInputSlotPos(delegate, node, slotIndex, factor));\n            const float arc = 28.f * (float(i) * 0.3f + 1.0f) * (i ? 1.f : -1.f);\n            const float ofs = 0.f;\n\n            ImVec2 pts[3] = {p + ImVec2(arc + ofs, 0.f), p + ImVec2(0.f + ofs, -arc), p + ImVec2(0.f + ofs, arc)};\n            drawList->AddTriangleFilled(pts[0], pts[1], pts[2], i ? 0xFFAA5030 : 0xFF30AA50);\n            drawList->AddTriangle(pts[0], pts[1], pts[2], 0xFF000000, 2.f);\n        }\n    }\n    */\n\n    ImGui::SetCursorScreenPos(nodeRectangleMin);\n    float maxHeight = ImMin(viewPort.Max.y, nodeRectangleMin.y + nodeSize.y) - nodeRectangleMin.y;\n    float maxWidth = ImMin(viewPort.Max.x, nodeRectangleMin.x + nodeSize.x) - nodeRectangleMin.x;\n    ImGui::InvisibleButton(\"node\", ImVec2(maxWidth, maxHeight));\n    // must be called right after creating the control we want to be able to move\n    bool nodeMovingActive = ImGui::IsItemActive();\n\n    // Save the size of what we have emitted and whether any of the widgets are being used\n    bool nodeWidgetsActive = (!old_any_active && ImGui::IsAnyItemActive());\n    ImVec2 nodeRectangleMax = nodeRectangleMin + nodeSize;\n\n    bool nodeHovered = false;\n    if (ImGui::IsItemHovered() && nodeOperation == NO_None && !overInput)\n    {\n        nodeHovered = true;\n    }\n\n    if (ImGui::IsWindowFocused())\n    {\n        if ((nodeWidgetsActive || nodeMovingActive) && !inMinimap)\n        {\n            if (!node.mSelected)\n            {\n                if (!io.KeyShift)\n                {\n                    const auto nodeCount = delegate.GetNodeCount();\n                    for (size_t i = 0; i < nodeCount; i++)\n                    {\n                        delegate.SelectNode(i, false);\n                    }\n                }\n                delegate.SelectNode(nodeIndex, true);\n            }\n        }\n    }\n    if (nodeMovingActive && io.MouseDown[0] && nodeHovered && !inMinimap)\n    {\n        if (nodeOperation != NO_MovingNodes)\n        {\n            nodeOperation = NO_MovingNodes;\n        }\n    }\n\n    const bool currentSelectedNode = node.mSelected;\n    const ImU32 node_bg_color = nodeHovered ? nodeTemplate.mBackgroundColorOver : nodeTemplate.mBackgroundColor;\n\n    drawList->AddRect(nodeRectangleMin,\n                      nodeRectangleMax,\n                      currentSelectedNode ? options.mSelectedNodeBorderColor : options.mNodeBorderColor,\n                      options.mRounding,\n                      ImDrawFlags_RoundCornersAll,\n                      currentSelectedNode ? options.mBorderSelectionThickness : options.mBorderThickness);\n\n    ImVec2 imgPos = nodeRectangleMin + ImVec2(14, 25);\n    ImVec2 imgSize = nodeRectangleMax + ImVec2(-5, -5) - imgPos;\n    float imgSizeComp = std::min(imgSize.x, imgSize.y);\n\n    drawList->AddRectFilled(nodeRectangleMin, nodeRectangleMax, node_bg_color, options.mRounding);\n    /*float progress = delegate->NodeProgress(nodeIndex);\n    if (progress > FLT_EPSILON && progress < 1.f - FLT_EPSILON)\n    {\n        ImVec2 progressLineA = nodeRectangleMax - ImVec2(nodeSize.x - 2.f, 3.f);\n        ImVec2 progressLineB = progressLineA + ImVec2(nodeSize.x * factor - 4.f, 0.f);\n        drawList->AddLine(progressLineA, progressLineB, 0xFF400000, 3.f);\n        drawList->AddLine(progressLineA, ImLerp(progressLineA, progressLineB, progress), 0xFFFF0000, 3.f);\n    }*/\n    ImVec2 imgPosMax = imgPos + ImVec2(imgSizeComp, imgSizeComp);\n\n    //ImVec2 imageSize = delegate->GetEvaluationSize(nodeIndex);\n    /*float imageRatio = 1.f;\n    if (imageSize.x > 0.f && imageSize.y > 0.f)\n    {\n        imageRatio = imageSize.y / imageSize.x;\n    }\n    ImVec2 quadSize = imgPosMax - imgPos;\n    ImVec2 marge(0.f, 0.f);\n    if (imageRatio > 1.f)\n    {\n        marge.x = (quadSize.x - quadSize.y / imageRatio) * 0.5f;\n    }\n    else\n    {\n        marge.y = (quadSize.y - quadSize.y * imageRatio) * 0.5f;\n    }*/\n\n    //delegate->DrawNodeImage(drawList, ImRect(imgPos, imgPosMax), marge, nodeIndex);\n\n    drawList->AddRectFilled(nodeRectangleMin,\n                            ImVec2(nodeRectangleMax.x, nodeRectangleMin.y + 20),\n                            nodeTemplate.mHeaderColor, options.mRounding);\n\n    drawList->PushClipRect(nodeRectangleMin, ImVec2(nodeRectangleMax.x, nodeRectangleMin.y + 20), true);\n    drawList->AddText(nodeRectangleMin + ImVec2(2, 2), IM_COL32(0, 0, 0, 255), node.mName);\n    drawList->PopClipRect();\n\n    ImRect customDrawRect(nodeRectangleMin + ImVec2(options.mRounding, 20 + options.mRounding), nodeRectangleMax - ImVec2(options.mRounding, options.mRounding));\n    if (customDrawRect.Max.y > customDrawRect.Min.y && customDrawRect.Max.x > customDrawRect.Min.x)\n    {\n        delegate.CustomDraw(drawList, customDrawRect, nodeIndex);\n    }\n/*\n    const ImTextureID bmpInfo = (ImTextureID)(uint64_t)delegate->GetBitmapInfo(nodeIndex).idx;\n    if (bmpInfo)\n    {\n        ImVec2 bmpInfoPos(nodeRectangleMax - ImVec2(26, 12));\n        ImVec2 bmpInfoSize(20, 20);\n        if (delegate->NodeIsCompute(nodeIndex))\n        {\n            drawList->AddImageQuad(bmpInfo,\n                                   bmpInfoPos,\n                                   bmpInfoPos + ImVec2(bmpInfoSize.x, 0.f),\n                                   bmpInfoPos + bmpInfoSize,\n                                   bmpInfoPos + ImVec2(0., bmpInfoSize.y));\n        }\n        else if (delegate->NodeIs2D(nodeIndex))\n        {\n            drawList->AddImageQuad(bmpInfo,\n                                   bmpInfoPos,\n                                   bmpInfoPos + ImVec2(bmpInfoSize.x, 0.f),\n                                   bmpInfoPos + bmpInfoSize,\n                                   bmpInfoPos + ImVec2(0., bmpInfoSize.y));\n        }\n        else if (delegate->NodeIsCubemap(nodeIndex))\n        {\n            drawList->AddImageQuad(bmpInfo,\n                                   bmpInfoPos + ImVec2(0., bmpInfoSize.y),\n                                   bmpInfoPos + bmpInfoSize,\n                                   bmpInfoPos + ImVec2(bmpInfoSize.x, 0.f),\n                                   bmpInfoPos);\n        }\n    }*/\n    return nodeHovered;\n}\n\nbool DrawMiniMap(ImDrawList* drawList, Delegate& delegate, ViewState& viewState, const Options& options, const ImVec2 windowPos, const ImVec2 canvasSize)\n{\n    if (Distance(options.mMinimap.Min, options.mMinimap.Max) <= FLT_EPSILON)\n    {\n        return false;\n    }\n\n    const size_t nodeCount = delegate.GetNodeCount();\n\n    if (!nodeCount)\n    {\n        return false;\n    }\n\n    ImVec2 min(FLT_MAX, FLT_MAX);\n    ImVec2 max(-FLT_MAX, -FLT_MAX);\n    const ImVec2 margin(50, 50);\n    for (NodeIndex nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)\n    {\n        const Node& node = delegate.GetNode(nodeIndex);\n        min = ImMin(min, node.mRect.Min - margin);\n        min = ImMin(min, node.mRect.Max + margin);\n        max = ImMax(max, node.mRect.Min - margin);\n        max = ImMax(max, node.mRect.Max + margin);\n    }\n\n    // add view in world space\n    const ImVec2 worldSizeView = canvasSize / viewState.mFactor;\n    const ImVec2 viewMin(-viewState.mPosition.x, -viewState.mPosition.y);\n    const ImVec2 viewMax = viewMin + worldSizeView;\n    min = ImMin(min, viewMin);\n    max = ImMax(max, viewMax);\n    const ImVec2 nodesSize = max - min;\n    const ImVec2 middleWorld = (min + max) * 0.5f;\n    const ImVec2 minScreen = windowPos + options.mMinimap.Min * canvasSize;\n    const ImVec2 maxScreen = windowPos + options.mMinimap.Max * canvasSize;\n    const ImVec2 viewSize = maxScreen - minScreen;\n    const ImVec2 middleScreen = (minScreen + maxScreen) * 0.5f;\n    const float ratioY = viewSize.y / nodesSize.y;\n    const float ratioX = viewSize.x / nodesSize.x;\n    const float factor = ImMin(ImMin(ratioY, ratioX), 1.f);\n\n    drawList->AddRectFilled(minScreen, maxScreen, IM_COL32(30, 30, 30, 200), 3, ImDrawFlags_RoundCornersAll);\n\n    for (NodeIndex nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)\n    {\n        const Node& node = delegate.GetNode(nodeIndex);\n        const auto nodeTemplate = delegate.GetTemplate(node.mTemplateIndex);\n\n        ImRect rect = node.mRect;\n        rect.Min -= middleWorld;\n        rect.Min *= factor;\n        rect.Min += middleScreen;\n\n        rect.Max -= middleWorld;\n        rect.Max *= factor;\n        rect.Max += middleScreen;\n\n        drawList->AddRectFilled(rect.Min, rect.Max, nodeTemplate.mBackgroundColor, 1, ImDrawFlags_RoundCornersAll);\n        if (node.mSelected)\n        {\n            drawList->AddRect(rect.Min, rect.Max, options.mSelectedNodeBorderColor, 1, ImDrawFlags_RoundCornersAll);\n        }\n    }\n\n    // add view\n    ImVec2 viewMinScreen = (viewMin - middleWorld) * factor + middleScreen;\n    ImVec2 viewMaxScreen = (viewMax - middleWorld) * factor + middleScreen;\n    drawList->AddRectFilled(viewMinScreen, viewMaxScreen, IM_COL32(255, 255, 255, 32), 1, ImDrawFlags_RoundCornersAll);\n    drawList->AddRect(viewMinScreen, viewMaxScreen, IM_COL32(255, 255, 255, 128), 1, ImDrawFlags_RoundCornersAll);\n    \n    ImGuiIO& io = ImGui::GetIO();\n    const bool mouseInMinimap = ImRect(minScreen, maxScreen).Contains(io.MousePos);\n    if (mouseInMinimap && io.MouseClicked[0])\n    {\n        const ImVec2 clickedRatio = (io.MousePos - minScreen) / viewSize;\n        const ImVec2 worldPosCenter = ImVec2(ImLerp(min.x, max.x, clickedRatio.x), ImLerp(min.y, max.y, clickedRatio.y));\n        \n        ImVec2 worldPosViewMin = worldPosCenter - worldSizeView * 0.5;\n        ImVec2 worldPosViewMax = worldPosCenter + worldSizeView * 0.5;\n        if (worldPosViewMin.x < min.x)\n        {\n            worldPosViewMin.x = min.x;\n            worldPosViewMax.x = worldPosViewMin.x + worldSizeView.x;\n        }\n        if (worldPosViewMin.y < min.y)\n        {\n            worldPosViewMin.y = min.y;\n            worldPosViewMax.y = worldPosViewMin.y + worldSizeView.y;\n        }\n        if (worldPosViewMax.x > max.x)\n        {\n            worldPosViewMax.x = max.x;\n            worldPosViewMin.x = worldPosViewMax.x - worldSizeView.x;\n        }\n        if (worldPosViewMax.y > max.y)\n        {\n            worldPosViewMax.y = max.y;\n            worldPosViewMin.y = worldPosViewMax.y - worldSizeView.y;\n        }\n        viewState.mPosition = ImVec2(-worldPosViewMin.x, -worldPosViewMin.y);\n    }\n    return mouseInMinimap;\n}\n\nvoid Show(Delegate& delegate, const Options& options, ViewState& viewState, bool enabled, FitOnScreen* fit)\n{\n    ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.f);\n    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 0.f));\n    ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.f);\n\n    const ImVec2 windowPos = ImGui::GetCursorScreenPos();\n    const ImVec2 canvasSize = ImGui::GetContentRegionAvail();\n    const ImVec2 scrollRegionLocalPos(0, 0);\n\n    ImRect regionRect(windowPos, windowPos + canvasSize);\n\n    HandleZoomScroll(regionRect, viewState, options);\n    ImVec2 offset = ImGui::GetCursorScreenPos() + viewState.mPosition * viewState.mFactor;\n    captureOffset = viewState.mPosition * viewState.mFactor;\n\n    //ImGui::InvisibleButton(\"GraphEditorButton\", canvasSize);\n    ImGui::BeginChildFrame(71711, canvasSize);\n\n    ImGui::SetCursorPos(windowPos);\n    ImGui::BeginGroup();\n\n    ImGuiIO& io = ImGui::GetIO();\n\n    // Create our child canvas\n    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1, 1));\n    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));\n    ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(30, 30, 30, 200));\n\n    ImDrawList* drawList = ImGui::GetWindowDrawList();\n    ImGui::PushClipRect(regionRect.Min, regionRect.Max, true);\n    drawList->AddRectFilled(windowPos, windowPos + canvasSize, options.mBackgroundColor);\n\n    // Background or Display grid\n    if (options.mRenderGrid)\n    {\n        DrawGrid(drawList, windowPos, viewState, canvasSize, options.mGridColor, options.mGridColor2, options.mGridSize);\n    }\n    \n    // Fit view\n    if (fit && ((*fit == Fit_AllNodes) || (*fit == Fit_SelectedNodes)))\n    {\n        FitNodes(delegate, viewState, canvasSize, (*fit == Fit_SelectedNodes));\n    }\n\n    if (enabled)\n    {\n        static NodeIndex hoveredNode = -1;\n        // Display links\n        drawList->ChannelsSplit(3);\n\n        // minimap\n        drawList->ChannelsSetCurrent(2); // minimap\n        const bool inMinimap = DrawMiniMap(drawList, delegate, viewState, options, windowPos, canvasSize);\n\n        // Focus rectangle\n        if (ImGui::IsWindowFocused())\n        {\n           drawList->AddRect(regionRect.Min, regionRect.Max, options.mFrameFocus, 1.f, 0, 2.f);\n        }\n\n        drawList->ChannelsSetCurrent(1); // Background\n\n        // Links\n        DisplayLinks(delegate, drawList, offset, viewState.mFactor, regionRect, hoveredNode, options);\n\n        // edit node link\n        if (nodeOperation == NO_EditingLink)\n        {\n            ImVec2 p1 = editingNodeSource;\n            ImVec2 p2 = io.MousePos;\n            drawList->AddLine(p1, p2, IM_COL32(200, 200, 200, 255), 3.0f);\n        }\n\n        // Display nodes\n        drawList->PushClipRect(regionRect.Min, regionRect.Max, true);\n        hoveredNode = -1;\n        \n        SlotIndex inputSlotOver = -1;\n        SlotIndex outputSlotOver = -1;\n        NodeIndex nodeOver = -1;\n\n        const auto nodeCount = delegate.GetNodeCount();\n        for (int i = 0; i < 2; i++)\n        {\n            for (NodeIndex nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)\n            {\n                //const auto* node = &nodes[nodeIndex];\n                const auto node = delegate.GetNode(nodeIndex);\n                if (node.mSelected != (i != 0))\n                {\n                    continue;\n                }\n\n                // node view clipping\n                ImRect nodeRect = GetNodeRect(node, viewState.mFactor);\n                nodeRect.Min += offset;\n                nodeRect.Max += offset;\n                if (!regionRect.Overlaps(nodeRect))\n                {\n                    continue;\n                }\n\n                ImGui::PushID((int)nodeIndex);\n                SlotIndex inputSlot = -1;\n                SlotIndex outputSlot = -1;\n\n                bool overInput = (!inMinimap) && HandleConnections(drawList, nodeIndex, offset, viewState.mFactor, delegate, options, false, inputSlot, outputSlot, inMinimap);\n\n                // shadow\n                /*\n                ImVec2 shadowOffset = ImVec2(30, 30);\n                ImVec2 shadowPivot = (nodeRect.Min + nodeRect.Max) /2.f;\n                ImVec2 shadowPointMiddle = shadowPivot + shadowOffset;\n                ImVec2 shadowPointTop = ImVec2(shadowPivot.x, nodeRect.Min.y) + shadowOffset;\n                ImVec2 shadowPointBottom = ImVec2(shadowPivot.x, nodeRect.Max.y) + shadowOffset;\n                ImVec2 shadowPointLeft = ImVec2(nodeRect.Min.x, shadowPivot.y) + shadowOffset;\n                ImVec2 shadowPointRight = ImVec2(nodeRect.Max.x, shadowPivot.y) + shadowOffset;\n\n                // top left\n                drawList->AddRectFilledMultiColor(nodeRect.Min + shadowOffset, shadowPointMiddle, IM_COL32(0 ,0, 0, 0), IM_COL32(0,0,0,0), IM_COL32(0, 0, 0, 255), IM_COL32(0, 0, 0, 0));\n\n                // top right\n                drawList->AddRectFilledMultiColor(shadowPointTop, shadowPointRight, IM_COL32(0 ,0, 0, 0), IM_COL32(0,0,0,0), IM_COL32(0, 0, 0, 0), IM_COL32(0, 0, 0, 255));\n\n                // bottom left\n                drawList->AddRectFilledMultiColor(shadowPointLeft, shadowPointBottom, IM_COL32(0 ,0, 0, 0), IM_COL32(0, 0, 0, 255), IM_COL32(0, 0, 0, 0), IM_COL32(0,0,0,0));\n\n                // bottom right\n                drawList->AddRectFilledMultiColor(shadowPointMiddle, nodeRect.Max + shadowOffset, IM_COL32(0, 0, 0, 255), IM_COL32(0 ,0, 0, 0), IM_COL32(0,0,0,0), IM_COL32(0, 0, 0, 0));\n                */\n                if (DrawNode(drawList, nodeIndex, offset, viewState.mFactor, delegate, overInput, options, inMinimap, regionRect))\n                {\n                    hoveredNode = nodeIndex;\n                }\n\n                HandleConnections(drawList, nodeIndex, offset, viewState.mFactor, delegate, options, true, inputSlot, outputSlot, inMinimap);\n                if (inputSlot != -1 || outputSlot != -1)\n                {\n                    inputSlotOver = inputSlot;\n                    outputSlotOver = outputSlot;\n                    nodeOver = nodeIndex;\n                }\n\n                ImGui::PopID();\n            }\n        }\n        \n\n        \n        drawList->PopClipRect();\n\n        if (nodeOperation == NO_MovingNodes)\n        {\n            if (ImGui::IsMouseDragging(0, 1))\n            {\n                ImVec2 delta = io.MouseDelta / viewState.mFactor;\n                if (fabsf(delta.x) >= 1.f || fabsf(delta.y) >= 1.f)\n                {\n                    delegate.MoveSelectedNodes(delta);\n                }\n            }\n        }\n\n        drawList->ChannelsSetCurrent(0);\n\n        // quad selection\n        if (!inMinimap)\n        {\n            HandleQuadSelection(delegate, drawList, offset, viewState.mFactor, regionRect, options);\n        }\n\n        drawList->ChannelsMerge();\n\n        // releasing mouse button means it's done in any operation\n        if (nodeOperation == NO_PanView)\n        {\n            if (!io.MouseDown[2])\n            {\n                nodeOperation = NO_None;\n            }\n        }\n        else if (nodeOperation != NO_None && !io.MouseDown[0])\n        {\n            nodeOperation = NO_None;\n        }\n\n        // right click\n        if (!inMinimap && nodeOperation == NO_None && regionRect.Contains(io.MousePos) &&\n                (ImGui::IsMouseClicked(1) /*|| (ImGui::IsWindowFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Tab))*/))\n        {\n            delegate.RightClick(nodeOver, inputSlotOver, outputSlotOver);\n        }\n\n        // Scrolling\n        if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && io.MouseClicked[2] && nodeOperation == NO_None)\n        {\n            nodeOperation = NO_PanView;\n        }\n        if (nodeOperation == NO_PanView)\n        {\n            viewState.mPosition += io.MouseDelta / viewState.mFactor;\n        }\n    }\n\n    ImGui::PopClipRect();\n\n    ImGui::PopStyleColor(1);\n    ImGui::PopStyleVar(2);\n    ImGui::EndGroup();\n    ImGui::EndChildFrame();\n\n    ImGui::PopStyleVar(3);\n    \n    // change fit to none\n    if (fit)\n    {\n        *fit = Fit_None;\n    }\n}\n\nbool EditOptions(Options& options)\n{\n    bool updated = false;\n    if (ImGui::CollapsingHeader(\"Colors\", nullptr))\n    {\n        ImColor backgroundColor(options.mBackgroundColor);\n        ImColor gridColor(options.mGridColor);\n        ImColor selectedNodeBorderColor(options.mSelectedNodeBorderColor);\n        ImColor nodeBorderColor(options.mNodeBorderColor);\n        ImColor quadSelection(options.mQuadSelection);\n        ImColor quadSelectionBorder(options.mQuadSelectionBorder);\n        ImColor defaultSlotColor(options.mDefaultSlotColor);\n        ImColor frameFocus(options.mFrameFocus);\n\n        updated |= ImGui::ColorEdit4(\"Background\", (float*)&backgroundColor);\n        updated |= ImGui::ColorEdit4(\"Grid\", (float*)&gridColor);\n        updated |= ImGui::ColorEdit4(\"Selected Node Border\", (float*)&selectedNodeBorderColor);\n        updated |= ImGui::ColorEdit4(\"Node Border\", (float*)&nodeBorderColor);\n        updated |= ImGui::ColorEdit4(\"Quad Selection\", (float*)&quadSelection);\n        updated |= ImGui::ColorEdit4(\"Quad Selection Border\", (float*)&quadSelectionBorder);\n        updated |= ImGui::ColorEdit4(\"Default Slot\", (float*)&defaultSlotColor);\n        updated |= ImGui::ColorEdit4(\"Frame when has focus\", (float*)&frameFocus);\n\n        options.mBackgroundColor = backgroundColor;\n        options.mGridColor = gridColor;\n        options.mSelectedNodeBorderColor = selectedNodeBorderColor;\n        options.mNodeBorderColor = nodeBorderColor;\n        options.mQuadSelection = quadSelection;\n        options.mQuadSelectionBorder = quadSelectionBorder;\n        options.mDefaultSlotColor = defaultSlotColor;\n        options.mFrameFocus = frameFocus;\n    }\n\n    if (ImGui::CollapsingHeader(\"Options\", nullptr))\n    {\n        updated |= ImGui::InputFloat4(\"Minimap\", &options.mMinimap.Min.x);\n        updated |= ImGui::InputFloat(\"Line Thickness\", &options.mLineThickness);\n        updated |= ImGui::InputFloat(\"Grid Size\", &options.mGridSize);\n        updated |= ImGui::InputFloat(\"Rounding\", &options.mRounding);\n        updated |= ImGui::InputFloat(\"Zoom Ratio\", &options.mZoomRatio);\n        updated |= ImGui::InputFloat(\"Zoom Lerp Factor\", &options.mZoomLerpFactor);\n        updated |= ImGui::InputFloat(\"Border Selection Thickness\", &options.mBorderSelectionThickness);\n        updated |= ImGui::InputFloat(\"Border Thickness\", &options.mBorderThickness);\n        updated |= ImGui::InputFloat(\"Slot Radius\", &options.mNodeSlotRadius);\n        updated |= ImGui::InputFloat(\"Slot Hover Factor\", &options.mNodeSlotHoverFactor);\n        updated |= ImGui::InputFloat2(\"Zoom min/max\", &options.mMinZoom);\n        updated |= ImGui::InputFloat(\"Slot Hover Factor\", &options.mSnap);\n        \n        if (ImGui::RadioButton(\"Curved Links\", options.mDisplayLinksAsCurves))\n        {\n            options.mDisplayLinksAsCurves = !options.mDisplayLinksAsCurves;\n            updated = true;\n        }\n        if (ImGui::RadioButton(\"Straight Links\", !options.mDisplayLinksAsCurves))\n        {\n            options.mDisplayLinksAsCurves = !options.mDisplayLinksAsCurves;\n            updated = true;\n        }\n\n        updated |= ImGui::Checkbox(\"Allow Quad Selection\", &options.mAllowQuadSelection);\n        updated |= ImGui::Checkbox(\"Render Grid\", &options.mRenderGrid);\n        updated |= ImGui::Checkbox(\"Draw IO names on hover\", &options.mDrawIONameOnHover);\n    }\n\n    return updated;\n}\n\n} // namespace\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/GraphEditor.h",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#pragma once\n\n#include <vector>\n#include <stdint.h>\n#include <string>\n#include \"imgui.h\"\n#include \"imgui_internal.h\"\n\nnamespace GraphEditor {\n\ntypedef size_t NodeIndex;\ntypedef size_t SlotIndex;\ntypedef size_t LinkIndex;\ntypedef size_t TemplateIndex;\n\n// Force the view to be respositionned and zoom to fit nodes with Show function.\n// Parameter value will be changed to Fit_None by the function.\nenum FitOnScreen\n{\n    Fit_None,\n    Fit_AllNodes,\n    Fit_SelectedNodes\n};\n\n// Display options and colors\nstruct Options\n{\n    ImRect mMinimap{{0.75f, 0.8f, 0.99f, 0.99f}}; // rectangle coordinates of minimap\n    ImU32 mBackgroundColor{ IM_COL32(40, 40, 40, 255) }; // full background color\n    ImU32 mGridColor{ IM_COL32(0, 0, 0, 60) }; // grid lines color\n    ImU32 mGridColor2{ IM_COL32(0, 0, 0, 160) }; // grid lines color every 10th\n    ImU32 mSelectedNodeBorderColor{ IM_COL32(255, 130, 30, 255) }; // node border color when it's selected\n    ImU32 mNodeBorderColor{ IM_COL32(100, 100, 100, 0) }; // node border color when it's not selected\n    ImU32 mQuadSelection{ IM_COL32(255, 32, 32, 64) }; // quad selection inside color\n    ImU32 mQuadSelectionBorder{ IM_COL32(255, 32, 32, 255) }; // quad selection border color\n    ImU32 mDefaultSlotColor{ IM_COL32(128, 128, 128, 255) }; // when no color is provided in node template, use this value\n    ImU32 mFrameFocus{ IM_COL32(64, 128, 255, 255) }; // rectangle border when graph editor has focus\n    float mLineThickness{ 5 }; // links width in pixels when zoom value is 1\n    float mGridSize{ 64.f }; // background grid size in pixels when zoom value is 1\n    float mRounding{ 3.f }; // rounding at node corners\n    float mZoomRatio{ 0.1f }; // factor per mouse wheel delta\n    float mZoomLerpFactor{ 0.25f }; // the smaller, the smoother\n    float mBorderSelectionThickness{ 6.f }; // thickness of selection border around nodes\n    float mBorderThickness{ 6.f }; // thickness of selection border around nodes\n    float mNodeSlotRadius{ 8.f }; // circle radius for inputs and outputs\n    float mNodeSlotHoverFactor{ 1.2f }; // increase size when hovering\n    float mMinZoom{ 0.2f }, mMaxZoom { 1.1f };\n    float mSnap{ 5.f };\n    bool mDisplayLinksAsCurves{ true }; // false is straight and 45deg lines\n    bool mAllowQuadSelection{ true }; // multiple selection using drag and drop\n    bool mRenderGrid{ true }; // grid or nothing\n    bool mDrawIONameOnHover{ true }; // only draw node input/output when hovering\n};\n\n// View state: scroll position and zoom factor\nstruct ViewState\n{\n    ImVec2 mPosition{0.0f, 0.0f}; // scroll position\n    float mFactor{ 1.0f }; // current zoom factor\n    float mFactorTarget{ 1.0f }; // targeted zoom factor interpolated using Options.mZoomLerpFactor\n};\n\nstruct Template\n{\n    ImU32 mHeaderColor;\n    ImU32 mBackgroundColor;\n    ImU32 mBackgroundColorOver;\n    ImU8 mInputCount;\n    const char** mInputNames; // can be nullptr. No text displayed.\n    ImU32* mInputColors; // can be nullptr, default slot color will be used.\n    ImU8 mOutputCount;\n    const char** mOutputNames; // can be nullptr. No text displayed.\n    ImU32* mOutputColors; // can be nullptr, default slot color will be used.\n};\n\nstruct Node\n{\n    const char* mName;\n    TemplateIndex mTemplateIndex;\n    ImRect mRect;\n    bool mSelected{ false };\n};\n\nstruct Link\n{\n    NodeIndex mInputNodeIndex;\n    SlotIndex mInputSlotIndex;\n    NodeIndex mOutputNodeIndex;\n    SlotIndex mOutputSlotIndex;\n};\n\nstruct Delegate\n{\n    virtual bool AllowedLink(NodeIndex from, NodeIndex to) = 0;\n\n    virtual void SelectNode(NodeIndex nodeIndex, bool selected) = 0;\n    virtual void MoveSelectedNodes(const ImVec2 delta) = 0;\n    \n    virtual void AddLink(NodeIndex inputNodeIndex, SlotIndex inputSlotIndex, NodeIndex outputNodeIndex, SlotIndex outputSlotIndex) = 0;\n    virtual void DelLink(LinkIndex linkIndex) = 0;\n    \n    // user is responsible for clipping\n    virtual void CustomDraw(ImDrawList* drawList, ImRect rectangle, NodeIndex nodeIndex) = 0;\n    \n    // use mouse position to open context menu\n    // if nodeIndex != -1, right click happens on the specified node\n    virtual void RightClick(NodeIndex nodeIndex, SlotIndex slotIndexInput, SlotIndex slotIndexOutput) = 0;\n\n    virtual const size_t GetTemplateCount() = 0;\n    virtual const Template GetTemplate(TemplateIndex index) = 0;\n\n    virtual const size_t GetNodeCount() = 0;\n    virtual const Node GetNode(NodeIndex index) = 0;\n    \n    virtual const size_t GetLinkCount() = 0;\n    virtual const Link GetLink(LinkIndex index) = 0;\n};\n\nvoid Show(Delegate& delegate, const Options& options, ViewState& viewState, bool enabled, FitOnScreen* fit = nullptr);\nvoid GraphEditorClear();\n\nbool EditOptions(Options& options);\n\n} // namespace\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImCurveEdit.cpp",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#include \"ImCurveEdit.h\"\n#include \"imgui.h\"\n#include \"imgui_internal.h\"\n#include <stdint.h>\n#include <set>\n#include <vector>\n\n#if defined(_MSC_VER) || defined(__MINGW32__)\n#include <malloc.h>\n#endif\n#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)\n#define _malloca(x) alloca(x)\n#define _freea(x)\n#endif\n\nnamespace ImCurveEdit\n{\n\n#ifndef IMGUI_DEFINE_MATH_OPERATORS\n   static ImVec2 operator+(const ImVec2& a, const ImVec2& b) {\n      return ImVec2(a.x + b.x, a.y + b.y);\n   }\n\n   static ImVec2 operator-(const ImVec2& a, const ImVec2& b) {\n      return ImVec2(a.x - b.x, a.y - b.y);\n   }\n\n   static ImVec2 operator*(const ImVec2& a, const ImVec2& b) {\n      return ImVec2(a.x * b.x, a.y * b.y);\n   }\n\n   static ImVec2 operator/(const ImVec2& a, const ImVec2& b) {\n      return ImVec2(a.x / b.x, a.y / b.y);\n   }\n\n   static ImVec2 operator*(const ImVec2& a, const float b) {\n      return ImVec2(a.x * b, a.y * b);\n   }\n#endif\n\n   static float smoothstep(float edge0, float edge1, float x)\n   {\n      x = ImClamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);\n      return x * x * (3 - 2 * x);\n   }\n\n   static float distance(float x, float y, float x1, float y1, float x2, float y2)\n   {\n      float A = x - x1;\n      float B = y - y1;\n      float C = x2 - x1;\n      float D = y2 - y1;\n\n      float dot = A * C + B * D;\n      float len_sq = C * C + D * D;\n      float param = -1.f;\n      if (len_sq > FLT_EPSILON)\n         param = dot / len_sq;\n\n      float xx, yy;\n\n      if (param < 0.f) {\n         xx = x1;\n         yy = y1;\n      }\n      else if (param > 1.f) {\n         xx = x2;\n         yy = y2;\n      }\n      else {\n         xx = x1 + param * C;\n         yy = y1 + param * D;\n      }\n\n      float dx = x - xx;\n      float dy = y - yy;\n      return sqrtf(dx * dx + dy * dy);\n   }\n\n   static int DrawPoint(ImDrawList* draw_list, ImVec2 pos, const ImVec2 size, const ImVec2 offset, bool edited)\n   {\n      int ret = 0;\n      ImGuiIO& io = ImGui::GetIO();\n\n      static const ImVec2 localOffsets[4] = { ImVec2(1,0), ImVec2(0,1), ImVec2(-1,0), ImVec2(0,-1) };\n      ImVec2 offsets[4];\n      for (int i = 0; i < 4; i++)\n      {\n         offsets[i] = pos * size + localOffsets[i] * 4.5f + offset;\n      }\n\n      const ImVec2 center = pos * size + offset;\n      const ImRect anchor(center - ImVec2(5, 5), center + ImVec2(5, 5));\n      draw_list->AddConvexPolyFilled(offsets, 4, 0xFF000000);\n      if (anchor.Contains(io.MousePos))\n      {\n         ret = 1;\n         if (io.MouseDown[0])\n            ret = 2;\n      }\n      if (edited)\n         draw_list->AddPolyline(offsets, 4, 0xFFFFFFFF, true, 3.0f);\n      else if (ret)\n         draw_list->AddPolyline(offsets, 4, 0xFF80B0FF, true, 2.0f);\n      else\n         draw_list->AddPolyline(offsets, 4, 0xFF0080FF, true, 2.0f);\n\n      return ret;\n   }\n\n   int Edit(Delegate& delegate, const ImVec2& size, unsigned int id, const ImRect* clippingRect, ImVector<EditPoint>* selectedPoints)\n   {\n      static bool selectingQuad = false;\n      static ImVec2 quadSelection;\n      static int overCurve = -1;\n      static int movingCurve = -1;\n      static bool scrollingV = false;\n      static std::set<EditPoint> selection;\n      static bool overSelectedPoint = false;\n\n      int ret = 0;\n\n      ImGuiIO& io = ImGui::GetIO();\n      ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));\n      ImGui::PushStyleColor(ImGuiCol_Border, 0);\n      ImGui::BeginChildFrame(id, size);\n      delegate.focused = ImGui::IsWindowFocused();\n      ImDrawList* draw_list = ImGui::GetWindowDrawList();\n      if (clippingRect)\n         draw_list->PushClipRect(clippingRect->Min, clippingRect->Max, true);\n\n      const ImVec2 offset = ImGui::GetCursorScreenPos() + ImVec2(0.f, size.y);\n      const ImVec2 ssize(size.x, -size.y);\n      const ImRect container(offset + ImVec2(0.f, ssize.y), offset + ImVec2(ssize.x, 0.f));\n      ImVec2& min = delegate.GetMin();\n      ImVec2& max = delegate.GetMax();\n\n      // handle zoom and VScroll\n      if (container.Contains(io.MousePos))\n      {\n         if (fabsf(io.MouseWheel) > FLT_EPSILON)\n         {\n            const float r = (io.MousePos.y - offset.y) / ssize.y;\n            float ratioY = ImLerp(min.y, max.y, r);\n            auto scaleValue = [&](float v) {\n               v -= ratioY;\n               v *= (1.f - io.MouseWheel * 0.05f);\n               v += ratioY;\n               return v;\n            };\n            min.y = scaleValue(min.y);\n            max.y = scaleValue(max.y);\n         }\n         if (!scrollingV && ImGui::IsMouseDown(2))\n         {\n            scrollingV = true;\n         }\n      }\n      ImVec2 range = max - min + ImVec2(1.f, 0.f);  // +1 because of inclusive last frame\n\n      const ImVec2 viewSize(size.x, -size.y);\n      const ImVec2 sizeOfPixel = ImVec2(1.f, 1.f) / viewSize;\n      const size_t curveCount = delegate.GetCurveCount();\n\n      if (scrollingV)\n      {\n         float deltaH = io.MouseDelta.y * range.y * sizeOfPixel.y;\n         min.y -= deltaH;\n         max.y -= deltaH;\n         if (!ImGui::IsMouseDown(2))\n            scrollingV = false;\n      }\n\n      draw_list->AddRectFilled(offset, offset + ssize, delegate.GetBackgroundColor());\n\n      auto pointToRange = [&](ImVec2 pt) { return (pt - min) / range; };\n      auto rangeToPoint = [&](ImVec2 pt) { return (pt * range) + min; };\n\n      draw_list->AddLine(ImVec2(-1.f, -min.y / range.y) * viewSize + offset, ImVec2(1.f, -min.y / range.y) * viewSize + offset, 0xFF000000, 1.5f);\n      bool overCurveOrPoint = false;\n\n      int localOverCurve = -1;\n      // make sure highlighted curve is rendered last\n      int* curvesIndex = (int*)_malloca(sizeof(int) * curveCount);\n      for (size_t c = 0; c < curveCount; c++)\n         curvesIndex[c] = int(c);\n      int highLightedCurveIndex = -1;\n      if (overCurve != -1 && curveCount)\n      {\n         ImSwap(curvesIndex[overCurve], curvesIndex[curveCount - 1]);\n         highLightedCurveIndex = overCurve;\n      }\n\n      for (size_t cur = 0; cur < curveCount; cur++)\n      {\n         int c = curvesIndex[cur];\n         if (!delegate.IsVisible(c))\n            continue;\n         const size_t ptCount = delegate.GetPointCount(c);\n         if (ptCount < 1)\n            continue;\n         CurveType curveType = delegate.GetCurveType(c);\n         if (curveType == CurveNone)\n            continue;\n         const ImVec2* pts = delegate.GetPoints(c);\n         uint32_t curveColor = delegate.GetCurveColor(c);\n         if ((c == highLightedCurveIndex && selection.empty() && !selectingQuad) || movingCurve == c)\n            curveColor = 0xFFFFFFFF;\n\n         for (size_t p = 0; p < ptCount - 1; p++)\n         {\n            const ImVec2 p1 = pointToRange(pts[p]);\n            const ImVec2 p2 = pointToRange(pts[p + 1]);\n\n            if (curveType == CurveSmooth || curveType == CurveLinear)\n            {\n               size_t subStepCount = (curveType == CurveSmooth) ? 20 : 2;\n               float step = 1.f / float(subStepCount - 1);\n               for (size_t substep = 0; substep < subStepCount - 1; substep++)\n               {\n                  float t = float(substep) * step;\n\n                  const ImVec2 sp1 = ImLerp(p1, p2, t);\n                  const ImVec2 sp2 = ImLerp(p1, p2, t + step);\n\n                  const float rt1 = smoothstep(p1.x, p2.x, sp1.x);\n                  const float rt2 = smoothstep(p1.x, p2.x, sp2.x);\n\n                  const ImVec2 pos1 = ImVec2(sp1.x, ImLerp(p1.y, p2.y, rt1)) * viewSize + offset;\n                  const ImVec2 pos2 = ImVec2(sp2.x, ImLerp(p1.y, p2.y, rt2)) * viewSize + offset;\n\n                  if (distance(io.MousePos.x, io.MousePos.y, pos1.x, pos1.y, pos2.x, pos2.y) < 8.f && !scrollingV)\n                  {\n                     localOverCurve = int(c);\n                     overCurve = int(c);\n                     overCurveOrPoint = true;\n                  }\n\n                  draw_list->AddLine(pos1, pos2, curveColor, 1.3f);\n               } // substep\n            }\n            else if (curveType == CurveDiscrete)\n            {\n               ImVec2 dp1 = p1 * viewSize + offset;\n               ImVec2 dp2 = ImVec2(p2.x, p1.y) * viewSize + offset;\n               ImVec2 dp3 = p2 * viewSize + offset;\n               draw_list->AddLine(dp1, dp2, curveColor, 1.3f);\n               draw_list->AddLine(dp2, dp3, curveColor, 1.3f);\n\n               if ((distance(io.MousePos.x, io.MousePos.y, dp1.x, dp1.y, dp3.x, dp1.y) < 8.f ||\n                  distance(io.MousePos.x, io.MousePos.y, dp3.x, dp1.y, dp3.x, dp3.y) < 8.f)\n                  /*&& localOverCurve == -1*/)\n               {\n                  localOverCurve = int(c);\n                  overCurve = int(c);\n                  overCurveOrPoint = true;\n               }\n            }\n         } // point loop\n\n         for (size_t p = 0; p < ptCount; p++)\n         {\n            const int drawState = DrawPoint(draw_list, pointToRange(pts[p]), viewSize, offset, (selection.find({ int(c), int(p) }) != selection.end() && movingCurve == -1 && !scrollingV));\n            if (drawState && movingCurve == -1 && !selectingQuad)\n            {\n               overCurveOrPoint = true;\n               overSelectedPoint = true;\n               overCurve = -1;\n               if (drawState == 2)\n               {\n                  if (!io.KeyShift && selection.find({ int(c), int(p) }) == selection.end())\n                     selection.clear();\n                  selection.insert({ int(c), int(p) });\n               }\n            }\n         }\n      } // curves loop\n\n      if (localOverCurve == -1)\n         overCurve = -1;\n\n      // move selection\n      static bool pointsMoved = false;\n      static ImVec2 mousePosOrigin;\n      static std::vector<ImVec2> originalPoints;\n      if (overSelectedPoint && io.MouseDown[0])\n      {\n         if ((fabsf(io.MouseDelta.x) > 0.f || fabsf(io.MouseDelta.y) > 0.f) && !selection.empty())\n         {\n            if (!pointsMoved)\n            {\n               delegate.BeginEdit(0);\n               mousePosOrigin = io.MousePos;\n               originalPoints.resize(selection.size());\n               int index = 0;\n               for (auto& sel : selection)\n               {\n                  const ImVec2* pts = delegate.GetPoints(sel.curveIndex);\n                  originalPoints[index++] = pts[sel.pointIndex];\n               }\n            }\n            pointsMoved = true;\n            ret = 1;\n            auto prevSelection = selection;\n            int originalIndex = 0;\n            for (auto& sel : prevSelection)\n            {\n               const ImVec2 p = rangeToPoint(pointToRange(originalPoints[originalIndex]) + (io.MousePos - mousePosOrigin) * sizeOfPixel);\n               const int newIndex = delegate.EditPoint(sel.curveIndex, sel.pointIndex, p);\n               if (newIndex != sel.pointIndex)\n               {\n                  selection.erase(sel);\n                  selection.insert({ sel.curveIndex, newIndex });\n               }\n               originalIndex++;\n            }\n         }\n      }\n\n      if (overSelectedPoint && !io.MouseDown[0])\n      {\n         overSelectedPoint = false;\n         if (pointsMoved)\n         {\n            pointsMoved = false;\n            delegate.EndEdit();\n         }\n      }\n\n      // add point\n      if (overCurve != -1 && io.MouseDoubleClicked[0])\n      {\n         const ImVec2 np = rangeToPoint((io.MousePos - offset) / viewSize);\n         delegate.BeginEdit(overCurve);\n         delegate.AddPoint(overCurve, np);\n         delegate.EndEdit();\n         ret = 1;\n      }\n\n      // move curve\n\n      if (movingCurve != -1)\n      {\n         const size_t ptCount = delegate.GetPointCount(movingCurve);\n         const ImVec2* pts = delegate.GetPoints(movingCurve);\n         if (!pointsMoved)\n         {\n            mousePosOrigin = io.MousePos;\n            pointsMoved = true;\n            originalPoints.resize(ptCount);\n            for (size_t index = 0; index < ptCount; index++)\n            {\n               originalPoints[index] = pts[index];\n            }\n         }\n         if (ptCount >= 1)\n         {\n            for (size_t p = 0; p < ptCount; p++)\n            {\n               delegate.EditPoint(movingCurve, int(p), rangeToPoint(pointToRange(originalPoints[p]) + (io.MousePos - mousePosOrigin) * sizeOfPixel));\n            }\n            ret = 1;\n         }\n         if (!io.MouseDown[0])\n         {\n            movingCurve = -1;\n            pointsMoved = false;\n            delegate.EndEdit();\n         }\n      }\n      if (movingCurve == -1 && overCurve != -1 && ImGui::IsMouseClicked(0) && selection.empty() && !selectingQuad)\n      {\n         movingCurve = overCurve;\n         delegate.BeginEdit(overCurve);\n      }\n\n      // quad selection\n      if (selectingQuad)\n      {\n         const ImVec2 bmin = ImMin(quadSelection, io.MousePos);\n         const ImVec2 bmax = ImMax(quadSelection, io.MousePos);\n         draw_list->AddRectFilled(bmin, bmax, 0x40FF0000, 1.f);\n         draw_list->AddRect(bmin, bmax, 0xFFFF0000, 1.f);\n         const ImRect selectionQuad(bmin, bmax);\n         if (!io.MouseDown[0])\n         {\n            if (!io.KeyShift)\n               selection.clear();\n            // select everythnig is quad\n            for (size_t c = 0; c < curveCount; c++)\n            {\n               if (!delegate.IsVisible(c))\n                  continue;\n\n               const size_t ptCount = delegate.GetPointCount(c);\n               if (ptCount < 1)\n                  continue;\n\n               const ImVec2* pts = delegate.GetPoints(c);\n               for (size_t p = 0; p < ptCount; p++)\n               {\n                  const ImVec2 center = pointToRange(pts[p]) * viewSize + offset;\n                  if (selectionQuad.Contains(center))\n                     selection.insert({ int(c), int(p) });\n               }\n            }\n            // done\n            selectingQuad = false;\n         }\n      }\n      if (!overCurveOrPoint && ImGui::IsMouseClicked(0) && !selectingQuad && movingCurve == -1 && !overSelectedPoint && container.Contains(io.MousePos))\n      {\n         selectingQuad = true;\n         quadSelection = io.MousePos;\n      }\n      if (clippingRect)\n         draw_list->PopClipRect();\n\n      ImGui::EndChildFrame();\n      ImGui::PopStyleVar();\n      ImGui::PopStyleColor(1);\n\n      if (selectedPoints)\n      {\n         selectedPoints->resize(int(selection.size()));\n         int index = 0;\n         for (auto& point : selection)\n            (*selectedPoints)[index++] = point;\n      }\n      return ret;\n   }\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImCurveEdit.h",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#pragma once\n#include <stdint.h>\n#include \"imgui.h\"\n\nstruct ImRect;\n\nnamespace ImCurveEdit\n{\n   enum CurveType\n   {\n      CurveNone,\n      CurveDiscrete,\n      CurveLinear,\n      CurveSmooth,\n      CurveBezier,\n   };\n\n   struct EditPoint\n   {\n      int curveIndex;\n      int pointIndex;\n      bool operator <(const EditPoint& other) const\n      {\n         if (curveIndex < other.curveIndex)\n            return true;\n         if (curveIndex > other.curveIndex)\n            return false;\n\n         if (pointIndex < other.pointIndex)\n            return true;\n         return false;\n      }\n   };\n\n   struct Delegate\n   {\n      bool focused = false;\n      virtual size_t GetCurveCount() = 0;\n      virtual bool IsVisible(size_t /*curveIndex*/) { return true; }\n      virtual CurveType GetCurveType(size_t /*curveIndex*/) const { return CurveLinear; }\n      virtual ImVec2& GetMin() = 0;\n      virtual ImVec2& GetMax() = 0;\n      virtual size_t GetPointCount(size_t curveIndex) = 0;\n      virtual uint32_t GetCurveColor(size_t curveIndex) = 0;\n      virtual ImVec2* GetPoints(size_t curveIndex) = 0;\n      virtual int EditPoint(size_t curveIndex, int pointIndex, ImVec2 value) = 0;\n      virtual void AddPoint(size_t curveIndex, ImVec2 value) = 0;\n      virtual unsigned int GetBackgroundColor() { return 0xFF202020; }\n      // handle undo/redo thru this functions\n      virtual void BeginEdit(int /*index*/) {}\n      virtual void EndEdit() {}\n   };\n\n   int Edit(Delegate& delegate, const ImVec2& size, unsigned int id, const ImRect* clippingRect = NULL, ImVector<EditPoint>* selectedPoints = NULL);\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImGradient.cpp",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#include \"ImGradient.h\"\n#include \"imgui.h\"\n#include \"imgui_internal.h\"\n\nnamespace ImGradient\n{\n#ifndef IMGUI_DEFINE_MATH_OPERATORS\n   static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }\n   static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }\n   static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }\n   static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }\n   static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }\n   static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }\n#endif\n\n   static int DrawPoint(ImDrawList* draw_list, ImVec4 color, const ImVec2 size, bool editing, ImVec2 pos)\n   {\n      ImGuiIO& io = ImGui::GetIO();\n\n      ImVec2 p1 = ImLerp(pos, ImVec2(pos + ImVec2(size.x - size.y, 0.f)), color.w) + ImVec2(3, 3);\n      ImVec2 p2 = ImLerp(pos + ImVec2(size.y, size.y), ImVec2(pos + size), color.w) - ImVec2(3, 3);\n      ImRect rc(p1, p2);\n\n      color.w = 1.f;\n      draw_list->AddRectFilled(p1, p2, ImColor(color));\n      if (editing)\n         draw_list->AddRect(p1, p2, 0xFFFFFFFF, 2.f, 15, 2.5f);\n      else\n         draw_list->AddRect(p1, p2, 0x80FFFFFF, 2.f, 15, 1.25f);\n\n      if (rc.Contains(io.MousePos))\n      {\n         if (io.MouseClicked[0])\n            return 2;\n         return 1;\n      }\n      return 0;\n   }\n\n   bool Edit(Delegate& delegate, const ImVec2& size, int& selection)\n   {\n      bool ret = false;\n      ImGuiIO& io = ImGui::GetIO();\n      ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));\n      ImGui::BeginChildFrame(137, size);\n\n      ImDrawList* draw_list = ImGui::GetWindowDrawList();\n      const ImVec2 offset = ImGui::GetCursorScreenPos();\n\n      const ImVec4* pts = delegate.GetPoints();\n      static int currentSelection = -1;\n      static int movingPt = -1;\n      if (currentSelection >= int(delegate.GetPointCount()))\n         currentSelection = -1;\n      if (movingPt != -1)\n      {\n         ImVec4 current = pts[movingPt];\n         current.w += io.MouseDelta.x / size.x;\n         current.w = ImClamp(current.w, 0.f, 1.f);\n         delegate.EditPoint(movingPt, current);\n         ret = true;\n         if (!io.MouseDown[0])\n            movingPt = -1;\n      }\n      for (size_t i = 0; i < delegate.GetPointCount(); i++)\n      {\n         int ptSel = DrawPoint(draw_list, pts[i], size, i == currentSelection, offset);\n         if (ptSel == 2)\n         {\n            currentSelection = int(i);\n            ret = true;\n         }\n         if (ptSel == 1 && io.MouseDown[0] && movingPt == -1)\n         {\n            movingPt = int(i);\n         }\n      }\n      ImRect rc(offset, offset + size);\n      if (rc.Contains(io.MousePos) && io.MouseDoubleClicked[0])\n      {\n         float t = (io.MousePos.x - offset.x) / size.x;\n         delegate.AddPoint(delegate.GetPoint(t));\n         ret = true;\n      }\n      ImGui::EndChildFrame();\n      ImGui::PopStyleVar();\n\n      selection = currentSelection;\n      return ret;\n   }\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImGradient.h",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#pragma once\n#include <cstddef>\n\nstruct ImVec4;\nstruct ImVec2;\n\nnamespace ImGradient\n{\n   struct Delegate\n   {\n      virtual size_t GetPointCount() = 0;\n      virtual ImVec4* GetPoints() = 0;\n      virtual int EditPoint(int pointIndex, ImVec4 value) = 0;\n      virtual ImVec4 GetPoint(float t) = 0;\n      virtual void AddPoint(ImVec4 value) = 0;\n   };\n\n   bool Edit(Delegate& delegate, const ImVec2& size, int& selection);\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImGuizmo.cpp",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n\n#ifndef IMGUI_DEFINE_MATH_OPERATORS\n#define IMGUI_DEFINE_MATH_OPERATORS\n#endif\n#include \"imgui.h\"\n#include \"imgui_internal.h\"\n#include \"ImGuizmo.h\"\n\n#if defined(_MSC_VER) || defined(__MINGW32__)\n#include <malloc.h>\n#endif\n#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)\n#define _malloca(x) alloca(x)\n#define _freea(x)\n#endif\n\n// includes patches for multiview from\n// https://github.com/CedricGuillemet/ImGuizmo/issues/15\n\nnamespace IMGUIZMO_NAMESPACE\n{\n   static const float ZPI = 3.14159265358979323846f;\n   static const float RAD2DEG = (180.f / ZPI);\n   static const float DEG2RAD = (ZPI / 180.f);\n   const float screenRotateSize = 0.06f;\n   // scale a bit so translate axis do not touch when in universal\n   const float rotationDisplayFactor = 1.2f;\n\n   static OPERATION operator&(OPERATION lhs, OPERATION rhs)\n   {\n     return static_cast<OPERATION>(static_cast<int>(lhs) & static_cast<int>(rhs));\n   }\n\n   static bool operator!=(OPERATION lhs, int rhs)\n   {\n     return static_cast<int>(lhs) != rhs;\n   }\n\n   static bool Intersects(OPERATION lhs, OPERATION rhs)\n   {\n     return (lhs & rhs) != 0;\n   }\n\n   // True if lhs contains rhs\n   static bool Contains(OPERATION lhs, OPERATION rhs)\n   {\n     return (lhs & rhs) == rhs;\n   }\n\n   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n   // utility and math\n\n   void FPU_MatrixF_x_MatrixF(const float* a, const float* b, float* r)\n   {\n      r[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12];\n      r[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13];\n      r[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14];\n      r[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15];\n\n      r[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12];\n      r[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13];\n      r[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14];\n      r[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15];\n\n      r[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12];\n      r[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13];\n      r[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14];\n      r[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15];\n\n      r[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12];\n      r[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13];\n      r[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14];\n      r[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15];\n   }\n\n   void Frustum(float left, float right, float bottom, float top, float znear, float zfar, float* m16)\n   {\n      float temp, temp2, temp3, temp4;\n      temp = 2.0f * znear;\n      temp2 = right - left;\n      temp3 = top - bottom;\n      temp4 = zfar - znear;\n      m16[0] = temp / temp2;\n      m16[1] = 0.0;\n      m16[2] = 0.0;\n      m16[3] = 0.0;\n      m16[4] = 0.0;\n      m16[5] = temp / temp3;\n      m16[6] = 0.0;\n      m16[7] = 0.0;\n      m16[8] = (right + left) / temp2;\n      m16[9] = (top + bottom) / temp3;\n      m16[10] = (-zfar - znear) / temp4;\n      m16[11] = -1.0f;\n      m16[12] = 0.0;\n      m16[13] = 0.0;\n      m16[14] = (-temp * zfar) / temp4;\n      m16[15] = 0.0;\n   }\n\n   void Perspective(float fovyInDegrees, float aspectRatio, float znear, float zfar, float* m16)\n   {\n      float ymax, xmax;\n      ymax = znear * tanf(fovyInDegrees * DEG2RAD);\n      xmax = ymax * aspectRatio;\n      Frustum(-xmax, xmax, -ymax, ymax, znear, zfar, m16);\n   }\n\n   void Cross(const float* a, const float* b, float* r)\n   {\n      r[0] = a[1] * b[2] - a[2] * b[1];\n      r[1] = a[2] * b[0] - a[0] * b[2];\n      r[2] = a[0] * b[1] - a[1] * b[0];\n   }\n\n   float Dot(const float* a, const float* b)\n   {\n      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n   }\n\n   void Normalize(const float* a, float* r)\n   {\n      float il = 1.f / (sqrtf(Dot(a, a)) + FLT_EPSILON);\n      r[0] = a[0] * il;\n      r[1] = a[1] * il;\n      r[2] = a[2] * il;\n   }\n\n   void LookAt(const float* eye, const float* at, const float* up, float* m16)\n   {\n      float X[3], Y[3], Z[3], tmp[3];\n\n      tmp[0] = eye[0] - at[0];\n      tmp[1] = eye[1] - at[1];\n      tmp[2] = eye[2] - at[2];\n      Normalize(tmp, Z);\n      Normalize(up, Y);\n      Cross(Y, Z, tmp);\n      Normalize(tmp, X);\n      Cross(Z, X, tmp);\n      Normalize(tmp, Y);\n\n      m16[0] = X[0];\n      m16[1] = Y[0];\n      m16[2] = Z[0];\n      m16[3] = 0.0f;\n      m16[4] = X[1];\n      m16[5] = Y[1];\n      m16[6] = Z[1];\n      m16[7] = 0.0f;\n      m16[8] = X[2];\n      m16[9] = Y[2];\n      m16[10] = Z[2];\n      m16[11] = 0.0f;\n      m16[12] = -Dot(X, eye);\n      m16[13] = -Dot(Y, eye);\n      m16[14] = -Dot(Z, eye);\n      m16[15] = 1.0f;\n   }\n\n   template <typename T> T Clamp(T x, T y, T z) { return ((x < y) ? y : ((x > z) ? z : x)); }\n   template <typename T> T max(T x, T y) { return (x > y) ? x : y; }\n   template <typename T> T min(T x, T y) { return (x < y) ? x : y; }\n   template <typename T> bool IsWithin(T x, T y, T z) { return (x >= y) && (x <= z); }\n\n   struct matrix_t;\n   struct vec_t\n   {\n   public:\n      float x, y, z, w;\n\n      void Lerp(const vec_t& v, float t)\n      {\n         x += (v.x - x) * t;\n         y += (v.y - y) * t;\n         z += (v.z - z) * t;\n         w += (v.w - w) * t;\n      }\n\n      void Set(float v) { x = y = z = w = v; }\n      void Set(float _x, float _y, float _z = 0.f, float _w = 0.f) { x = _x; y = _y; z = _z; w = _w; }\n\n      vec_t& operator -= (const vec_t& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }\n      vec_t& operator += (const vec_t& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }\n      vec_t& operator *= (const vec_t& v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }\n      vec_t& operator *= (float v) { x *= v;    y *= v;    z *= v;    w *= v;    return *this; }\n\n      vec_t operator * (float f) const;\n      vec_t operator - () const;\n      vec_t operator - (const vec_t& v) const;\n      vec_t operator + (const vec_t& v) const;\n      vec_t operator * (const vec_t& v) const;\n\n      const vec_t& operator + () const { return (*this); }\n      float Length() const { return sqrtf(x * x + y * y + z * z); };\n      float LengthSq() const { return (x * x + y * y + z * z); };\n      vec_t Normalize() { (*this) *= (1.f / ( Length() > FLT_EPSILON ? Length() : FLT_EPSILON ) ); return (*this); }\n      vec_t Normalize(const vec_t& v) { this->Set(v.x, v.y, v.z, v.w); this->Normalize(); return (*this); }\n      vec_t Abs() const;\n\n      void Cross(const vec_t& v)\n      {\n         vec_t res;\n         res.x = y * v.z - z * v.y;\n         res.y = z * v.x - x * v.z;\n         res.z = x * v.y - y * v.x;\n\n         x = res.x;\n         y = res.y;\n         z = res.z;\n         w = 0.f;\n      }\n\n      void Cross(const vec_t& v1, const vec_t& v2)\n      {\n         x = v1.y * v2.z - v1.z * v2.y;\n         y = v1.z * v2.x - v1.x * v2.z;\n         z = v1.x * v2.y - v1.y * v2.x;\n         w = 0.f;\n      }\n\n      float Dot(const vec_t& v) const\n      {\n         return (x * v.x) + (y * v.y) + (z * v.z) + (w * v.w);\n      }\n\n      float Dot3(const vec_t& v) const\n      {\n         return (x * v.x) + (y * v.y) + (z * v.z);\n      }\n\n      void Transform(const matrix_t& matrix);\n      void Transform(const vec_t& s, const matrix_t& matrix);\n\n      void TransformVector(const matrix_t& matrix);\n      void TransformPoint(const matrix_t& matrix);\n      void TransformVector(const vec_t& v, const matrix_t& matrix) { (*this) = v; this->TransformVector(matrix); }\n      void TransformPoint(const vec_t& v, const matrix_t& matrix) { (*this) = v; this->TransformPoint(matrix); }\n\n      float& operator [] (size_t index) { return ((float*)&x)[index]; }\n      const float& operator [] (size_t index) const { return ((float*)&x)[index]; }\n      bool operator!=(const vec_t& other) const { return memcmp(this, &other, sizeof(vec_t)) != 0; }\n   };\n\n   vec_t makeVect(float _x, float _y, float _z = 0.f, float _w = 0.f) { vec_t res; res.x = _x; res.y = _y; res.z = _z; res.w = _w; return res; }\n   vec_t makeVect(ImVec2 v) { vec_t res; res.x = v.x; res.y = v.y; res.z = 0.f; res.w = 0.f; return res; }\n   vec_t vec_t::operator * (float f) const { return makeVect(x * f, y * f, z * f, w * f); }\n   vec_t vec_t::operator - () const { return makeVect(-x, -y, -z, -w); }\n   vec_t vec_t::operator - (const vec_t& v) const { return makeVect(x - v.x, y - v.y, z - v.z, w - v.w); }\n   vec_t vec_t::operator + (const vec_t& v) const { return makeVect(x + v.x, y + v.y, z + v.z, w + v.w); }\n   vec_t vec_t::operator * (const vec_t& v) const { return makeVect(x * v.x, y * v.y, z * v.z, w * v.w); }\n   vec_t vec_t::Abs() const { return makeVect(fabsf(x), fabsf(y), fabsf(z)); }\n\n   vec_t Normalized(const vec_t& v) { vec_t res; res = v; res.Normalize(); return res; }\n   vec_t Cross(const vec_t& v1, const vec_t& v2)\n   {\n      vec_t res;\n      res.x = v1.y * v2.z - v1.z * v2.y;\n      res.y = v1.z * v2.x - v1.x * v2.z;\n      res.z = v1.x * v2.y - v1.y * v2.x;\n      res.w = 0.f;\n      return res;\n   }\n\n   float Dot(const vec_t& v1, const vec_t& v2)\n   {\n      return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);\n   }\n\n   vec_t BuildPlan(const vec_t& p_point1, const vec_t& p_normal)\n   {\n      vec_t normal, res;\n      normal.Normalize(p_normal);\n      res.w = normal.Dot(p_point1);\n      res.x = normal.x;\n      res.y = normal.y;\n      res.z = normal.z;\n      return res;\n   }\n\n   struct matrix_t\n   {\n   public:\n\n      union\n      {\n         float m[4][4];\n         float m16[16];\n         struct\n         {\n            vec_t right, up, dir, position;\n         } v;\n         vec_t component[4];\n      };\n\n      operator float* () { return m16; }\n      operator const float* () const { return m16; }\n      void Translation(float _x, float _y, float _z) { this->Translation(makeVect(_x, _y, _z)); }\n\n      void Translation(const vec_t& vt)\n      {\n         v.right.Set(1.f, 0.f, 0.f, 0.f);\n         v.up.Set(0.f, 1.f, 0.f, 0.f);\n         v.dir.Set(0.f, 0.f, 1.f, 0.f);\n         v.position.Set(vt.x, vt.y, vt.z, 1.f);\n      }\n\n      void Scale(float _x, float _y, float _z)\n      {\n         v.right.Set(_x, 0.f, 0.f, 0.f);\n         v.up.Set(0.f, _y, 0.f, 0.f);\n         v.dir.Set(0.f, 0.f, _z, 0.f);\n         v.position.Set(0.f, 0.f, 0.f, 1.f);\n      }\n      void Scale(const vec_t& s) { Scale(s.x, s.y, s.z); }\n\n      matrix_t& operator *= (const matrix_t& mat)\n      {\n         matrix_t tmpMat;\n         tmpMat = *this;\n         tmpMat.Multiply(mat);\n         *this = tmpMat;\n         return *this;\n      }\n      matrix_t operator * (const matrix_t& mat) const\n      {\n         matrix_t matT;\n         matT.Multiply(*this, mat);\n         return matT;\n      }\n\n      void Multiply(const matrix_t& matrix)\n      {\n         matrix_t tmp;\n         tmp = *this;\n\n         FPU_MatrixF_x_MatrixF((float*)&tmp, (float*)&matrix, (float*)this);\n      }\n\n      void Multiply(const matrix_t& m1, const matrix_t& m2)\n      {\n         FPU_MatrixF_x_MatrixF((float*)&m1, (float*)&m2, (float*)this);\n      }\n\n      float GetDeterminant() const\n      {\n         return m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] + m[0][2] * m[1][0] * m[2][1] -\n            m[0][2] * m[1][1] * m[2][0] - m[0][1] * m[1][0] * m[2][2] - m[0][0] * m[1][2] * m[2][1];\n      }\n\n      float Inverse(const matrix_t& srcMatrix, bool affine = false);\n      void SetToIdentity()\n      {\n         v.right.Set(1.f, 0.f, 0.f, 0.f);\n         v.up.Set(0.f, 1.f, 0.f, 0.f);\n         v.dir.Set(0.f, 0.f, 1.f, 0.f);\n         v.position.Set(0.f, 0.f, 0.f, 1.f);\n      }\n      void Transpose()\n      {\n         matrix_t tmpm;\n         for (int l = 0; l < 4; l++)\n         {\n            for (int c = 0; c < 4; c++)\n            {\n               tmpm.m[l][c] = m[c][l];\n            }\n         }\n         (*this) = tmpm;\n      }\n\n      void RotationAxis(const vec_t& axis, float angle);\n\n      void OrthoNormalize()\n      {\n         v.right.Normalize();\n         v.up.Normalize();\n         v.dir.Normalize();\n      }\n   };\n\n   void vec_t::Transform(const matrix_t& matrix)\n   {\n      vec_t out;\n\n      out.x = x * matrix.m[0][0] + y * matrix.m[1][0] + z * matrix.m[2][0] + w * matrix.m[3][0];\n      out.y = x * matrix.m[0][1] + y * matrix.m[1][1] + z * matrix.m[2][1] + w * matrix.m[3][1];\n      out.z = x * matrix.m[0][2] + y * matrix.m[1][2] + z * matrix.m[2][2] + w * matrix.m[3][2];\n      out.w = x * matrix.m[0][3] + y * matrix.m[1][3] + z * matrix.m[2][3] + w * matrix.m[3][3];\n\n      x = out.x;\n      y = out.y;\n      z = out.z;\n      w = out.w;\n   }\n\n   void vec_t::Transform(const vec_t& s, const matrix_t& matrix)\n   {\n      *this = s;\n      Transform(matrix);\n   }\n\n   void vec_t::TransformPoint(const matrix_t& matrix)\n   {\n      vec_t out;\n\n      out.x = x * matrix.m[0][0] + y * matrix.m[1][0] + z * matrix.m[2][0] + matrix.m[3][0];\n      out.y = x * matrix.m[0][1] + y * matrix.m[1][1] + z * matrix.m[2][1] + matrix.m[3][1];\n      out.z = x * matrix.m[0][2] + y * matrix.m[1][2] + z * matrix.m[2][2] + matrix.m[3][2];\n      out.w = x * matrix.m[0][3] + y * matrix.m[1][3] + z * matrix.m[2][3] + matrix.m[3][3];\n\n      x = out.x;\n      y = out.y;\n      z = out.z;\n      w = out.w;\n   }\n\n   void vec_t::TransformVector(const matrix_t& matrix)\n   {\n      vec_t out;\n\n      out.x = x * matrix.m[0][0] + y * matrix.m[1][0] + z * matrix.m[2][0];\n      out.y = x * matrix.m[0][1] + y * matrix.m[1][1] + z * matrix.m[2][1];\n      out.z = x * matrix.m[0][2] + y * matrix.m[1][2] + z * matrix.m[2][2];\n      out.w = x * matrix.m[0][3] + y * matrix.m[1][3] + z * matrix.m[2][3];\n\n      x = out.x;\n      y = out.y;\n      z = out.z;\n      w = out.w;\n   }\n\n   float matrix_t::Inverse(const matrix_t& srcMatrix, bool affine)\n   {\n      float det = 0;\n\n      if (affine)\n      {\n         det = GetDeterminant();\n         float s = 1 / det;\n         m[0][0] = (srcMatrix.m[1][1] * srcMatrix.m[2][2] - srcMatrix.m[1][2] * srcMatrix.m[2][1]) * s;\n         m[0][1] = (srcMatrix.m[2][1] * srcMatrix.m[0][2] - srcMatrix.m[2][2] * srcMatrix.m[0][1]) * s;\n         m[0][2] = (srcMatrix.m[0][1] * srcMatrix.m[1][2] - srcMatrix.m[0][2] * srcMatrix.m[1][1]) * s;\n         m[1][0] = (srcMatrix.m[1][2] * srcMatrix.m[2][0] - srcMatrix.m[1][0] * srcMatrix.m[2][2]) * s;\n         m[1][1] = (srcMatrix.m[2][2] * srcMatrix.m[0][0] - srcMatrix.m[2][0] * srcMatrix.m[0][2]) * s;\n         m[1][2] = (srcMatrix.m[0][2] * srcMatrix.m[1][0] - srcMatrix.m[0][0] * srcMatrix.m[1][2]) * s;\n         m[2][0] = (srcMatrix.m[1][0] * srcMatrix.m[2][1] - srcMatrix.m[1][1] * srcMatrix.m[2][0]) * s;\n         m[2][1] = (srcMatrix.m[2][0] * srcMatrix.m[0][1] - srcMatrix.m[2][1] * srcMatrix.m[0][0]) * s;\n         m[2][2] = (srcMatrix.m[0][0] * srcMatrix.m[1][1] - srcMatrix.m[0][1] * srcMatrix.m[1][0]) * s;\n         m[3][0] = -(m[0][0] * srcMatrix.m[3][0] + m[1][0] * srcMatrix.m[3][1] + m[2][0] * srcMatrix.m[3][2]);\n         m[3][1] = -(m[0][1] * srcMatrix.m[3][0] + m[1][1] * srcMatrix.m[3][1] + m[2][1] * srcMatrix.m[3][2]);\n         m[3][2] = -(m[0][2] * srcMatrix.m[3][0] + m[1][2] * srcMatrix.m[3][1] + m[2][2] * srcMatrix.m[3][2]);\n      }\n      else\n      {\n         // transpose matrix\n         float src[16];\n         for (int i = 0; i < 4; ++i)\n         {\n            src[i] = srcMatrix.m16[i * 4];\n            src[i + 4] = srcMatrix.m16[i * 4 + 1];\n            src[i + 8] = srcMatrix.m16[i * 4 + 2];\n            src[i + 12] = srcMatrix.m16[i * 4 + 3];\n         }\n\n         // calculate pairs for first 8 elements (cofactors)\n         float tmp[12]; // temp array for pairs\n         tmp[0] = src[10] * src[15];\n         tmp[1] = src[11] * src[14];\n         tmp[2] = src[9] * src[15];\n         tmp[3] = src[11] * src[13];\n         tmp[4] = src[9] * src[14];\n         tmp[5] = src[10] * src[13];\n         tmp[6] = src[8] * src[15];\n         tmp[7] = src[11] * src[12];\n         tmp[8] = src[8] * src[14];\n         tmp[9] = src[10] * src[12];\n         tmp[10] = src[8] * src[13];\n         tmp[11] = src[9] * src[12];\n\n         // calculate first 8 elements (cofactors)\n         m16[0] = (tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]) - (tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]);\n         m16[1] = (tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]) - (tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7]);\n         m16[2] = (tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7]) - (tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7]);\n         m16[3] = (tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6]) - (tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6]);\n         m16[4] = (tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3]) - (tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3]);\n         m16[5] = (tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3]) - (tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3]);\n         m16[6] = (tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3]) - (tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]);\n         m16[7] = (tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]) - (tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]);\n\n         // calculate pairs for second 8 elements (cofactors)\n         tmp[0] = src[2] * src[7];\n         tmp[1] = src[3] * src[6];\n         tmp[2] = src[1] * src[7];\n         tmp[3] = src[3] * src[5];\n         tmp[4] = src[1] * src[6];\n         tmp[5] = src[2] * src[5];\n         tmp[6] = src[0] * src[7];\n         tmp[7] = src[3] * src[4];\n         tmp[8] = src[0] * src[6];\n         tmp[9] = src[2] * src[4];\n         tmp[10] = src[0] * src[5];\n         tmp[11] = src[1] * src[4];\n\n         // calculate second 8 elements (cofactors)\n         m16[8] = (tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]) - (tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]);\n         m16[9] = (tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]) - (tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]);\n         m16[10] = (tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15]) - (tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15]);\n         m16[11] = (tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14]) - (tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14]);\n         m16[12] = (tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]) - (tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]);\n         m16[13] = (tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]) - (tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]);\n         m16[14] = (tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8]) - (tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]);\n         m16[15] = (tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]) - (tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]);\n\n         // calculate determinant\n         det = src[0] * m16[0] + src[1] * m16[1] + src[2] * m16[2] + src[3] * m16[3];\n\n         // calculate matrix inverse\n         float invdet = 1 / det;\n         for (int j = 0; j < 16; ++j)\n         {\n            m16[j] *= invdet;\n         }\n      }\n\n      return det;\n   }\n\n   void matrix_t::RotationAxis(const vec_t& axis, float angle)\n   {\n      float length2 = axis.LengthSq();\n      if (length2 < FLT_EPSILON)\n      {\n         SetToIdentity();\n         return;\n      }\n\n      vec_t n = axis * (1.f / sqrtf(length2));\n      float s = sinf(angle);\n      float c = cosf(angle);\n      float k = 1.f - c;\n\n      float xx = n.x * n.x * k + c;\n      float yy = n.y * n.y * k + c;\n      float zz = n.z * n.z * k + c;\n      float xy = n.x * n.y * k;\n      float yz = n.y * n.z * k;\n      float zx = n.z * n.x * k;\n      float xs = n.x * s;\n      float ys = n.y * s;\n      float zs = n.z * s;\n\n      m[0][0] = xx;\n      m[0][1] = xy + zs;\n      m[0][2] = zx - ys;\n      m[0][3] = 0.f;\n      m[1][0] = xy - zs;\n      m[1][1] = yy;\n      m[1][2] = yz + xs;\n      m[1][3] = 0.f;\n      m[2][0] = zx + ys;\n      m[2][1] = yz - xs;\n      m[2][2] = zz;\n      m[2][3] = 0.f;\n      m[3][0] = 0.f;\n      m[3][1] = 0.f;\n      m[3][2] = 0.f;\n      m[3][3] = 1.f;\n   }\n\n   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n   //\n\n   enum MOVETYPE\n   {\n      MT_NONE,\n      MT_MOVE_X,\n      MT_MOVE_Y,\n      MT_MOVE_Z,\n      MT_MOVE_YZ,\n      MT_MOVE_ZX,\n      MT_MOVE_XY,\n      MT_MOVE_SCREEN,\n      MT_ROTATE_X,\n      MT_ROTATE_Y,\n      MT_ROTATE_Z,\n      MT_ROTATE_SCREEN,\n      MT_SCALE_X,\n      MT_SCALE_Y,\n      MT_SCALE_Z,\n      MT_SCALE_XYZ\n   };\n\n   static bool IsTranslateType(int type)\n   {\n     return type >= MT_MOVE_X && type <= MT_MOVE_SCREEN;\n   }\n\n   static bool IsRotateType(int type)\n   {\n     return type >= MT_ROTATE_X && type <= MT_ROTATE_SCREEN;\n   }\n\n   static bool IsScaleType(int type)\n   {\n     return type >= MT_SCALE_X && type <= MT_SCALE_XYZ;\n   }\n\n   // Matches MT_MOVE_AB order\n   static const OPERATION TRANSLATE_PLANS[3] = { TRANSLATE_Y | TRANSLATE_Z, TRANSLATE_X | TRANSLATE_Z, TRANSLATE_X | TRANSLATE_Y };\n\n   Style::Style()\n   {\n      // default values\n      TranslationLineThickness   = 3.0f;\n      TranslationLineArrowSize   = 6.0f;\n      RotationLineThickness      = 2.0f;\n      RotationOuterLineThickness = 3.0f;\n      ScaleLineThickness         = 3.0f;\n      ScaleLineCircleSize        = 6.0f;\n      HatchedAxisLineThickness   = 6.0f;\n      CenterCircleSize           = 6.0f;\n\n      // initialize default colors\n      Colors[DIRECTION_X]           = ImVec4(0.666f, 0.000f, 0.000f, 1.000f);\n      Colors[DIRECTION_Y]           = ImVec4(0.000f, 0.666f, 0.000f, 1.000f);\n      Colors[DIRECTION_Z]           = ImVec4(0.000f, 0.000f, 0.666f, 1.000f);\n      Colors[PLANE_X]               = ImVec4(0.666f, 0.000f, 0.000f, 0.380f);\n      Colors[PLANE_Y]               = ImVec4(0.000f, 0.666f, 0.000f, 0.380f);\n      Colors[PLANE_Z]               = ImVec4(0.000f, 0.000f, 0.666f, 0.380f);\n      Colors[SELECTION]             = ImVec4(1.000f, 0.500f, 0.062f, 0.541f);\n      Colors[INACTIVE]              = ImVec4(0.600f, 0.600f, 0.600f, 0.600f);\n      Colors[TRANSLATION_LINE]      = ImVec4(0.666f, 0.666f, 0.666f, 0.666f);\n      Colors[SCALE_LINE]            = ImVec4(0.250f, 0.250f, 0.250f, 1.000f);\n      Colors[ROTATION_USING_BORDER] = ImVec4(1.000f, 0.500f, 0.062f, 1.000f);\n      Colors[ROTATION_USING_FILL]   = ImVec4(1.000f, 0.500f, 0.062f, 0.500f);\n      Colors[HATCHED_AXIS_LINES]    = ImVec4(0.000f, 0.000f, 0.000f, 0.500f);\n      Colors[TEXT]                  = ImVec4(1.000f, 1.000f, 1.000f, 1.000f);\n      Colors[TEXT_SHADOW]           = ImVec4(0.000f, 0.000f, 0.000f, 1.000f);\n   }\n\n   struct Context\n   {\n      Context() : mbUsing(false), mbEnable(true), mbUsingBounds(false)\n      {\n      }\n\n      ImDrawList* mDrawList;\n      Style mStyle;\n\n      MODE mMode;\n      matrix_t mViewMat;\n      matrix_t mProjectionMat;\n      matrix_t mModel;\n      matrix_t mModelLocal; // orthonormalized model\n      matrix_t mModelInverse;\n      matrix_t mModelSource;\n      matrix_t mModelSourceInverse;\n      matrix_t mMVP;\n      matrix_t mMVPLocal; // MVP with full model matrix whereas mMVP's model matrix might only be translation in case of World space edition\n      matrix_t mViewProjection;\n\n      vec_t mModelScaleOrigin;\n      vec_t mCameraEye;\n      vec_t mCameraRight;\n      vec_t mCameraDir;\n      vec_t mCameraUp;\n      vec_t mRayOrigin;\n      vec_t mRayVector;\n\n      float  mRadiusSquareCenter;\n      ImVec2 mScreenSquareCenter;\n      ImVec2 mScreenSquareMin;\n      ImVec2 mScreenSquareMax;\n\n      float mScreenFactor;\n      vec_t mRelativeOrigin;\n\n      bool mbUsing;\n      bool mbEnable;\n      bool mbMouseOver;\n      bool mReversed; // reversed projection matrix\n\n      // translation\n      vec_t mTranslationPlan;\n      vec_t mTranslationPlanOrigin;\n      vec_t mMatrixOrigin;\n      vec_t mTranslationLastDelta;\n\n      // rotation\n      vec_t mRotationVectorSource;\n      float mRotationAngle;\n      float mRotationAngleOrigin;\n      //vec_t mWorldToLocalAxis;\n\n      // scale\n      vec_t mScale;\n      vec_t mScaleValueOrigin;\n      vec_t mScaleLast;\n      float mSaveMousePosx;\n\n      // save axis factor when using gizmo\n      bool mBelowAxisLimit[3];\n      bool mBelowPlaneLimit[3];\n      float mAxisFactor[3];\n\n      // bounds stretching\n      vec_t mBoundsPivot;\n      vec_t mBoundsAnchor;\n      vec_t mBoundsPlan;\n      vec_t mBoundsLocalPivot;\n      int mBoundsBestAxis;\n      int mBoundsAxis[2];\n      bool mbUsingBounds;\n      matrix_t mBoundsMatrix;\n\n      //\n      int mCurrentOperation;\n\n      float mX = 0.f;\n      float mY = 0.f;\n      float mWidth = 0.f;\n      float mHeight = 0.f;\n      float mXMax = 0.f;\n      float mYMax = 0.f;\n      float mDisplayRatio = 1.f;\n\n      bool mIsOrthographic = false;\n\n      int mActualID = -1;\n      int mEditingID = -1;\n      OPERATION mOperation = OPERATION(-1);\n\n      bool mAllowAxisFlip = true;\n      float mGizmoSizeClipSpace = 0.1f;\n   };\n\n   static Context gContext;\n\n   static const vec_t directionUnary[3] = { makeVect(1.f, 0.f, 0.f), makeVect(0.f, 1.f, 0.f), makeVect(0.f, 0.f, 1.f) };\n   static const char* translationInfoMask[] = { \"X : %5.3f\", \"Y : %5.3f\", \"Z : %5.3f\",\n      \"Y : %5.3f Z : %5.3f\", \"X : %5.3f Z : %5.3f\", \"X : %5.3f Y : %5.3f\",\n      \"X : %5.3f Y : %5.3f Z : %5.3f\" };\n   static const char* scaleInfoMask[] = { \"X : %5.2f\", \"Y : %5.2f\", \"Z : %5.2f\", \"XYZ : %5.2f\" };\n   static const char* rotationInfoMask[] = { \"X : %5.2f deg %5.2f rad\", \"Y : %5.2f deg %5.2f rad\", \"Z : %5.2f deg %5.2f rad\", \"Screen : %5.2f deg %5.2f rad\" };\n   static const int translationInfoIndex[] = { 0,0,0, 1,0,0, 2,0,0, 1,2,0, 0,2,0, 0,1,0, 0,1,2 };\n   static const float quadMin = 0.5f;\n   static const float quadMax = 0.8f;\n   static const float quadUV[8] = { quadMin, quadMin, quadMin, quadMax, quadMax, quadMax, quadMax, quadMin };\n   static const int halfCircleSegmentCount = 64;\n   static const float snapTension = 0.5f;\n\n   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n   //\n   static int GetMoveType(OPERATION op, vec_t* gizmoHitProportion);\n   static int GetRotateType(OPERATION op);\n   static int GetScaleType(OPERATION op);\n\n   Style& GetStyle()\n   {\n      return gContext.mStyle;\n   }\n\n   static ImU32 GetColorU32(int idx)\n   {\n      IM_ASSERT(idx < COLOR::COUNT);\n      return ImGui::ColorConvertFloat4ToU32(gContext.mStyle.Colors[idx]);\n   }\n\n   static ImVec2 worldToPos(const vec_t& worldPos, const matrix_t& mat, ImVec2 position = ImVec2(gContext.mX, gContext.mY), ImVec2 size = ImVec2(gContext.mWidth, gContext.mHeight))\n   {\n      vec_t trans;\n      trans.TransformPoint(worldPos, mat);\n      trans *= 0.5f / trans.w;\n      trans += makeVect(0.5f, 0.5f);\n      trans.y = 1.f - trans.y;\n      trans.x *= size.x;\n      trans.y *= size.y;\n      trans.x += position.x;\n      trans.y += position.y;\n      return ImVec2(trans.x, trans.y);\n   }\n\n   static void ComputeCameraRay(vec_t& rayOrigin, vec_t& rayDir, ImVec2 position = ImVec2(gContext.mX, gContext.mY), ImVec2 size = ImVec2(gContext.mWidth, gContext.mHeight))\n   {\n      ImGuiIO& io = ImGui::GetIO();\n\n      matrix_t mViewProjInverse;\n      mViewProjInverse.Inverse(gContext.mViewMat * gContext.mProjectionMat);\n\n      const float mox = ((io.MousePos.x - position.x) / size.x) * 2.f - 1.f;\n      const float moy = (1.f - ((io.MousePos.y - position.y) / size.y)) * 2.f - 1.f;\n\n      const float zNear = gContext.mReversed ? (1.f - FLT_EPSILON) : 0.f;\n      const float zFar = gContext.mReversed ? 0.f : (1.f - FLT_EPSILON);\n\n      rayOrigin.Transform(makeVect(mox, moy, zNear, 1.f), mViewProjInverse);\n      rayOrigin *= 1.f / rayOrigin.w;\n      vec_t rayEnd;\n      rayEnd.Transform(makeVect(mox, moy, zFar, 1.f), mViewProjInverse);\n      rayEnd *= 1.f / rayEnd.w;\n      rayDir = Normalized(rayEnd - rayOrigin);\n   }\n\n   static float GetSegmentLengthClipSpace(const vec_t& start, const vec_t& end, const bool localCoordinates = false)\n   {\n      vec_t startOfSegment = start;\n      const matrix_t& mvp = localCoordinates ? gContext.mMVPLocal : gContext.mMVP;\n      startOfSegment.TransformPoint(mvp);\n      if (fabsf(startOfSegment.w) > FLT_EPSILON) // check for axis aligned with camera direction\n      {\n         startOfSegment *= 1.f / startOfSegment.w;\n      }\n\n      vec_t endOfSegment = end;\n      endOfSegment.TransformPoint(mvp);\n      if (fabsf(endOfSegment.w) > FLT_EPSILON) // check for axis aligned with camera direction\n      {\n         endOfSegment *= 1.f / endOfSegment.w;\n      }\n\n      vec_t clipSpaceAxis = endOfSegment - startOfSegment;\n      clipSpaceAxis.y /= gContext.mDisplayRatio;\n      float segmentLengthInClipSpace = sqrtf(clipSpaceAxis.x * clipSpaceAxis.x + clipSpaceAxis.y * clipSpaceAxis.y);\n      return segmentLengthInClipSpace;\n   }\n\n   static float GetParallelogram(const vec_t& ptO, const vec_t& ptA, const vec_t& ptB)\n   {\n      vec_t pts[] = { ptO, ptA, ptB };\n      for (unsigned int i = 0; i < 3; i++)\n      {\n         pts[i].TransformPoint(gContext.mMVP);\n         if (fabsf(pts[i].w) > FLT_EPSILON) // check for axis aligned with camera direction\n         {\n            pts[i] *= 1.f / pts[i].w;\n         }\n      }\n      vec_t segA = pts[1] - pts[0];\n      vec_t segB = pts[2] - pts[0];\n      segA.y /= gContext.mDisplayRatio;\n      segB.y /= gContext.mDisplayRatio;\n      vec_t segAOrtho = makeVect(-segA.y, segA.x);\n      segAOrtho.Normalize();\n      float dt = segAOrtho.Dot3(segB);\n      float surface = sqrtf(segA.x * segA.x + segA.y * segA.y) * fabsf(dt);\n      return surface;\n   }\n\n   inline vec_t PointOnSegment(const vec_t& point, const vec_t& vertPos1, const vec_t& vertPos2)\n   {\n      vec_t c = point - vertPos1;\n      vec_t V;\n\n      V.Normalize(vertPos2 - vertPos1);\n      float d = (vertPos2 - vertPos1).Length();\n      float t = V.Dot3(c);\n\n      if (t < 0.f)\n      {\n         return vertPos1;\n      }\n\n      if (t > d)\n      {\n         return vertPos2;\n      }\n\n      return vertPos1 + V * t;\n   }\n\n   static float IntersectRayPlane(const vec_t& rOrigin, const vec_t& rVector, const vec_t& plan)\n   {\n      const float numer = plan.Dot3(rOrigin) - plan.w;\n      const float denom = plan.Dot3(rVector);\n\n      if (fabsf(denom) < FLT_EPSILON)  // normal is orthogonal to vector, cant intersect\n      {\n         return -1.0f;\n      }\n\n      return -(numer / denom);\n   }\n\n   static float DistanceToPlane(const vec_t& point, const vec_t& plan)\n   {\n      return plan.Dot3(point) + plan.w;\n   }\n\n   static bool IsInContextRect(ImVec2 p)\n   {\n      return IsWithin(p.x, gContext.mX, gContext.mXMax) && IsWithin(p.y, gContext.mY, gContext.mYMax);\n   }\n\n   static bool IsHoveringWindow()\n   {\n      ImGuiContext& g = *ImGui::GetCurrentContext();\n      ImGuiWindow* window = ImGui::FindWindowByName(gContext.mDrawList->_OwnerName);\n      if (g.HoveredWindow == window)   // Mouse hovering drawlist window\n         return true;\n      if (g.HoveredWindow != NULL)     // Any other window is hovered\n         return false;\n      if (ImGui::IsMouseHoveringRect(window->InnerRect.Min, window->InnerRect.Max, false))   // Hovering drawlist window rect, while no other window is hovered (for _NoInputs windows)\n         return true;\n      return false;\n   }\n\n   void SetRect(float x, float y, float width, float height)\n   {\n      gContext.mX = x;\n      gContext.mY = y;\n      gContext.mWidth = width;\n      gContext.mHeight = height;\n      gContext.mXMax = gContext.mX + gContext.mWidth;\n      gContext.mYMax = gContext.mY + gContext.mXMax;\n      gContext.mDisplayRatio = width / height;\n   }\n\n   void SetOrthographic(bool isOrthographic)\n   {\n      gContext.mIsOrthographic = isOrthographic;\n   }\n\n   void SetDrawlist(ImDrawList* drawlist)\n   {\n      gContext.mDrawList = drawlist ? drawlist : ImGui::GetWindowDrawList();\n   }\n\n   void SetImGuiContext(ImGuiContext* ctx)\n   {\n      ImGui::SetCurrentContext(ctx);\n   }\n\n   void BeginFrame()\n   {\n      const ImU32 flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus;\n\n#ifdef IMGUI_HAS_VIEWPORT\n      ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size);\n      ImGui::SetNextWindowPos(ImGui::GetMainViewport()->Pos);\n#else\n      ImGuiIO& io = ImGui::GetIO();\n      ImGui::SetNextWindowSize(io.DisplaySize);\n      ImGui::SetNextWindowPos(ImVec2(0, 0));\n#endif\n\n      ImGui::PushStyleColor(ImGuiCol_WindowBg, 0);\n      ImGui::PushStyleColor(ImGuiCol_Border, 0);\n      ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);\n\n      ImGui::Begin(\"gizmo\", NULL, flags);\n      gContext.mDrawList = ImGui::GetWindowDrawList();\n      ImGui::End();\n      ImGui::PopStyleVar();\n      ImGui::PopStyleColor(2);\n   }\n\n   bool IsUsing()\n   {\n      return gContext.mbUsing || gContext.mbUsingBounds;\n   }\n\n   bool IsOver()\n   {\n      return (Intersects(gContext.mOperation, TRANSLATE) && GetMoveType(gContext.mOperation, NULL) != MT_NONE) ||\n         (Intersects(gContext.mOperation, ROTATE) && GetRotateType(gContext.mOperation) != MT_NONE) ||\n         (Intersects(gContext.mOperation, SCALE) && GetScaleType(gContext.mOperation) != MT_NONE) || IsUsing();\n   }\n\n   bool IsOver(OPERATION op)\n   {\n      if(IsUsing())\n      {\n         return true;\n      }\n      if(Intersects(op, SCALE) && GetScaleType(op) != MT_NONE)\n      {\n         return true;\n      }\n      if(Intersects(op, ROTATE) && GetRotateType(op) != MT_NONE)\n      {\n         return true;\n      }\n      if(Intersects(op, TRANSLATE) && GetMoveType(op, NULL) != MT_NONE)\n      {\n         return true;\n      }\n      return false;\n   }\n\n   void Enable(bool enable)\n   {\n      gContext.mbEnable = enable;\n      if (!enable)\n      {\n         gContext.mbUsing = false;\n         gContext.mbUsingBounds = false;\n      }\n   }\n\n   static void ComputeContext(const float* view, const float* projection, float* matrix, MODE mode)\n   {\n      gContext.mMode = mode;\n      gContext.mViewMat = *(matrix_t*)view;\n      gContext.mProjectionMat = *(matrix_t*)projection;\n      gContext.mbMouseOver = IsHoveringWindow();\n\n      gContext.mModelLocal = *(matrix_t*)matrix;\n      gContext.mModelLocal.OrthoNormalize();\n\n      if (mode == LOCAL)\n      {\n         gContext.mModel = gContext.mModelLocal;\n      }\n      else\n      {\n         gContext.mModel.Translation(((matrix_t*)matrix)->v.position);\n      }\n      gContext.mModelSource = *(matrix_t*)matrix;\n      gContext.mModelScaleOrigin.Set(gContext.mModelSource.v.right.Length(), gContext.mModelSource.v.up.Length(), gContext.mModelSource.v.dir.Length());\n\n      gContext.mModelInverse.Inverse(gContext.mModel);\n      gContext.mModelSourceInverse.Inverse(gContext.mModelSource);\n      gContext.mViewProjection = gContext.mViewMat * gContext.mProjectionMat;\n      gContext.mMVP = gContext.mModel * gContext.mViewProjection;\n      gContext.mMVPLocal = gContext.mModelLocal * gContext.mViewProjection;\n\n      matrix_t viewInverse;\n      viewInverse.Inverse(gContext.mViewMat);\n      gContext.mCameraDir = viewInverse.v.dir;\n      gContext.mCameraEye = viewInverse.v.position;\n      gContext.mCameraRight = viewInverse.v.right;\n      gContext.mCameraUp = viewInverse.v.up;\n\n      // projection reverse\n       vec_t nearPos, farPos;\n       nearPos.Transform(makeVect(0, 0, 1.f, 1.f), gContext.mProjectionMat);\n       farPos.Transform(makeVect(0, 0, 2.f, 1.f), gContext.mProjectionMat);\n\n       gContext.mReversed = (nearPos.z/nearPos.w) > (farPos.z / farPos.w);\n\n      // compute scale from the size of camera right vector projected on screen at the matrix position\n      vec_t pointRight = viewInverse.v.right;\n      pointRight.TransformPoint(gContext.mViewProjection);\n      gContext.mScreenFactor = gContext.mGizmoSizeClipSpace / (pointRight.x / pointRight.w - gContext.mMVP.v.position.x / gContext.mMVP.v.position.w);\n\n      vec_t rightViewInverse = viewInverse.v.right;\n      rightViewInverse.TransformVector(gContext.mModelInverse);\n      float rightLength = GetSegmentLengthClipSpace(makeVect(0.f, 0.f), rightViewInverse);\n      gContext.mScreenFactor = gContext.mGizmoSizeClipSpace / rightLength;\n\n      ImVec2 centerSSpace = worldToPos(makeVect(0.f, 0.f), gContext.mMVP);\n      gContext.mScreenSquareCenter = centerSSpace;\n      gContext.mScreenSquareMin = ImVec2(centerSSpace.x - 10.f, centerSSpace.y - 10.f);\n      gContext.mScreenSquareMax = ImVec2(centerSSpace.x + 10.f, centerSSpace.y + 10.f);\n\n      ComputeCameraRay(gContext.mRayOrigin, gContext.mRayVector);\n   }\n\n   static void ComputeColors(ImU32* colors, int type, OPERATION operation)\n   {\n      if (gContext.mbEnable)\n      {\n         ImU32 selectionColor = GetColorU32(SELECTION);\n\n         switch (operation)\n         {\n         case TRANSLATE:\n            colors[0] = (type == MT_MOVE_SCREEN) ? selectionColor : IM_COL32_WHITE;\n            for (int i = 0; i < 3; i++)\n            {\n               colors[i + 1] = (type == (int)(MT_MOVE_X + i)) ? selectionColor : GetColorU32(DIRECTION_X + i);\n               colors[i + 4] = (type == (int)(MT_MOVE_YZ + i)) ? selectionColor : GetColorU32(PLANE_X + i);\n               colors[i + 4] = (type == MT_MOVE_SCREEN) ? selectionColor : colors[i + 4];\n            }\n            break;\n         case ROTATE:\n            colors[0] = (type == MT_ROTATE_SCREEN) ? selectionColor : IM_COL32_WHITE;\n            for (int i = 0; i < 3; i++)\n            {\n               colors[i + 1] = (type == (int)(MT_ROTATE_X + i)) ? selectionColor : GetColorU32(DIRECTION_X + i);\n            }\n            break;\n         case SCALEU:\n         case SCALE:\n            colors[0] = (type == MT_SCALE_XYZ) ? selectionColor : IM_COL32_WHITE;\n            for (int i = 0; i < 3; i++)\n            {\n               colors[i + 1] = (type == (int)(MT_SCALE_X + i)) ? selectionColor : GetColorU32(DIRECTION_X + i);\n            }\n            break;\n         // note: this internal function is only called with three possible values for operation\n         default:\n            break;\n         }\n      }\n      else\n      {\n         ImU32 inactiveColor = GetColorU32(INACTIVE);\n         for (int i = 0; i < 7; i++)\n         {\n            colors[i] = inactiveColor;\n         }\n      }\n   }\n\n   static void ComputeTripodAxisAndVisibility(const int axisIndex, vec_t& dirAxis, vec_t& dirPlaneX, vec_t& dirPlaneY, bool& belowAxisLimit, bool& belowPlaneLimit, const bool localCoordinates = false)\n   {\n      dirAxis = directionUnary[axisIndex];\n      dirPlaneX = directionUnary[(axisIndex + 1) % 3];\n      dirPlaneY = directionUnary[(axisIndex + 2) % 3];\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID))\n      {\n         // when using, use stored factors so the gizmo doesn't flip when we translate\n         belowAxisLimit = gContext.mBelowAxisLimit[axisIndex];\n         belowPlaneLimit = gContext.mBelowPlaneLimit[axisIndex];\n\n         dirAxis *= gContext.mAxisFactor[axisIndex];\n         dirPlaneX *= gContext.mAxisFactor[(axisIndex + 1) % 3];\n         dirPlaneY *= gContext.mAxisFactor[(axisIndex + 2) % 3];\n      }\n      else\n      {\n         // new method\n         float lenDir = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirAxis, localCoordinates);\n         float lenDirMinus = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), -dirAxis, localCoordinates);\n\n         float lenDirPlaneX = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirPlaneX, localCoordinates);\n         float lenDirMinusPlaneX = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), -dirPlaneX, localCoordinates);\n\n         float lenDirPlaneY = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirPlaneY, localCoordinates);\n         float lenDirMinusPlaneY = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), -dirPlaneY, localCoordinates);\n\n         // For readability\n         bool & allowFlip = gContext.mAllowAxisFlip;\n         float mulAxis = (allowFlip && lenDir < lenDirMinus&& fabsf(lenDir - lenDirMinus) > FLT_EPSILON) ? -1.f : 1.f;\n         float mulAxisX = (allowFlip && lenDirPlaneX < lenDirMinusPlaneX&& fabsf(lenDirPlaneX - lenDirMinusPlaneX) > FLT_EPSILON) ? -1.f : 1.f;\n         float mulAxisY = (allowFlip && lenDirPlaneY < lenDirMinusPlaneY&& fabsf(lenDirPlaneY - lenDirMinusPlaneY) > FLT_EPSILON) ? -1.f : 1.f;\n         dirAxis *= mulAxis;\n         dirPlaneX *= mulAxisX;\n         dirPlaneY *= mulAxisY;\n\n         // for axis\n         float axisLengthInClipSpace = GetSegmentLengthClipSpace(makeVect(0.f, 0.f, 0.f), dirAxis * gContext.mScreenFactor, localCoordinates);\n\n         float paraSurf = GetParallelogram(makeVect(0.f, 0.f, 0.f), dirPlaneX * gContext.mScreenFactor, dirPlaneY * gContext.mScreenFactor);\n         belowPlaneLimit = (paraSurf > 0.0025f);\n         belowAxisLimit = (axisLengthInClipSpace > 0.02f);\n\n         // and store values\n         gContext.mAxisFactor[axisIndex] = mulAxis;\n         gContext.mAxisFactor[(axisIndex + 1) % 3] = mulAxisX;\n         gContext.mAxisFactor[(axisIndex + 2) % 3] = mulAxisY;\n         gContext.mBelowAxisLimit[axisIndex] = belowAxisLimit;\n         gContext.mBelowPlaneLimit[axisIndex] = belowPlaneLimit;\n      }\n   }\n\n   static void ComputeSnap(float* value, float snap)\n   {\n      if (snap <= FLT_EPSILON)\n      {\n         return;\n      }\n\n      float modulo = fmodf(*value, snap);\n      float moduloRatio = fabsf(modulo) / snap;\n      if (moduloRatio < snapTension)\n      {\n         *value -= modulo;\n      }\n      else if (moduloRatio > (1.f - snapTension))\n      {\n         *value = *value - modulo + snap * ((*value < 0.f) ? -1.f : 1.f);\n      }\n   }\n   static void ComputeSnap(vec_t& value, const float* snap)\n   {\n      for (int i = 0; i < 3; i++)\n      {\n         ComputeSnap(&value[i], snap[i]);\n      }\n   }\n\n   static float ComputeAngleOnPlan()\n   {\n      const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);\n      vec_t localPos = Normalized(gContext.mRayOrigin + gContext.mRayVector * len - gContext.mModel.v.position);\n\n      vec_t perpendicularVector;\n      perpendicularVector.Cross(gContext.mRotationVectorSource, gContext.mTranslationPlan);\n      perpendicularVector.Normalize();\n      float acosAngle = Clamp(Dot(localPos, gContext.mRotationVectorSource), -1.f, 1.f);\n      float angle = acosf(acosAngle);\n      angle *= (Dot(localPos, perpendicularVector) < 0.f) ? 1.f : -1.f;\n      return angle;\n   }\n\n   static void DrawRotationGizmo(OPERATION op, int type)\n   {\n      if(!Intersects(op, ROTATE))\n      {\n         return;\n      }\n      ImDrawList* drawList = gContext.mDrawList;\n\n      // colors\n      ImU32 colors[7];\n      ComputeColors(colors, type, ROTATE);\n\n      vec_t cameraToModelNormalized;\n      if (gContext.mIsOrthographic)\n      {\n         matrix_t viewInverse;\n         viewInverse.Inverse(*(matrix_t*)&gContext.mViewMat);\n         cameraToModelNormalized = -viewInverse.v.dir;\n      }\n      else\n      {\n         cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);\n      }\n\n      cameraToModelNormalized.TransformVector(gContext.mModelInverse);\n\n      gContext.mRadiusSquareCenter = screenRotateSize * gContext.mHeight;\n\n      bool hasRSC = Intersects(op, ROTATE_SCREEN);\n      for (int axis = 0; axis < 3; axis++)\n      {\n         if(!Intersects(op, static_cast<OPERATION>(ROTATE_Z >> axis)))\n         {\n            continue;\n         }\n         const bool usingAxis = (gContext.mbUsing && type == MT_ROTATE_Z - axis);\n         const int circleMul = (hasRSC && !usingAxis ) ? 1 : 2;\n\n         ImVec2* circlePos = (ImVec2*)alloca(sizeof(ImVec2) * (circleMul * halfCircleSegmentCount + 1));\n\n         float angleStart = atan2f(cameraToModelNormalized[(4 - axis) % 3], cameraToModelNormalized[(3 - axis) % 3]) + ZPI * 0.5f;\n\n         for (int i = 0; i < circleMul * halfCircleSegmentCount + 1; i++)\n         {\n            float ng = angleStart + (float)circleMul * ZPI * ((float)i / (float)halfCircleSegmentCount);\n            vec_t axisPos = makeVect(cosf(ng), sinf(ng), 0.f);\n            vec_t pos = makeVect(axisPos[axis], axisPos[(axis + 1) % 3], axisPos[(axis + 2) % 3]) * gContext.mScreenFactor * rotationDisplayFactor;\n            circlePos[i] = worldToPos(pos, gContext.mMVP);\n         }\n         if (!gContext.mbUsing || usingAxis)\n         {\n            drawList->AddPolyline(circlePos, circleMul* halfCircleSegmentCount + 1, colors[3 - axis], false, gContext.mStyle.RotationLineThickness);\n         }\n\n         float radiusAxis = sqrtf((ImLengthSqr(worldToPos(gContext.mModel.v.position, gContext.mViewProjection) - circlePos[0])));\n         if (radiusAxis > gContext.mRadiusSquareCenter)\n         {\n            gContext.mRadiusSquareCenter = radiusAxis;\n         }\n      }\n      if(hasRSC && (!gContext.mbUsing || type == MT_ROTATE_SCREEN))\n      {\n         drawList->AddCircle(worldToPos(gContext.mModel.v.position, gContext.mViewProjection), gContext.mRadiusSquareCenter, colors[0], 64, gContext.mStyle.RotationOuterLineThickness);\n      }\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsRotateType(type))\n      {\n         ImVec2 circlePos[halfCircleSegmentCount + 1];\n\n         circlePos[0] = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);\n         for (unsigned int i = 1; i < halfCircleSegmentCount; i++)\n         {\n            float ng = gContext.mRotationAngle * ((float)(i - 1) / (float)(halfCircleSegmentCount - 1));\n            matrix_t rotateVectorMatrix;\n            rotateVectorMatrix.RotationAxis(gContext.mTranslationPlan, ng);\n            vec_t pos;\n            pos.TransformPoint(gContext.mRotationVectorSource, rotateVectorMatrix);\n            pos *= gContext.mScreenFactor * rotationDisplayFactor;\n            circlePos[i] = worldToPos(pos + gContext.mModel.v.position, gContext.mViewProjection);\n         }\n         drawList->AddConvexPolyFilled(circlePos, halfCircleSegmentCount, GetColorU32(ROTATION_USING_FILL));\n         drawList->AddPolyline(circlePos, halfCircleSegmentCount, GetColorU32(ROTATION_USING_BORDER), true, gContext.mStyle.RotationLineThickness);\n\n         ImVec2 destinationPosOnScreen = circlePos[1];\n         char tmps[512];\n         ImFormatString(tmps, sizeof(tmps), rotationInfoMask[type - MT_ROTATE_X], (gContext.mRotationAngle / ZPI) * 180.f, gContext.mRotationAngle);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), GetColorU32(TEXT_SHADOW), tmps);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), GetColorU32(TEXT), tmps);\n      }\n   }\n\n   static void DrawHatchedAxis(const vec_t& axis)\n   {\n      if (gContext.mStyle.HatchedAxisLineThickness <= 0.0f)\n      {\n         return;\n      }\n\n      for (int j = 1; j < 10; j++)\n      {\n         ImVec2 baseSSpace2 = worldToPos(axis * 0.05f * (float)(j * 2) * gContext.mScreenFactor, gContext.mMVP);\n         ImVec2 worldDirSSpace2 = worldToPos(axis * 0.05f * (float)(j * 2 + 1) * gContext.mScreenFactor, gContext.mMVP);\n         gContext.mDrawList->AddLine(baseSSpace2, worldDirSSpace2, GetColorU32(HATCHED_AXIS_LINES), gContext.mStyle.HatchedAxisLineThickness);\n      }\n   }\n\n   static void DrawScaleGizmo(OPERATION op, int type)\n   {\n      ImDrawList* drawList = gContext.mDrawList;\n\n      if(!Intersects(op, SCALE))\n      {\n        return;\n      }\n\n      // colors\n      ImU32 colors[7];\n      ComputeColors(colors, type, SCALE);\n\n      // draw\n      vec_t scaleDisplay = { 1.f, 1.f, 1.f, 1.f };\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID))\n      {\n         scaleDisplay = gContext.mScale;\n      }\n\n      for (int i = 0; i < 3; i++)\n      {\n         if(!Intersects(op, static_cast<OPERATION>(SCALE_X << i)))\n         {\n            continue;\n         }\n         const bool usingAxis = (gContext.mbUsing && type == MT_SCALE_X + i);\n         if (!gContext.mbUsing || usingAxis)\n         {\n            vec_t dirPlaneX, dirPlaneY, dirAxis;\n            bool belowAxisLimit, belowPlaneLimit;\n            ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit, true);\n\n            // draw axis\n            if (belowAxisLimit)\n            {\n               bool hasTranslateOnAxis = Contains(op, static_cast<OPERATION>(TRANSLATE_X << i));\n               float markerScale = hasTranslateOnAxis ? 1.4f : 1.0f;\n               ImVec2 baseSSpace = worldToPos(dirAxis * 0.1f * gContext.mScreenFactor, gContext.mMVP);\n               ImVec2 worldDirSSpaceNoScale = worldToPos(dirAxis * markerScale * gContext.mScreenFactor, gContext.mMVP);\n               ImVec2 worldDirSSpace = worldToPos((dirAxis * markerScale * scaleDisplay[i]) * gContext.mScreenFactor, gContext.mMVP);\n\n               if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID))\n               {\n                  ImU32 scaleLineColor = GetColorU32(SCALE_LINE);\n                  drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, scaleLineColor, gContext.mStyle.ScaleLineThickness);\n                  drawList->AddCircleFilled(worldDirSSpaceNoScale, gContext.mStyle.ScaleLineCircleSize, scaleLineColor);\n               }\n\n               if (!hasTranslateOnAxis || gContext.mbUsing)\n               {\n                  drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], gContext.mStyle.ScaleLineThickness);\n               }\n               drawList->AddCircleFilled(worldDirSSpace, gContext.mStyle.ScaleLineCircleSize, colors[i + 1]);\n\n               if (gContext.mAxisFactor[i] < 0.f)\n               {\n                  DrawHatchedAxis(dirAxis * scaleDisplay[i]);\n               }\n            }\n         }\n      }\n\n      // draw screen cirle\n      drawList->AddCircleFilled(gContext.mScreenSquareCenter, gContext.mStyle.CenterCircleSize, colors[0], 32);\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsScaleType(type))\n      {\n         //ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);\n         ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);\n         /*vec_t dif(destinationPosOnScreen.x - sourcePosOnScreen.x, destinationPosOnScreen.y - sourcePosOnScreen.y);\n         dif.Normalize();\n         dif *= 5.f;\n         drawList->AddCircle(sourcePosOnScreen, 6.f, translationLineColor);\n         drawList->AddCircle(destinationPosOnScreen, 6.f, translationLineColor);\n         drawList->AddLine(ImVec2(sourcePosOnScreen.x + dif.x, sourcePosOnScreen.y + dif.y), ImVec2(destinationPosOnScreen.x - dif.x, destinationPosOnScreen.y - dif.y), translationLineColor, 2.f);\n         */\n         char tmps[512];\n         //vec_t deltaInfo = gContext.mModel.v.position - gContext.mMatrixOrigin;\n         int componentInfoIndex = (type - MT_SCALE_X) * 3;\n         ImFormatString(tmps, sizeof(tmps), scaleInfoMask[type - MT_SCALE_X], scaleDisplay[translationInfoIndex[componentInfoIndex]]);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), GetColorU32(TEXT_SHADOW), tmps);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), GetColorU32(TEXT), tmps);\n      }\n   }\n\n\n   static void DrawScaleUniveralGizmo(OPERATION op, int type)\n   {\n      ImDrawList* drawList = gContext.mDrawList;\n\n      if (!Intersects(op, SCALEU))\n      {\n         return;\n      }\n\n      // colors\n      ImU32 colors[7];\n      ComputeColors(colors, type, SCALEU);\n\n      // draw\n      vec_t scaleDisplay = { 1.f, 1.f, 1.f, 1.f };\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID))\n      {\n         scaleDisplay = gContext.mScale;\n      }\n\n      for (int i = 0; i < 3; i++)\n      {\n         if (!Intersects(op, static_cast<OPERATION>(SCALE_XU << i)))\n         {\n            continue;\n         }\n         const bool usingAxis = (gContext.mbUsing && type == MT_SCALE_X + i);\n         if (!gContext.mbUsing || usingAxis)\n         {\n            vec_t dirPlaneX, dirPlaneY, dirAxis;\n            bool belowAxisLimit, belowPlaneLimit;\n            ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit, true);\n\n            // draw axis\n            if (belowAxisLimit)\n            {\n               bool hasTranslateOnAxis = Contains(op, static_cast<OPERATION>(TRANSLATE_X << i));\n               float markerScale = hasTranslateOnAxis ? 1.4f : 1.0f;\n               //ImVec2 baseSSpace = worldToPos(dirAxis * 0.1f * gContext.mScreenFactor, gContext.mMVPLocal);\n               //ImVec2 worldDirSSpaceNoScale = worldToPos(dirAxis * markerScale * gContext.mScreenFactor, gContext.mMVP);\n               ImVec2 worldDirSSpace = worldToPos((dirAxis * markerScale * scaleDisplay[i]) * gContext.mScreenFactor, gContext.mMVPLocal);\n\n#if 0\n               if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID))\n               {\n                  drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, IM_COL32(0x40, 0x40, 0x40, 0xFF), 3.f);\n                  drawList->AddCircleFilled(worldDirSSpaceNoScale, 6.f, IM_COL32(0x40, 0x40, 0x40, 0xFF));\n               }\n               /*\n               if (!hasTranslateOnAxis || gContext.mbUsing)\n               {\n                  drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);\n               }\n               */\n#endif\n               drawList->AddCircleFilled(worldDirSSpace, 12.f, colors[i + 1]);\n            }\n         }\n      }\n\n      // draw screen cirle\n      drawList->AddCircle(gContext.mScreenSquareCenter, 20.f, colors[0], 32, gContext.mStyle.CenterCircleSize);\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsScaleType(type))\n      {\n         //ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);\n         ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);\n         /*vec_t dif(destinationPosOnScreen.x - sourcePosOnScreen.x, destinationPosOnScreen.y - sourcePosOnScreen.y);\n         dif.Normalize();\n         dif *= 5.f;\n         drawList->AddCircle(sourcePosOnScreen, 6.f, translationLineColor);\n         drawList->AddCircle(destinationPosOnScreen, 6.f, translationLineColor);\n         drawList->AddLine(ImVec2(sourcePosOnScreen.x + dif.x, sourcePosOnScreen.y + dif.y), ImVec2(destinationPosOnScreen.x - dif.x, destinationPosOnScreen.y - dif.y), translationLineColor, 2.f);\n         */\n         char tmps[512];\n         //vec_t deltaInfo = gContext.mModel.v.position - gContext.mMatrixOrigin;\n         int componentInfoIndex = (type - MT_SCALE_X) * 3;\n         ImFormatString(tmps, sizeof(tmps), scaleInfoMask[type - MT_SCALE_X], scaleDisplay[translationInfoIndex[componentInfoIndex]]);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), GetColorU32(TEXT_SHADOW), tmps);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), GetColorU32(TEXT), tmps);\n      }\n   }\n\n   static void DrawTranslationGizmo(OPERATION op, int type)\n   {\n      ImDrawList* drawList = gContext.mDrawList;\n      if (!drawList)\n      {\n         return;\n      }\n\n      if(!Intersects(op, TRANSLATE))\n      {\n         return;\n      }\n\n      // colors\n      ImU32 colors[7];\n      ComputeColors(colors, type, TRANSLATE);\n\n      const ImVec2 origin = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);\n\n      // draw\n      bool belowAxisLimit = false;\n      bool belowPlaneLimit = false;\n      for (int i = 0; i < 3; ++i)\n      {\n         vec_t dirPlaneX, dirPlaneY, dirAxis;\n         ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);\n\n         if (!gContext.mbUsing || (gContext.mbUsing && type == MT_MOVE_X + i))\n         {\n            // draw axis\n            if (belowAxisLimit && Intersects(op, static_cast<OPERATION>(TRANSLATE_X << i)))\n            {\n               ImVec2 baseSSpace = worldToPos(dirAxis * 0.1f * gContext.mScreenFactor, gContext.mMVP);\n               ImVec2 worldDirSSpace = worldToPos(dirAxis * gContext.mScreenFactor, gContext.mMVP);\n\n               drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], gContext.mStyle.TranslationLineThickness);\n\n               // Arrow head begin\n               ImVec2 dir(origin - worldDirSSpace);\n\n               float d = sqrtf(ImLengthSqr(dir));\n               dir /= d; // Normalize\n               dir *= gContext.mStyle.TranslationLineArrowSize;\n\n               ImVec2 ortogonalDir(dir.y, -dir.x); // Perpendicular vector\n               ImVec2 a(worldDirSSpace + dir);\n               drawList->AddTriangleFilled(worldDirSSpace - dir, a + ortogonalDir, a - ortogonalDir, colors[i + 1]);\n               // Arrow head end\n\n               if (gContext.mAxisFactor[i] < 0.f)\n               {\n                  DrawHatchedAxis(dirAxis);\n               }\n            }\n         }\n         // draw plane\n         if (!gContext.mbUsing || (gContext.mbUsing && type == MT_MOVE_YZ + i))\n         {\n            if (belowPlaneLimit && Contains(op, TRANSLATE_PLANS[i]))\n            {\n               ImVec2 screenQuadPts[4];\n               for (int j = 0; j < 4; ++j)\n               {\n                  vec_t cornerWorldPos = (dirPlaneX * quadUV[j * 2] + dirPlaneY * quadUV[j * 2 + 1]) * gContext.mScreenFactor;\n                  screenQuadPts[j] = worldToPos(cornerWorldPos, gContext.mMVP);\n               }\n               drawList->AddPolyline(screenQuadPts, 4, GetColorU32(DIRECTION_X + i), true, 1.0f);\n               drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4]);\n            }\n         }\n      }\n\n      drawList->AddCircleFilled(gContext.mScreenSquareCenter, gContext.mStyle.CenterCircleSize, colors[0], 32);\n\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsTranslateType(type))\n      {\n         ImU32 translationLineColor = GetColorU32(TRANSLATION_LINE);\n\n         ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);\n         ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);\n         vec_t dif = { destinationPosOnScreen.x - sourcePosOnScreen.x, destinationPosOnScreen.y - sourcePosOnScreen.y, 0.f, 0.f };\n         dif.Normalize();\n         dif *= 5.f;\n         drawList->AddCircle(sourcePosOnScreen, 6.f, translationLineColor);\n         drawList->AddCircle(destinationPosOnScreen, 6.f, translationLineColor);\n         drawList->AddLine(ImVec2(sourcePosOnScreen.x + dif.x, sourcePosOnScreen.y + dif.y), ImVec2(destinationPosOnScreen.x - dif.x, destinationPosOnScreen.y - dif.y), translationLineColor, 2.f);\n\n         char tmps[512];\n         vec_t deltaInfo = gContext.mModel.v.position - gContext.mMatrixOrigin;\n         int componentInfoIndex = (type - MT_MOVE_X) * 3;\n         ImFormatString(tmps, sizeof(tmps), translationInfoMask[type - MT_MOVE_X], deltaInfo[translationInfoIndex[componentInfoIndex]], deltaInfo[translationInfoIndex[componentInfoIndex + 1]], deltaInfo[translationInfoIndex[componentInfoIndex + 2]]);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), GetColorU32(TEXT_SHADOW), tmps);\n         drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), GetColorU32(TEXT), tmps);\n      }\n   }\n\n   static bool CanActivate()\n   {\n      if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && !ImGui::IsAnyItemActive())\n      {\n         return true;\n      }\n      return false;\n   }\n\n   static void HandleAndDrawLocalBounds(const float* bounds, matrix_t* matrix, const float* snapValues, OPERATION operation)\n   {\n      ImGuiIO& io = ImGui::GetIO();\n      ImDrawList* drawList = gContext.mDrawList;\n\n      // compute best projection axis\n      vec_t axesWorldDirections[3];\n      vec_t bestAxisWorldDirection = { 0.0f, 0.0f, 0.0f, 0.0f };\n      int axes[3];\n      unsigned int numAxes = 1;\n      axes[0] = gContext.mBoundsBestAxis;\n      int bestAxis = axes[0];\n      if (!gContext.mbUsingBounds)\n      {\n         numAxes = 0;\n         float bestDot = 0.f;\n         for (int i = 0; i < 3; i++)\n         {\n            vec_t dirPlaneNormalWorld;\n            dirPlaneNormalWorld.TransformVector(directionUnary[i], gContext.mModelSource);\n            dirPlaneNormalWorld.Normalize();\n\n            float dt = fabsf(Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld));\n            if (dt >= bestDot)\n            {\n               bestDot = dt;\n               bestAxis = i;\n               bestAxisWorldDirection = dirPlaneNormalWorld;\n            }\n\n            if (dt >= 0.1f)\n            {\n               axes[numAxes] = i;\n               axesWorldDirections[numAxes] = dirPlaneNormalWorld;\n               ++numAxes;\n            }\n         }\n      }\n\n      if (numAxes == 0)\n      {\n         axes[0] = bestAxis;\n         axesWorldDirections[0] = bestAxisWorldDirection;\n         numAxes = 1;\n      }\n\n      else if (bestAxis != axes[0])\n      {\n         unsigned int bestIndex = 0;\n         for (unsigned int i = 0; i < numAxes; i++)\n         {\n            if (axes[i] == bestAxis)\n            {\n               bestIndex = i;\n               break;\n            }\n         }\n         int tempAxis = axes[0];\n         axes[0] = axes[bestIndex];\n         axes[bestIndex] = tempAxis;\n         vec_t tempDirection = axesWorldDirections[0];\n         axesWorldDirections[0] = axesWorldDirections[bestIndex];\n         axesWorldDirections[bestIndex] = tempDirection;\n      }\n\n      for (unsigned int axisIndex = 0; axisIndex < numAxes; ++axisIndex)\n      {\n         bestAxis = axes[axisIndex];\n         bestAxisWorldDirection = axesWorldDirections[axisIndex];\n\n         // corners\n         vec_t aabb[4];\n\n         int secondAxis = (bestAxis + 1) % 3;\n         int thirdAxis = (bestAxis + 2) % 3;\n\n         for (int i = 0; i < 4; i++)\n         {\n            aabb[i][3] = aabb[i][bestAxis] = 0.f;\n            aabb[i][secondAxis] = bounds[secondAxis + 3 * (i >> 1)];\n            aabb[i][thirdAxis] = bounds[thirdAxis + 3 * ((i >> 1) ^ (i & 1))];\n         }\n\n         // draw bounds\n         unsigned int anchorAlpha = gContext.mbEnable ? IM_COL32_BLACK : IM_COL32(0, 0, 0, 0x80);\n\n         matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection;\n         for (int i = 0; i < 4; i++)\n         {\n            ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP);\n            ImVec2 worldBound2 = worldToPos(aabb[(i + 1) % 4], boundsMVP);\n            if (!IsInContextRect(worldBound1) || !IsInContextRect(worldBound2))\n            {\n               continue;\n            }\n            float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2));\n            int stepCount = (int)(boundDistance / 10.f);\n            stepCount = min(stepCount, 1000);\n            for (int j = 0; j < stepCount; j++)\n            {\n               float stepLength = 1.f / (float)stepCount;\n               float t1 = (float)j * stepLength;\n               float t2 = (float)j * stepLength + stepLength * 0.5f;\n               ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1));\n               ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2));\n               //drawList->AddLine(worldBoundSS1, worldBoundSS2, IM_COL32(0, 0, 0, 0) + anchorAlpha, 3.f);\n               drawList->AddLine(worldBoundSS1, worldBoundSS2, IM_COL32(0xAA, 0xAA, 0xAA, 0) + anchorAlpha, 2.f);\n            }\n            vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4]) * 0.5f;\n            ImVec2 midBound = worldToPos(midPoint, boundsMVP);\n            static const float AnchorBigRadius = 8.f;\n            static const float AnchorSmallRadius = 6.f;\n            bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius * AnchorBigRadius);\n            bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius * AnchorBigRadius);\n\n            int type = MT_NONE;\n            vec_t gizmoHitProportion;\n\n            if(Intersects(operation, TRANSLATE))\n            {\n               type = GetMoveType(operation, &gizmoHitProportion);\n            }\n            if(Intersects(operation, ROTATE) && type == MT_NONE)\n            {\n               type = GetRotateType(operation);\n            }\n            if(Intersects(operation, SCALE) && type == MT_NONE)\n            {\n               type = GetScaleType(operation);\n            }\n\n            if (type != MT_NONE)\n            {\n               overBigAnchor = false;\n               overSmallAnchor = false;\n            }\n\n            ImU32 selectionColor = GetColorU32(SELECTION);\n\n            unsigned int bigAnchorColor = overBigAnchor ? selectionColor : (IM_COL32(0xAA, 0xAA, 0xAA, 0) + anchorAlpha);\n            unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (IM_COL32(0xAA, 0xAA, 0xAA, 0) + anchorAlpha);\n\n            drawList->AddCircleFilled(worldBound1, AnchorBigRadius, IM_COL32_BLACK);\n            drawList->AddCircleFilled(worldBound1, AnchorBigRadius - 1.2f, bigAnchorColor);\n\n            drawList->AddCircleFilled(midBound, AnchorSmallRadius, IM_COL32_BLACK);\n            drawList->AddCircleFilled(midBound, AnchorSmallRadius - 1.2f, smallAnchorColor);\n            int oppositeIndex = (i + 2) % 4;\n            // big anchor on corners\n            if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && CanActivate())\n            {\n               gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource);\n               gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource);\n               gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);\n               gContext.mBoundsBestAxis = bestAxis;\n               gContext.mBoundsAxis[0] = secondAxis;\n               gContext.mBoundsAxis[1] = thirdAxis;\n\n               gContext.mBoundsLocalPivot.Set(0.f);\n               gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis];\n               gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis];\n\n               gContext.mbUsingBounds = true;\n               gContext.mEditingID = gContext.mActualID;\n               gContext.mBoundsMatrix = gContext.mModelSource;\n            }\n            // small anchor on middle of segment\n            if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && CanActivate())\n            {\n               vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f;\n               gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource);\n               gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource);\n               gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);\n               gContext.mBoundsBestAxis = bestAxis;\n               int indices[] = { secondAxis , thirdAxis };\n               gContext.mBoundsAxis[0] = indices[i % 2];\n               gContext.mBoundsAxis[1] = -1;\n\n               gContext.mBoundsLocalPivot.Set(0.f);\n               gContext.mBoundsLocalPivot[gContext.mBoundsAxis[0]] = aabb[oppositeIndex][indices[i % 2]];// bounds[gContext.mBoundsAxis[0]] * (((i + 1) & 2) ? 1.f : -1.f);\n\n               gContext.mbUsingBounds = true;\n               gContext.mEditingID = gContext.mActualID;\n               gContext.mBoundsMatrix = gContext.mModelSource;\n            }\n         }\n\n         if (gContext.mbUsingBounds && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID))\n         {\n            matrix_t scale;\n            scale.SetToIdentity();\n\n            // compute projected mouse position on plan\n            const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan);\n            vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;\n\n            // compute a reference and delta vectors base on mouse move\n            vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs();\n            vec_t referenceVector = (gContext.mBoundsAnchor - gContext.mBoundsPivot).Abs();\n\n            // for 1 or 2 axes, compute a ratio that's used for scale and snap it based on resulting length\n            for (int i = 0; i < 2; i++)\n            {\n               int axisIndex1 = gContext.mBoundsAxis[i];\n               if (axisIndex1 == -1)\n               {\n                  continue;\n               }\n\n               float ratioAxis = 1.f;\n               vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex1].Abs();\n\n               float dtAxis = axisDir.Dot(referenceVector);\n               float boundSize = bounds[axisIndex1 + 3] - bounds[axisIndex1];\n               if (dtAxis > FLT_EPSILON)\n               {\n                  ratioAxis = axisDir.Dot(deltaVector) / dtAxis;\n               }\n\n               if (snapValues)\n               {\n                  float length = boundSize * ratioAxis;\n                  ComputeSnap(&length, snapValues[axisIndex1]);\n                  if (boundSize > FLT_EPSILON)\n                  {\n                     ratioAxis = length / boundSize;\n                  }\n               }\n               scale.component[axisIndex1] *= ratioAxis;\n            }\n\n            // transform matrix\n            matrix_t preScale, postScale;\n            preScale.Translation(-gContext.mBoundsLocalPivot);\n            postScale.Translation(gContext.mBoundsLocalPivot);\n            matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix;\n            *matrix = res;\n\n            // info text\n            char tmps[512];\n            ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);\n            ImFormatString(tmps, sizeof(tmps), \"X: %.2f Y: %.2f Z: %.2f\"\n               , (bounds[3] - bounds[0]) * gContext.mBoundsMatrix.component[0].Length() * scale.component[0].Length()\n               , (bounds[4] - bounds[1]) * gContext.mBoundsMatrix.component[1].Length() * scale.component[1].Length()\n               , (bounds[5] - bounds[2]) * gContext.mBoundsMatrix.component[2].Length() * scale.component[2].Length()\n            );\n            drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), GetColorU32(TEXT_SHADOW), tmps);\n            drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), GetColorU32(TEXT), tmps);\n         }\n\n         if (!io.MouseDown[0]) {\n            gContext.mbUsingBounds = false;\n            gContext.mEditingID = -1;\n         }\n         if (gContext.mbUsingBounds)\n         {\n            break;\n         }\n      }\n   }\n\n   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n   //\n\n   static int GetScaleType(OPERATION op)\n   {\n      if (gContext.mbUsing)\n      {\n         return MT_NONE;\n      }\n      ImGuiIO& io = ImGui::GetIO();\n      int type = MT_NONE;\n\n      // screen\n      if (io.MousePos.x >= gContext.mScreenSquareMin.x && io.MousePos.x <= gContext.mScreenSquareMax.x &&\n         io.MousePos.y >= gContext.mScreenSquareMin.y && io.MousePos.y <= gContext.mScreenSquareMax.y &&\n         Contains(op, SCALE))\n      {\n         type = MT_SCALE_XYZ;\n      }\n\n      // compute\n      for (int i = 0; i < 3 && type == MT_NONE; i++)\n      {\n         if(!Intersects(op, static_cast<OPERATION>(SCALE_X << i)))\n         {\n            continue;\n         }\n         vec_t dirPlaneX, dirPlaneY, dirAxis;\n         bool belowAxisLimit, belowPlaneLimit;\n         ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit, true);\n         dirAxis.TransformVector(gContext.mModelLocal);\n         dirPlaneX.TransformVector(gContext.mModelLocal);\n         dirPlaneY.TransformVector(gContext.mModelLocal);\n\n         const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, BuildPlan(gContext.mModelLocal.v.position, dirAxis));\n         vec_t posOnPlan = gContext.mRayOrigin + gContext.mRayVector * len;\n\n         const float startOffset = Contains(op, static_cast<OPERATION>(TRANSLATE_X << i)) ? 1.0f : 0.1f;\n         const float endOffset = Contains(op, static_cast<OPERATION>(TRANSLATE_X << i)) ? 1.4f : 1.0f;\n         const ImVec2 posOnPlanScreen = worldToPos(posOnPlan, gContext.mViewProjection);\n         const ImVec2 axisStartOnScreen = worldToPos(gContext.mModelLocal.v.position + dirAxis * gContext.mScreenFactor * startOffset, gContext.mViewProjection);\n         const ImVec2 axisEndOnScreen = worldToPos(gContext.mModelLocal.v.position + dirAxis * gContext.mScreenFactor * endOffset, gContext.mViewProjection);\n\n         vec_t closestPointOnAxis = PointOnSegment(makeVect(posOnPlanScreen), makeVect(axisStartOnScreen), makeVect(axisEndOnScreen));\n\n         if ((closestPointOnAxis - makeVect(posOnPlanScreen)).Length() < 12.f) // pixel size\n         {\n            type = MT_SCALE_X + i;\n         }\n      }\n\n      // universal\n\n      vec_t deltaScreen = { io.MousePos.x - gContext.mScreenSquareCenter.x, io.MousePos.y - gContext.mScreenSquareCenter.y, 0.f, 0.f };\n      float dist = deltaScreen.Length();\n      if (Contains(op, SCALEU) && dist >= 17.0f && dist < 23.0f)\n      {\n         type = MT_SCALE_XYZ;\n      }\n\n      for (int i = 0; i < 3 && type == MT_NONE; i++)\n      {\n         if (!Intersects(op, static_cast<OPERATION>(SCALE_XU << i)))\n         {\n            continue;\n         }\n\n         vec_t dirPlaneX, dirPlaneY, dirAxis;\n         bool belowAxisLimit, belowPlaneLimit;\n         ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit, true);\n\n         // draw axis\n         if (belowAxisLimit)\n         {\n            bool hasTranslateOnAxis = Contains(op, static_cast<OPERATION>(TRANSLATE_X << i));\n            float markerScale = hasTranslateOnAxis ? 1.4f : 1.0f;\n            //ImVec2 baseSSpace = worldToPos(dirAxis * 0.1f * gContext.mScreenFactor, gContext.mMVPLocal);\n            //ImVec2 worldDirSSpaceNoScale = worldToPos(dirAxis * markerScale * gContext.mScreenFactor, gContext.mMVP);\n            ImVec2 worldDirSSpace = worldToPos((dirAxis * markerScale) * gContext.mScreenFactor, gContext.mMVPLocal);\n\n            float distance = sqrtf(ImLengthSqr(worldDirSSpace - io.MousePos));\n            if (distance < 12.f)\n            {\n               type = MT_SCALE_X + i;\n            }\n         }\n      }\n      return type;\n   }\n\n   static int GetRotateType(OPERATION op)\n   {\n      if (gContext.mbUsing)\n      {\n         return MT_NONE;\n      }\n      ImGuiIO& io = ImGui::GetIO();\n      int type = MT_NONE;\n\n      vec_t deltaScreen = { io.MousePos.x - gContext.mScreenSquareCenter.x, io.MousePos.y - gContext.mScreenSquareCenter.y, 0.f, 0.f };\n      float dist = deltaScreen.Length();\n      if (Intersects(op, ROTATE_SCREEN) && dist >= (gContext.mRadiusSquareCenter - 4.0f) && dist < (gContext.mRadiusSquareCenter + 4.0f))\n      {\n         type = MT_ROTATE_SCREEN;\n      }\n\n      const vec_t planNormals[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir };\n\n      vec_t modelViewPos;\n      modelViewPos.TransformPoint(gContext.mModel.v.position, gContext.mViewMat);\n\n      for (int i = 0; i < 3 && type == MT_NONE; i++)\n      {\n         if(!Intersects(op, static_cast<OPERATION>(ROTATE_X << i)))\n         {\n            continue;\n         }\n         // pickup plan\n         vec_t pickupPlan = BuildPlan(gContext.mModel.v.position, planNormals[i]);\n\n         const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, pickupPlan);\n         const vec_t intersectWorldPos = gContext.mRayOrigin + gContext.mRayVector * len;\n         vec_t intersectViewPos;\n         intersectViewPos.TransformPoint(intersectWorldPos, gContext.mViewMat);\n\n         if (ImAbs(modelViewPos.z) - ImAbs(intersectViewPos.z) < -FLT_EPSILON)\n         {\n            continue;\n         }\n\n         const vec_t localPos = intersectWorldPos - gContext.mModel.v.position;\n         vec_t idealPosOnCircle = Normalized(localPos);\n         idealPosOnCircle.TransformVector(gContext.mModelInverse);\n         const ImVec2 idealPosOnCircleScreen = worldToPos(idealPosOnCircle * rotationDisplayFactor * gContext.mScreenFactor, gContext.mMVP);\n\n         //gContext.mDrawList->AddCircle(idealPosOnCircleScreen, 5.f, IM_COL32_WHITE);\n         const ImVec2 distanceOnScreen = idealPosOnCircleScreen - io.MousePos;\n\n         const float distance = makeVect(distanceOnScreen).Length();\n         if (distance < 8.f) // pixel size\n         {\n            type = MT_ROTATE_X + i;\n         }\n      }\n\n      return type;\n   }\n\n   static int GetMoveType(OPERATION op, vec_t* gizmoHitProportion)\n   {\n      if(!Intersects(op, TRANSLATE) || gContext.mbUsing || !gContext.mbMouseOver)\n      {\n        return MT_NONE;\n      }\n      ImGuiIO& io = ImGui::GetIO();\n      int type = MT_NONE;\n\n      // screen\n      if (io.MousePos.x >= gContext.mScreenSquareMin.x && io.MousePos.x <= gContext.mScreenSquareMax.x &&\n         io.MousePos.y >= gContext.mScreenSquareMin.y && io.MousePos.y <= gContext.mScreenSquareMax.y &&\n         Contains(op, TRANSLATE))\n      {\n         type = MT_MOVE_SCREEN;\n      }\n\n      const vec_t screenCoord = makeVect(io.MousePos - ImVec2(gContext.mX, gContext.mY));\n\n      // compute\n      for (int i = 0; i < 3 && type == MT_NONE; i++)\n      {\n         vec_t dirPlaneX, dirPlaneY, dirAxis;\n         bool belowAxisLimit, belowPlaneLimit;\n         ComputeTripodAxisAndVisibility(i, dirAxis, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);\n         dirAxis.TransformVector(gContext.mModel);\n         dirPlaneX.TransformVector(gContext.mModel);\n         dirPlaneY.TransformVector(gContext.mModel);\n\n         const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, BuildPlan(gContext.mModel.v.position, dirAxis));\n         vec_t posOnPlan = gContext.mRayOrigin + gContext.mRayVector * len;\n\n         const ImVec2 axisStartOnScreen = worldToPos(gContext.mModel.v.position + dirAxis * gContext.mScreenFactor * 0.1f, gContext.mViewProjection) - ImVec2(gContext.mX, gContext.mY);\n         const ImVec2 axisEndOnScreen = worldToPos(gContext.mModel.v.position + dirAxis * gContext.mScreenFactor, gContext.mViewProjection) - ImVec2(gContext.mX, gContext.mY);\n\n         vec_t closestPointOnAxis = PointOnSegment(screenCoord, makeVect(axisStartOnScreen), makeVect(axisEndOnScreen));\n         if ((closestPointOnAxis - screenCoord).Length() < 12.f && Intersects(op, static_cast<OPERATION>(TRANSLATE_X << i))) // pixel size\n         {\n            type = MT_MOVE_X + i;\n         }\n\n         const float dx = dirPlaneX.Dot3((posOnPlan - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor));\n         const float dy = dirPlaneY.Dot3((posOnPlan - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor));\n         if (belowPlaneLimit && dx >= quadUV[0] && dx <= quadUV[4] && dy >= quadUV[1] && dy <= quadUV[3] && Contains(op, TRANSLATE_PLANS[i]))\n         {\n            type = MT_MOVE_YZ + i;\n         }\n\n         if (gizmoHitProportion)\n         {\n            *gizmoHitProportion = makeVect(dx, dy, 0.f);\n         }\n      }\n      return type;\n   }\n\n   static bool HandleTranslation(float* matrix, float* deltaMatrix, OPERATION op, int& type, const float* snap)\n   {\n      if(!Intersects(op, TRANSLATE) || type != MT_NONE)\n      {\n        return false;\n      }\n      const ImGuiIO& io = ImGui::GetIO();\n      const bool applyRotationLocaly = gContext.mMode == LOCAL || type == MT_MOVE_SCREEN;\n      bool modified = false;\n\n      // move\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsTranslateType(gContext.mCurrentOperation))\n      {\n#if IMGUI_VERSION_NUM >= 18723\n         ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n         ImGui::CaptureMouseFromApp();\n#endif\n         const float signedLength = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);\n         const float len = fabsf(signedLength); // near plan\n         const vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;\n\n         // compute delta\n         const vec_t newOrigin = newPos - gContext.mRelativeOrigin * gContext.mScreenFactor;\n         vec_t delta = newOrigin - gContext.mModel.v.position;\n\n         // 1 axis constraint\n         if (gContext.mCurrentOperation >= MT_MOVE_X && gContext.mCurrentOperation <= MT_MOVE_Z)\n         {\n            const int axisIndex = gContext.mCurrentOperation - MT_MOVE_X;\n            const vec_t& axisValue = *(vec_t*)&gContext.mModel.m[axisIndex];\n            const float lengthOnAxis = Dot(axisValue, delta);\n            delta = axisValue * lengthOnAxis;\n         }\n\n         // snap\n         if (snap)\n         {\n            vec_t cumulativeDelta = gContext.mModel.v.position + delta - gContext.mMatrixOrigin;\n            if (applyRotationLocaly)\n            {\n               matrix_t modelSourceNormalized = gContext.mModelSource;\n               modelSourceNormalized.OrthoNormalize();\n               matrix_t modelSourceNormalizedInverse;\n               modelSourceNormalizedInverse.Inverse(modelSourceNormalized);\n               cumulativeDelta.TransformVector(modelSourceNormalizedInverse);\n               ComputeSnap(cumulativeDelta, snap);\n               cumulativeDelta.TransformVector(modelSourceNormalized);\n            }\n            else\n            {\n               ComputeSnap(cumulativeDelta, snap);\n            }\n            delta = gContext.mMatrixOrigin + cumulativeDelta - gContext.mModel.v.position;\n\n         }\n\n         if (delta != gContext.mTranslationLastDelta)\n         {\n            modified = true;\n         }\n         gContext.mTranslationLastDelta = delta;\n\n         // compute matrix & delta\n         matrix_t deltaMatrixTranslation;\n         deltaMatrixTranslation.Translation(delta);\n         if (deltaMatrix)\n         {\n            memcpy(deltaMatrix, deltaMatrixTranslation.m16, sizeof(float) * 16);\n         }\n\n         const matrix_t res = gContext.mModelSource * deltaMatrixTranslation;\n         *(matrix_t*)matrix = res;\n\n         if (!io.MouseDown[0])\n         {\n            gContext.mbUsing = false;\n         }\n\n         type = gContext.mCurrentOperation;\n      }\n      else\n      {\n         // find new possible way to move\n         vec_t gizmoHitProportion;\n         type = GetMoveType(op, &gizmoHitProportion);\n         if (type != MT_NONE)\n         {\n#if IMGUI_VERSION_NUM >= 18723\n            ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n            ImGui::CaptureMouseFromApp();\n#endif\n         }\n         if (CanActivate() && type != MT_NONE)\n         {\n            gContext.mbUsing = true;\n            gContext.mEditingID = gContext.mActualID;\n            gContext.mCurrentOperation = type;\n            vec_t movePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir,\n               gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir,\n               -gContext.mCameraDir };\n\n            vec_t cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);\n            for (unsigned int i = 0; i < 3; i++)\n            {\n               vec_t orthoVector = Cross(movePlanNormal[i], cameraToModelNormalized);\n               movePlanNormal[i].Cross(orthoVector);\n               movePlanNormal[i].Normalize();\n            }\n            // pickup plan\n            gContext.mTranslationPlan = BuildPlan(gContext.mModel.v.position, movePlanNormal[type - MT_MOVE_X]);\n            const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);\n            gContext.mTranslationPlanOrigin = gContext.mRayOrigin + gContext.mRayVector * len;\n            gContext.mMatrixOrigin = gContext.mModel.v.position;\n\n            gContext.mRelativeOrigin = (gContext.mTranslationPlanOrigin - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor);\n         }\n      }\n      return modified;\n   }\n\n   static bool HandleScale(float* matrix, float* deltaMatrix, OPERATION op, int& type, const float* snap)\n   {\n      if((!Intersects(op, SCALE) && !Intersects(op, SCALEU)) || type != MT_NONE || !gContext.mbMouseOver)\n      {\n         return false;\n      }\n      ImGuiIO& io = ImGui::GetIO();\n      bool modified = false;\n\n      if (!gContext.mbUsing)\n      {\n         // find new possible way to scale\n         type = GetScaleType(op);\n         if (type != MT_NONE)\n         {\n#if IMGUI_VERSION_NUM >= 18723\n            ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n            ImGui::CaptureMouseFromApp();\n#endif\n         }\n         if (CanActivate() && type != MT_NONE)\n         {\n            gContext.mbUsing = true;\n            gContext.mEditingID = gContext.mActualID;\n            gContext.mCurrentOperation = type;\n            const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.up, gContext.mModel.v.right, -gContext.mCameraDir };\n            // pickup plan\n\n            gContext.mTranslationPlan = BuildPlan(gContext.mModel.v.position, movePlanNormal[type - MT_SCALE_X]);\n            const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);\n            gContext.mTranslationPlanOrigin = gContext.mRayOrigin + gContext.mRayVector * len;\n            gContext.mMatrixOrigin = gContext.mModel.v.position;\n            gContext.mScale.Set(1.f, 1.f, 1.f);\n            gContext.mRelativeOrigin = (gContext.mTranslationPlanOrigin - gContext.mModel.v.position) * (1.f / gContext.mScreenFactor);\n            gContext.mScaleValueOrigin = makeVect(gContext.mModelSource.v.right.Length(), gContext.mModelSource.v.up.Length(), gContext.mModelSource.v.dir.Length());\n            gContext.mSaveMousePosx = io.MousePos.x;\n         }\n      }\n      // scale\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsScaleType(gContext.mCurrentOperation))\n      {\n#if IMGUI_VERSION_NUM >= 18723\n         ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n         ImGui::CaptureMouseFromApp();\n#endif\n         const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);\n         vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;\n         vec_t newOrigin = newPos - gContext.mRelativeOrigin * gContext.mScreenFactor;\n         vec_t delta = newOrigin - gContext.mModelLocal.v.position;\n\n         // 1 axis constraint\n         if (gContext.mCurrentOperation >= MT_SCALE_X && gContext.mCurrentOperation <= MT_SCALE_Z)\n         {\n            int axisIndex = gContext.mCurrentOperation - MT_SCALE_X;\n            const vec_t& axisValue = *(vec_t*)&gContext.mModelLocal.m[axisIndex];\n            float lengthOnAxis = Dot(axisValue, delta);\n            delta = axisValue * lengthOnAxis;\n\n            vec_t baseVector = gContext.mTranslationPlanOrigin - gContext.mModelLocal.v.position;\n            float ratio = Dot(axisValue, baseVector + delta) / Dot(axisValue, baseVector);\n\n            gContext.mScale[axisIndex] = max(ratio, 0.001f);\n         }\n         else\n         {\n            float scaleDelta = (io.MousePos.x - gContext.mSaveMousePosx) * 0.01f;\n            gContext.mScale.Set(max(1.f + scaleDelta, 0.001f));\n         }\n\n         // snap\n         if (snap)\n         {\n            float scaleSnap[] = { snap[0], snap[0], snap[0] };\n            ComputeSnap(gContext.mScale, scaleSnap);\n         }\n\n         // no 0 allowed\n         for (int i = 0; i < 3; i++)\n            gContext.mScale[i] = max(gContext.mScale[i], 0.001f);\n\n         if (gContext.mScaleLast != gContext.mScale)\n         {\n            modified = true;\n         }\n         gContext.mScaleLast = gContext.mScale;\n\n         // compute matrix & delta\n         matrix_t deltaMatrixScale;\n         deltaMatrixScale.Scale(gContext.mScale * gContext.mScaleValueOrigin);\n\n         matrix_t res = deltaMatrixScale * gContext.mModelLocal;\n         *(matrix_t*)matrix = res;\n\n         if (deltaMatrix)\n         {\n            vec_t deltaScale = gContext.mScale * gContext.mScaleValueOrigin;\n\n            vec_t originalScaleDivider;\n            originalScaleDivider.x = 1 / gContext.mModelScaleOrigin.x;\n            originalScaleDivider.y = 1 / gContext.mModelScaleOrigin.y;\n            originalScaleDivider.z = 1 / gContext.mModelScaleOrigin.z;\n\n            deltaScale = deltaScale * originalScaleDivider;\n\n            deltaMatrixScale.Scale(deltaScale);\n            memcpy(deltaMatrix, deltaMatrixScale.m16, sizeof(float) * 16);\n         }\n\n         if (!io.MouseDown[0])\n         {\n            gContext.mbUsing = false;\n            gContext.mScale.Set(1.f, 1.f, 1.f);\n         }\n\n         type = gContext.mCurrentOperation;\n      }\n      return modified;\n   }\n\n   static bool HandleRotation(float* matrix, float* deltaMatrix, OPERATION op, int& type, const float* snap)\n   {\n      if(!Intersects(op, ROTATE) || type != MT_NONE || !gContext.mbMouseOver)\n      {\n        return false;\n      }\n      ImGuiIO& io = ImGui::GetIO();\n      bool applyRotationLocaly = gContext.mMode == LOCAL;\n      bool modified = false;\n\n      if (!gContext.mbUsing)\n      {\n         type = GetRotateType(op);\n\n         if (type != MT_NONE)\n         {\n#if IMGUI_VERSION_NUM >= 18723\n            ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n            ImGui::CaptureMouseFromApp();\n#endif\n         }\n\n         if (type == MT_ROTATE_SCREEN)\n         {\n            applyRotationLocaly = true;\n         }\n\n         if (CanActivate() && type != MT_NONE)\n         {\n            gContext.mbUsing = true;\n            gContext.mEditingID = gContext.mActualID;\n            gContext.mCurrentOperation = type;\n            const vec_t rotatePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir, -gContext.mCameraDir };\n            // pickup plan\n            if (applyRotationLocaly)\n            {\n               gContext.mTranslationPlan = BuildPlan(gContext.mModel.v.position, rotatePlanNormal[type - MT_ROTATE_X]);\n            }\n            else\n            {\n               gContext.mTranslationPlan = BuildPlan(gContext.mModelSource.v.position, directionUnary[type - MT_ROTATE_X]);\n            }\n\n            const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);\n            vec_t localPos = gContext.mRayOrigin + gContext.mRayVector * len - gContext.mModel.v.position;\n            gContext.mRotationVectorSource = Normalized(localPos);\n            gContext.mRotationAngleOrigin = ComputeAngleOnPlan();\n         }\n      }\n\n      // rotation\n      if (gContext.mbUsing && (gContext.mActualID == -1 || gContext.mActualID == gContext.mEditingID) && IsRotateType(gContext.mCurrentOperation))\n      {\n#if IMGUI_VERSION_NUM >= 18723\n         ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n         ImGui::CaptureMouseFromApp();\n#endif\n         gContext.mRotationAngle = ComputeAngleOnPlan();\n         if (snap)\n         {\n            float snapInRadian = snap[0] * DEG2RAD;\n            ComputeSnap(&gContext.mRotationAngle, snapInRadian);\n         }\n         vec_t rotationAxisLocalSpace;\n\n         rotationAxisLocalSpace.TransformVector(makeVect(gContext.mTranslationPlan.x, gContext.mTranslationPlan.y, gContext.mTranslationPlan.z, 0.f), gContext.mModelInverse);\n         rotationAxisLocalSpace.Normalize();\n\n         matrix_t deltaRotation;\n         deltaRotation.RotationAxis(rotationAxisLocalSpace, gContext.mRotationAngle - gContext.mRotationAngleOrigin);\n         if (gContext.mRotationAngle != gContext.mRotationAngleOrigin)\n         {\n            modified = true;\n         }\n         gContext.mRotationAngleOrigin = gContext.mRotationAngle;\n\n         matrix_t scaleOrigin;\n         scaleOrigin.Scale(gContext.mModelScaleOrigin);\n\n         if (applyRotationLocaly)\n         {\n            *(matrix_t*)matrix = scaleOrigin * deltaRotation * gContext.mModelLocal;\n         }\n         else\n         {\n            matrix_t res = gContext.mModelSource;\n            res.v.position.Set(0.f);\n\n            *(matrix_t*)matrix = res * deltaRotation;\n            ((matrix_t*)matrix)->v.position = gContext.mModelSource.v.position;\n         }\n\n         if (deltaMatrix)\n         {\n            *(matrix_t*)deltaMatrix = gContext.mModelInverse * deltaRotation * gContext.mModel;\n         }\n\n         if (!io.MouseDown[0])\n         {\n            gContext.mbUsing = false;\n            gContext.mEditingID = -1;\n         }\n         type = gContext.mCurrentOperation;\n      }\n      return modified;\n   }\n\n   void DecomposeMatrixToComponents(const float* matrix, float* translation, float* rotation, float* scale)\n   {\n      matrix_t mat = *(matrix_t*)matrix;\n\n      scale[0] = mat.v.right.Length();\n      scale[1] = mat.v.up.Length();\n      scale[2] = mat.v.dir.Length();\n\n      mat.OrthoNormalize();\n\n      rotation[0] = RAD2DEG * atan2f(mat.m[1][2], mat.m[2][2]);\n      rotation[1] = RAD2DEG * atan2f(-mat.m[0][2], sqrtf(mat.m[1][2] * mat.m[1][2] + mat.m[2][2] * mat.m[2][2]));\n      rotation[2] = RAD2DEG * atan2f(mat.m[0][1], mat.m[0][0]);\n\n      translation[0] = mat.v.position.x;\n      translation[1] = mat.v.position.y;\n      translation[2] = mat.v.position.z;\n   }\n\n   void RecomposeMatrixFromComponents(const float* translation, const float* rotation, const float* scale, float* matrix)\n   {\n      matrix_t& mat = *(matrix_t*)matrix;\n\n      matrix_t rot[3];\n      for (int i = 0; i < 3; i++)\n      {\n         rot[i].RotationAxis(directionUnary[i], rotation[i] * DEG2RAD);\n      }\n\n      mat = rot[0] * rot[1] * rot[2];\n\n      float validScale[3];\n      for (int i = 0; i < 3; i++)\n      {\n         if (fabsf(scale[i]) < FLT_EPSILON)\n         {\n            validScale[i] = 0.001f;\n         }\n         else\n         {\n            validScale[i] = scale[i];\n         }\n      }\n      mat.v.right *= validScale[0];\n      mat.v.up *= validScale[1];\n      mat.v.dir *= validScale[2];\n      mat.v.position.Set(translation[0], translation[1], translation[2], 1.f);\n   }\n\n   void SetID(int id)\n   {\n      gContext.mActualID = id;\n   }\n\n   void AllowAxisFlip(bool value)\n   {\n     gContext.mAllowAxisFlip = value;\n   }\n\n   bool Manipulate(const float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float* deltaMatrix, const float* snap, const float* localBounds, const float* boundsSnap)\n   {\n      // Scale is always local or matrix will be skewed when applying world scale or oriented matrix\n      ComputeContext(view, projection, matrix, (operation & SCALE) ? LOCAL : mode);\n\n      // set delta to identity\n      if (deltaMatrix)\n      {\n         ((matrix_t*)deltaMatrix)->SetToIdentity();\n      }\n\n      // behind camera\n      vec_t camSpacePosition;\n      camSpacePosition.TransformPoint(makeVect(0.f, 0.f, 0.f), gContext.mMVP);\n      if (!gContext.mIsOrthographic && camSpacePosition.z < 0.001f)\n      {\n         return false;\n      }\n\n      // --\n      int type = MT_NONE;\n      bool manipulated = false;\n      if (gContext.mbEnable)\n      {\n         if (!gContext.mbUsingBounds)\n         {\n            manipulated = HandleTranslation(matrix, deltaMatrix, operation, type, snap) ||\n                          HandleScale(matrix, deltaMatrix, operation, type, snap) ||\n                          HandleRotation(matrix, deltaMatrix, operation, type, snap);\n         }\n      }\n\n      if (localBounds && !gContext.mbUsing)\n      {\n         HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap, operation);\n      }\n\n      gContext.mOperation = operation;\n      if (!gContext.mbUsingBounds)\n      {\n         DrawRotationGizmo(operation, type);\n         DrawTranslationGizmo(operation, type);\n         DrawScaleGizmo(operation, type);\n         DrawScaleUniveralGizmo(operation, type);\n      }\n      return manipulated;\n   }\n\n   void SetGizmoSizeClipSpace(float value)\n   {\n      gContext.mGizmoSizeClipSpace = value;\n   }\n\n   ///////////////////////////////////////////////////////////////////////////////////////////////////\n   void ComputeFrustumPlanes(vec_t* frustum, const float* clip)\n   {\n      frustum[0].x = clip[3] - clip[0];\n      frustum[0].y = clip[7] - clip[4];\n      frustum[0].z = clip[11] - clip[8];\n      frustum[0].w = clip[15] - clip[12];\n\n      frustum[1].x = clip[3] + clip[0];\n      frustum[1].y = clip[7] + clip[4];\n      frustum[1].z = clip[11] + clip[8];\n      frustum[1].w = clip[15] + clip[12];\n\n      frustum[2].x = clip[3] + clip[1];\n      frustum[2].y = clip[7] + clip[5];\n      frustum[2].z = clip[11] + clip[9];\n      frustum[2].w = clip[15] + clip[13];\n\n      frustum[3].x = clip[3] - clip[1];\n      frustum[3].y = clip[7] - clip[5];\n      frustum[3].z = clip[11] - clip[9];\n      frustum[3].w = clip[15] - clip[13];\n\n      frustum[4].x = clip[3] - clip[2];\n      frustum[4].y = clip[7] - clip[6];\n      frustum[4].z = clip[11] - clip[10];\n      frustum[4].w = clip[15] - clip[14];\n\n      frustum[5].x = clip[3] + clip[2];\n      frustum[5].y = clip[7] + clip[6];\n      frustum[5].z = clip[11] + clip[10];\n      frustum[5].w = clip[15] + clip[14];\n\n      for (int i = 0; i < 6; i++)\n      {\n         frustum[i].Normalize();\n      }\n   }\n\n   void DrawCubes(const float* view, const float* projection, const float* matrices, int matrixCount)\n   {\n      matrix_t viewInverse;\n      viewInverse.Inverse(*(matrix_t*)view);\n\n      struct CubeFace\n      {\n         float z;\n         ImVec2 faceCoordsScreen[4];\n         ImU32 color;\n      };\n      CubeFace* faces = (CubeFace*)_malloca(sizeof(CubeFace) * matrixCount * 6);\n\n      if (!faces)\n      {\n         return;\n      }\n\n      vec_t frustum[6];\n      matrix_t viewProjection = *(matrix_t*)view * *(matrix_t*)projection;\n      ComputeFrustumPlanes(frustum, viewProjection.m16);\n\n      int cubeFaceCount = 0;\n      for (int cube = 0; cube < matrixCount; cube++)\n      {\n         const float* matrix = &matrices[cube * 16];\n\n         matrix_t res = *(matrix_t*)matrix * *(matrix_t*)view * *(matrix_t*)projection;\n\n         for (int iFace = 0; iFace < 6; iFace++)\n         {\n            const int normalIndex = (iFace % 3);\n            const int perpXIndex = (normalIndex + 1) % 3;\n            const int perpYIndex = (normalIndex + 2) % 3;\n            const float invert = (iFace > 2) ? -1.f : 1.f;\n\n            const vec_t faceCoords[4] = { directionUnary[normalIndex] + directionUnary[perpXIndex] + directionUnary[perpYIndex],\n               directionUnary[normalIndex] + directionUnary[perpXIndex] - directionUnary[perpYIndex],\n               directionUnary[normalIndex] - directionUnary[perpXIndex] - directionUnary[perpYIndex],\n               directionUnary[normalIndex] - directionUnary[perpXIndex] + directionUnary[perpYIndex],\n            };\n\n            // clipping\n            /*\n            bool skipFace = false;\n            for (unsigned int iCoord = 0; iCoord < 4; iCoord++)\n            {\n               vec_t camSpacePosition;\n               camSpacePosition.TransformPoint(faceCoords[iCoord] * 0.5f * invert, res);\n               if (camSpacePosition.z < 0.001f)\n               {\n                  skipFace = true;\n                  break;\n               }\n            }\n            if (skipFace)\n            {\n               continue;\n            }\n            */\n            vec_t centerPosition, centerPositionVP;\n            centerPosition.TransformPoint(directionUnary[normalIndex] * 0.5f * invert, *(matrix_t*)matrix);\n            centerPositionVP.TransformPoint(directionUnary[normalIndex] * 0.5f * invert, res);\n\n            bool inFrustum = true;\n            for (int iFrustum = 0; iFrustum < 6; iFrustum++)\n            {\n               float dist = DistanceToPlane(centerPosition, frustum[iFrustum]);\n               if (dist < 0.f)\n               {\n                  inFrustum = false;\n                  break;\n               }\n            }\n\n            if (!inFrustum)\n            {\n               continue;\n            }\n            CubeFace& cubeFace = faces[cubeFaceCount];\n\n            // 3D->2D\n            //ImVec2 faceCoordsScreen[4];\n            for (unsigned int iCoord = 0; iCoord < 4; iCoord++)\n            {\n               cubeFace.faceCoordsScreen[iCoord] = worldToPos(faceCoords[iCoord] * 0.5f * invert, res);\n            }\n\n            ImU32 directionColor = GetColorU32(DIRECTION_X + normalIndex);\n            cubeFace.color = directionColor | IM_COL32(0x80, 0x80, 0x80, 0);\n\n            cubeFace.z = centerPositionVP.z / centerPositionVP.w;\n            cubeFaceCount++;\n         }\n      }\n      qsort(faces, cubeFaceCount, sizeof(CubeFace), [](void const* _a, void const* _b) {\n         CubeFace* a = (CubeFace*)_a;\n         CubeFace* b = (CubeFace*)_b;\n         if (a->z < b->z)\n         {\n            return 1;\n         }\n         return -1;\n         });\n      // draw face with lighter color\n      for (int iFace = 0; iFace < cubeFaceCount; iFace++)\n      {\n         const CubeFace& cubeFace = faces[iFace];\n         gContext.mDrawList->AddConvexPolyFilled(cubeFace.faceCoordsScreen, 4, cubeFace.color);\n      }\n\n      _freea(faces);\n   }\n\n   void DrawGrid(const float* view, const float* projection, const float* matrix, const float gridSize)\n   {\n      matrix_t viewProjection = *(matrix_t*)view * *(matrix_t*)projection;\n      vec_t frustum[6];\n      ComputeFrustumPlanes(frustum, viewProjection.m16);\n      matrix_t res = *(matrix_t*)matrix * viewProjection;\n\n      for (float f = -gridSize; f <= gridSize; f += 1.f)\n      {\n         for (int dir = 0; dir < 2; dir++)\n         {\n            vec_t ptA = makeVect(dir ? -gridSize : f, 0.f, dir ? f : -gridSize);\n            vec_t ptB = makeVect(dir ? gridSize : f, 0.f, dir ? f : gridSize);\n            bool visible = true;\n            for (int i = 0; i < 6; i++)\n            {\n               float dA = DistanceToPlane(ptA, frustum[i]);\n               float dB = DistanceToPlane(ptB, frustum[i]);\n               if (dA < 0.f && dB < 0.f)\n               {\n                  visible = false;\n                  break;\n               }\n               if (dA > 0.f && dB > 0.f)\n               {\n                  continue;\n               }\n               if (dA < 0.f)\n               {\n                  float len = fabsf(dA - dB);\n                  float t = fabsf(dA) / len;\n                  ptA.Lerp(ptB, t);\n               }\n               if (dB < 0.f)\n               {\n                  float len = fabsf(dB - dA);\n                  float t = fabsf(dB) / len;\n                  ptB.Lerp(ptA, t);\n               }\n            }\n            if (visible)\n            {\n               ImU32 col = IM_COL32(0x80, 0x80, 0x80, 0xFF);\n               col = (fmodf(fabsf(f), 10.f) < FLT_EPSILON) ? IM_COL32(0x90, 0x90, 0x90, 0xFF) : col;\n               col = (fabsf(f) < FLT_EPSILON) ? IM_COL32(0x40, 0x40, 0x40, 0xFF): col;\n\n               float thickness = 1.f;\n               thickness = (fmodf(fabsf(f), 10.f) < FLT_EPSILON) ? 1.5f : thickness;\n               thickness = (fabsf(f) < FLT_EPSILON) ? 2.3f : thickness;\n\n               gContext.mDrawList->AddLine(worldToPos(ptA, res), worldToPos(ptB, res), col, thickness);\n            }\n         }\n      }\n   }\n\n   void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor)\n   {\n      // Scale is always local or matrix will be skewed when applying world scale or oriented matrix\n      ComputeContext(view, projection, matrix, (operation & SCALE) ? LOCAL : mode);\n      ViewManipulate(view, length, position, size, backgroundColor);\n   }\n\n   void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor)\n   {\n      static bool isDraging = false;\n      static bool isClicking = false;\n      static bool isInside = false;\n      static vec_t interpolationUp;\n      static vec_t interpolationDir;\n      static int interpolationFrames = 0;\n      const vec_t referenceUp = makeVect(0.f, 1.f, 0.f);\n\n      matrix_t svgView, svgProjection;\n      svgView = gContext.mViewMat;\n      svgProjection = gContext.mProjectionMat;\n\n      ImGuiIO& io = ImGui::GetIO();\n      gContext.mDrawList->AddRectFilled(position, position + size, backgroundColor);\n      matrix_t viewInverse;\n      viewInverse.Inverse(*(matrix_t*)view);\n\n      const vec_t camTarget = viewInverse.v.position - viewInverse.v.dir * length;\n\n      // view/projection matrices\n      const float distance = 3.f;\n      matrix_t cubeProjection, cubeView;\n      float fov = acosf(distance / (sqrtf(distance * distance + 3.f))) * RAD2DEG;\n      Perspective(fov / sqrtf(2.f), size.x / size.y, 0.01f, 1000.f, cubeProjection.m16);\n\n      vec_t dir = makeVect(viewInverse.m[2][0], viewInverse.m[2][1], viewInverse.m[2][2]);\n      vec_t up = makeVect(viewInverse.m[1][0], viewInverse.m[1][1], viewInverse.m[1][2]);\n      vec_t eye = dir * distance;\n      vec_t zero = makeVect(0.f, 0.f);\n      LookAt(&eye.x, &zero.x, &up.x, cubeView.m16);\n\n      // set context\n      gContext.mViewMat = cubeView;\n      gContext.mProjectionMat = cubeProjection;\n      ComputeCameraRay(gContext.mRayOrigin, gContext.mRayVector, position, size);\n\n      const matrix_t res = cubeView * cubeProjection;\n\n      // panels\n      static const ImVec2 panelPosition[9] = { ImVec2(0.75f,0.75f), ImVec2(0.25f, 0.75f), ImVec2(0.f, 0.75f),\n         ImVec2(0.75f, 0.25f), ImVec2(0.25f, 0.25f), ImVec2(0.f, 0.25f),\n         ImVec2(0.75f, 0.f), ImVec2(0.25f, 0.f), ImVec2(0.f, 0.f) };\n\n      static const ImVec2 panelSize[9] = { ImVec2(0.25f,0.25f), ImVec2(0.5f, 0.25f), ImVec2(0.25f, 0.25f),\n         ImVec2(0.25f, 0.5f), ImVec2(0.5f, 0.5f), ImVec2(0.25f, 0.5f),\n         ImVec2(0.25f, 0.25f), ImVec2(0.5f, 0.25f), ImVec2(0.25f, 0.25f) };\n\n      // tag faces\n      bool boxes[27]{};\n      static int overBox = -1;\n      for (int iPass = 0; iPass < 2; iPass++)\n      {\n         for (int iFace = 0; iFace < 6; iFace++)\n         {\n            const int normalIndex = (iFace % 3);\n            const int perpXIndex = (normalIndex + 1) % 3;\n            const int perpYIndex = (normalIndex + 2) % 3;\n            const float invert = (iFace > 2) ? -1.f : 1.f;\n            const vec_t indexVectorX = directionUnary[perpXIndex] * invert;\n            const vec_t indexVectorY = directionUnary[perpYIndex] * invert;\n            const vec_t boxOrigin = directionUnary[normalIndex] * -invert - indexVectorX - indexVectorY;\n\n            // plan local space\n            const vec_t n = directionUnary[normalIndex] * invert;\n            vec_t viewSpaceNormal = n;\n            vec_t viewSpacePoint = n * 0.5f;\n            viewSpaceNormal.TransformVector(cubeView);\n            viewSpaceNormal.Normalize();\n            viewSpacePoint.TransformPoint(cubeView);\n            const vec_t viewSpaceFacePlan = BuildPlan(viewSpacePoint, viewSpaceNormal);\n\n            // back face culling\n            if (viewSpaceFacePlan.w > 0.f)\n            {\n               continue;\n            }\n\n            const vec_t facePlan = BuildPlan(n * 0.5f, n);\n\n            const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, facePlan);\n            vec_t posOnPlan = gContext.mRayOrigin + gContext.mRayVector * len - (n * 0.5f);\n\n            float localx = Dot(directionUnary[perpXIndex], posOnPlan) * invert + 0.5f;\n            float localy = Dot(directionUnary[perpYIndex], posOnPlan) * invert + 0.5f;\n\n            // panels\n            const vec_t dx = directionUnary[perpXIndex];\n            const vec_t dy = directionUnary[perpYIndex];\n            const vec_t origin = directionUnary[normalIndex] - dx - dy;\n            for (int iPanel = 0; iPanel < 9; iPanel++)\n            {\n               vec_t boxCoord = boxOrigin + indexVectorX * float(iPanel % 3) + indexVectorY * float(iPanel / 3) + makeVect(1.f, 1.f, 1.f);\n               const ImVec2 p = panelPosition[iPanel] * 2.f;\n               const ImVec2 s = panelSize[iPanel] * 2.f;\n               ImVec2 faceCoordsScreen[4];\n               vec_t panelPos[4] = { dx * p.x + dy * p.y,\n                                     dx * p.x + dy * (p.y + s.y),\n                                     dx * (p.x + s.x) + dy * (p.y + s.y),\n                                     dx * (p.x + s.x) + dy * p.y };\n\n               for (unsigned int iCoord = 0; iCoord < 4; iCoord++)\n               {\n                  faceCoordsScreen[iCoord] = worldToPos((panelPos[iCoord] + origin) * 0.5f * invert, res, position, size);\n               }\n\n               const ImVec2 panelCorners[2] = { panelPosition[iPanel], panelPosition[iPanel] + panelSize[iPanel] };\n               bool insidePanel = localx > panelCorners[0].x && localx < panelCorners[1].x && localy > panelCorners[0].y && localy < panelCorners[1].y;\n               int boxCoordInt = int(boxCoord.x * 9.f + boxCoord.y * 3.f + boxCoord.z);\n               IM_ASSERT(boxCoordInt < 27);\n               boxes[boxCoordInt] |= insidePanel && (!isDraging) && gContext.mbMouseOver;\n\n               // draw face with lighter color\n               if (iPass)\n               {\n                  ImU32 directionColor = GetColorU32(DIRECTION_X + normalIndex);\n                  gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, (directionColor | IM_COL32(0x80, 0x80, 0x80, 0x80)) | (isInside ? IM_COL32(0x08, 0x08, 0x08, 0) : 0));\n                  if (boxes[boxCoordInt])\n                  {\n                     gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, IM_COL32(0xF0, 0xA0, 0x60, 0x80));\n\n                     if (io.MouseDown[0] && !isClicking && !isDraging) {\n                        overBox = boxCoordInt;\n                        isClicking = true;\n                        isDraging = true;\n                     }\n                  }\n               }\n            }\n         }\n      }\n      if (interpolationFrames)\n      {\n         interpolationFrames--;\n         vec_t newDir = viewInverse.v.dir;\n         newDir.Lerp(interpolationDir, 0.2f);\n         newDir.Normalize();\n\n         vec_t newUp = viewInverse.v.up;\n         newUp.Lerp(interpolationUp, 0.3f);\n         newUp.Normalize();\n         newUp = interpolationUp;\n         vec_t newEye = camTarget + newDir * length;\n         LookAt(&newEye.x, &camTarget.x, &newUp.x, view);\n      }\n      isInside = gContext.mbMouseOver && ImRect(position, position + size).Contains(io.MousePos);\n\n      if (io.MouseDown[0] && (fabsf(io.MouseDelta[0]) || fabsf(io.MouseDelta[1])) && isClicking)\n      {\n         isClicking = false;\n      }\n\n      if (!io.MouseDown[0])\n      {\n         if (isClicking)\n         {\n            // apply new view direction\n            int cx = overBox / 9;\n            int cy = (overBox - cx * 9) / 3;\n            int cz = overBox % 3;\n            interpolationDir = makeVect(1.f - (float)cx, 1.f - (float)cy, 1.f - (float)cz);\n            interpolationDir.Normalize();\n\n            if (fabsf(Dot(interpolationDir, referenceUp)) > 1.0f - 0.01f)\n            {\n               vec_t right = viewInverse.v.right;\n               if (fabsf(right.x) > fabsf(right.z))\n               {\n                  right.z = 0.f;\n               }\n               else\n               {\n                  right.x = 0.f;\n               }\n               right.Normalize();\n               interpolationUp = Cross(interpolationDir, right);\n               interpolationUp.Normalize();\n            }\n            else\n            {\n               interpolationUp = referenceUp;\n            }\n            interpolationFrames = 40;\n            \n         }\n         isClicking = false;\n         isDraging = false;\n      }\n\n\n      if (isDraging)\n      {\n         matrix_t rx, ry, roll;\n\n         rx.RotationAxis(referenceUp, -io.MouseDelta.x * 0.01f);\n         ry.RotationAxis(viewInverse.v.right, -io.MouseDelta.y * 0.01f);\n\n         roll = rx * ry;\n\n         vec_t newDir = viewInverse.v.dir;\n         newDir.TransformVector(roll);\n         newDir.Normalize();\n\n         // clamp\n         vec_t planDir = Cross(viewInverse.v.right, referenceUp);\n         planDir.y = 0.f;\n         planDir.Normalize();\n         float dt = Dot(planDir, newDir);\n         if (dt < 0.0f)\n         {\n            newDir += planDir * dt;\n            newDir.Normalize();\n         }\n\n         vec_t newEye = camTarget + newDir * length;\n         LookAt(&newEye.x, &camTarget.x, &referenceUp.x, view);\n      }\n\n      // restore view/projection because it was used to compute ray\n      ComputeContext(svgView.m16, svgProjection.m16, gContext.mModelSource.m16, gContext.mMode);\n   }\n};\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImGuizmo.h",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n// -------------------------------------------------------------------------------------------\n// History :\n// 2019/11/03 View gizmo\n// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode.\n// 2016/09/09 Hatched negative axis. Snapping. Documentation update.\n// 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved\n// 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results.\n// 2016/08/31 First version\n//\n// -------------------------------------------------------------------------------------------\n// Future (no order):\n//\n// - Multi view\n// - display rotation/translation/scale infos in local/world space and not only local\n// - finish local/world matrix application\n// - OPERATION as bitmask\n// \n// -------------------------------------------------------------------------------------------\n// Example \n#if 0\nvoid EditTransform(const Camera& camera, matrix_t& matrix)\n{\n   static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);\n   static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);\n   if (ImGui::IsKeyPressed(90))\n      mCurrentGizmoOperation = ImGuizmo::TRANSLATE;\n   if (ImGui::IsKeyPressed(69))\n      mCurrentGizmoOperation = ImGuizmo::ROTATE;\n   if (ImGui::IsKeyPressed(82)) // r Key\n      mCurrentGizmoOperation = ImGuizmo::SCALE;\n   if (ImGui::RadioButton(\"Translate\", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))\n      mCurrentGizmoOperation = ImGuizmo::TRANSLATE;\n   ImGui::SameLine();\n   if (ImGui::RadioButton(\"Rotate\", mCurrentGizmoOperation == ImGuizmo::ROTATE))\n      mCurrentGizmoOperation = ImGuizmo::ROTATE;\n   ImGui::SameLine();\n   if (ImGui::RadioButton(\"Scale\", mCurrentGizmoOperation == ImGuizmo::SCALE))\n      mCurrentGizmoOperation = ImGuizmo::SCALE;\n   float matrixTranslation[3], matrixRotation[3], matrixScale[3];\n   ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale);\n   ImGui::InputFloat3(\"Tr\", matrixTranslation, 3);\n   ImGui::InputFloat3(\"Rt\", matrixRotation, 3);\n   ImGui::InputFloat3(\"Sc\", matrixScale, 3);\n   ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);\n\n   if (mCurrentGizmoOperation != ImGuizmo::SCALE)\n   {\n      if (ImGui::RadioButton(\"Local\", mCurrentGizmoMode == ImGuizmo::LOCAL))\n         mCurrentGizmoMode = ImGuizmo::LOCAL;\n      ImGui::SameLine();\n      if (ImGui::RadioButton(\"World\", mCurrentGizmoMode == ImGuizmo::WORLD))\n         mCurrentGizmoMode = ImGuizmo::WORLD;\n   }\n   static bool useSnap(false);\n   if (ImGui::IsKeyPressed(83))\n      useSnap = !useSnap;\n   ImGui::Checkbox(\"\", &useSnap);\n   ImGui::SameLine();\n   vec_t snap;\n   switch (mCurrentGizmoOperation)\n   {\n   case ImGuizmo::TRANSLATE:\n      snap = config.mSnapTranslation;\n      ImGui::InputFloat3(\"Snap\", &snap.x);\n      break;\n   case ImGuizmo::ROTATE:\n      snap = config.mSnapRotation;\n      ImGui::InputFloat(\"Angle Snap\", &snap.x);\n      break;\n   case ImGuizmo::SCALE:\n      snap = config.mSnapScale;\n      ImGui::InputFloat(\"Scale Snap\", &snap.x);\n      break;\n   }\n   ImGuiIO& io = ImGui::GetIO();\n   ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);\n   ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);\n}\n#endif\n#pragma once\n\n#ifdef USE_IMGUI_API\n#include \"imconfig.h\"\n#endif\n#ifndef IMGUI_API\n#define IMGUI_API\n#endif\n\n#ifndef IMGUIZMO_NAMESPACE\n#define IMGUIZMO_NAMESPACE ImGuizmo\n#endif\n\nnamespace IMGUIZMO_NAMESPACE\n{\n   // call inside your own window and before Manipulate() in order to draw gizmo to that window.\n   // Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()).\n   IMGUI_API void SetDrawlist(ImDrawList* drawlist = nullptr);\n\n   // call BeginFrame right after ImGui_XXXX_NewFrame();\n   IMGUI_API void BeginFrame();\n\n   // this is necessary because when imguizmo is compiled into a dll, and imgui into another\n   // globals are not shared between them.\n   // More details at https://stackoverflow.com/questions/19373061/what-happens-to-global-and-static-variables-in-a-shared-library-when-it-is-dynam\n   // expose method to set imgui context\n   IMGUI_API void SetImGuiContext(ImGuiContext* ctx);\n\n   // return true if mouse cursor is over any gizmo control (axis, plan or screen component)\n   IMGUI_API bool IsOver();\n\n   // return true if mouse IsOver or if the gizmo is in moving state\n   IMGUI_API bool IsUsing();\n\n   // enable/disable the gizmo. Stay in the state until next call to Enable.\n   // gizmo is rendered with gray half transparent color when disabled\n   IMGUI_API void Enable(bool enable);\n\n   // helper functions for manualy editing translation/rotation/scale with an input float\n   // translation, rotation and scale float points to 3 floats each\n   // Angles are in degrees (more suitable for human editing)\n   // example:\n   // float matrixTranslation[3], matrixRotation[3], matrixScale[3];\n   // ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);\n   // ImGui::InputFloat3(\"Tr\", matrixTranslation, 3);\n   // ImGui::InputFloat3(\"Rt\", matrixRotation, 3);\n   // ImGui::InputFloat3(\"Sc\", matrixScale, 3);\n   // ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);\n   //\n   // These functions have some numerical stability issues for now. Use with caution.\n   IMGUI_API void DecomposeMatrixToComponents(const float* matrix, float* translation, float* rotation, float* scale);\n   IMGUI_API void RecomposeMatrixFromComponents(const float* translation, const float* rotation, const float* scale, float* matrix);\n\n   IMGUI_API void SetRect(float x, float y, float width, float height);\n   // default is false\n   IMGUI_API void SetOrthographic(bool isOrthographic);\n\n   // Render a cube with face color corresponding to face normal. Usefull for debug/tests\n   IMGUI_API void DrawCubes(const float* view, const float* projection, const float* matrices, int matrixCount);\n   IMGUI_API void DrawGrid(const float* view, const float* projection, const float* matrix, const float gridSize);\n\n   // call it when you want a gizmo\n   // Needs view and projection matrices. \n   // matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional\n   // translation is applied in world space\n   enum OPERATION\n   {\n      TRANSLATE_X      = (1u << 0),\n      TRANSLATE_Y      = (1u << 1),\n      TRANSLATE_Z      = (1u << 2),\n      ROTATE_X         = (1u << 3),\n      ROTATE_Y         = (1u << 4),\n      ROTATE_Z         = (1u << 5),\n      ROTATE_SCREEN    = (1u << 6),\n      SCALE_X          = (1u << 7),\n      SCALE_Y          = (1u << 8),\n      SCALE_Z          = (1u << 9),\n      BOUNDS           = (1u << 10),\n      SCALE_XU         = (1u << 11),\n      SCALE_YU         = (1u << 12),\n      SCALE_ZU         = (1u << 13),\n\n      TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z,\n      ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN,\n      SCALE = SCALE_X | SCALE_Y | SCALE_Z,\n      SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal\n      UNIVERSAL = TRANSLATE | ROTATE | SCALEU\n   };\n\n   inline OPERATION operator|(OPERATION lhs, OPERATION rhs)\n   {\n     return static_cast<OPERATION>(static_cast<int>(lhs) | static_cast<int>(rhs));\n   }\n\n   enum MODE\n   {\n      LOCAL,\n      WORLD\n   };\n\n   IMGUI_API bool Manipulate(const float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float* deltaMatrix = NULL, const float* snap = NULL, const float* localBounds = NULL, const float* boundsSnap = NULL);\n   //\n   // Please note that this cubeview is patented by Autodesk : https://patents.google.com/patent/US7782319B2/en\n   // It seems to be a defensive patent in the US. I don't think it will bring troubles using it as\n   // other software are using the same mechanics. But just in case, you are now warned!\n   //\n   IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);\n\n   // use this version if you did not call Manipulate before and you are just using ViewManipulate\n   IMGUI_API void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);\n\n   IMGUI_API void SetID(int id);\n\n   // return true if the cursor is over the operation's gizmo\n   IMGUI_API bool IsOver(OPERATION op);\n   IMGUI_API void SetGizmoSizeClipSpace(float value);\n\n   // Allow axis to flip\n   // When true (default), the guizmo axis flip for better visibility\n   // When false, they always stay along the positive world/local axis\n   IMGUI_API void AllowAxisFlip(bool value);\n\n   enum COLOR\n   {\n      DIRECTION_X,      // directionColor[0]\n      DIRECTION_Y,      // directionColor[1]\n      DIRECTION_Z,      // directionColor[2]\n      PLANE_X,          // planeColor[0]\n      PLANE_Y,          // planeColor[1]\n      PLANE_Z,          // planeColor[2]\n      SELECTION,        // selectionColor\n      INACTIVE,         // inactiveColor\n      TRANSLATION_LINE, // translationLineColor\n      SCALE_LINE,\n      ROTATION_USING_BORDER,\n      ROTATION_USING_FILL,\n      HATCHED_AXIS_LINES,\n      TEXT,\n      TEXT_SHADOW,\n      COUNT\n   };\n\n   struct Style\n   {\n      IMGUI_API Style();\n\n      float TranslationLineThickness;   // Thickness of lines for translation gizmo\n      float TranslationLineArrowSize;   // Size of arrow at the end of lines for translation gizmo\n      float RotationLineThickness;      // Thickness of lines for rotation gizmo\n      float RotationOuterLineThickness; // Thickness of line surrounding the rotation gizmo\n      float ScaleLineThickness;         // Thickness of lines for scale gizmo\n      float ScaleLineCircleSize;        // Size of circle at the end of lines for scale gizmo\n      float HatchedAxisLineThickness;   // Thickness of hatched axis lines\n      float CenterCircleSize;           // Size of circle at the center of the translate/scale gizmo\n\n      ImVec4 Colors[COLOR::COUNT];\n   };\n\n   IMGUI_API Style& GetStyle();\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImSequencer.cpp",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#include \"ImSequencer.h\"\n#include \"imgui.h\"\n#include \"imgui_internal.h\"\n#include <cstdlib>\n\nnamespace ImSequencer\n{\n#ifndef IMGUI_DEFINE_MATH_OPERATORS\n   static ImVec2 operator+(const ImVec2& a, const ImVec2& b) {\n      return ImVec2(a.x + b.x, a.y + b.y);\n   }\n#endif\n   static bool SequencerAddDelButton(ImDrawList* draw_list, ImVec2 pos, bool add = true)\n   {\n      ImGuiIO& io = ImGui::GetIO();\n      ImRect btnRect(pos, ImVec2(pos.x + 16, pos.y + 16));\n      bool overBtn = btnRect.Contains(io.MousePos);\n      bool containedClick = overBtn && btnRect.Contains(io.MouseClickedPos[0]);\n      bool clickedBtn = containedClick && io.MouseReleased[0];\n      int btnColor = overBtn ? 0xAAEAFFAA : 0x77A3B2AA;\n      if (containedClick && io.MouseDownDuration[0] > 0)\n         btnRect.Expand(2.0f);\n\n      float midy = pos.y + 16 / 2 - 0.5f;\n      float midx = pos.x + 16 / 2 - 0.5f;\n      draw_list->AddRect(btnRect.Min, btnRect.Max, btnColor, 4);\n      draw_list->AddLine(ImVec2(btnRect.Min.x + 3, midy), ImVec2(btnRect.Max.x - 3, midy), btnColor, 2);\n      if (add)\n         draw_list->AddLine(ImVec2(midx, btnRect.Min.y + 3), ImVec2(midx, btnRect.Max.y - 3), btnColor, 2);\n      return clickedBtn;\n   }\n\n   bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions)\n   {\n      bool ret = false;\n      ImGuiIO& io = ImGui::GetIO();\n      int cx = (int)(io.MousePos.x);\n      int cy = (int)(io.MousePos.y);\n      static float framePixelWidth = 10.f;\n      static float framePixelWidthTarget = 10.f;\n      int legendWidth = 200;\n\n      static int movingEntry = -1;\n      static int movingPos = -1;\n      static int movingPart = -1;\n      int delEntry = -1;\n      int dupEntry = -1;\n      int ItemHeight = 20;\n\n      bool popupOpened = false;\n      int sequenceCount = sequence->GetItemCount();\n      if (!sequenceCount)\n         return false;\n      ImGui::BeginGroup();\n\n      ImDrawList* draw_list = ImGui::GetWindowDrawList();\n      ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!\n      ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available\n      int firstFrameUsed = firstFrame ? *firstFrame : 0;\n\n\n      int controlHeight = sequenceCount * ItemHeight;\n      for (int i = 0; i < sequenceCount; i++)\n         controlHeight += int(sequence->GetCustomHeight(i));\n      int frameCount = ImMax(sequence->GetFrameMax() - sequence->GetFrameMin(), 1);\n\n      static bool MovingScrollBar = false;\n      static bool MovingCurrentFrame = false;\n      struct CustomDraw\n      {\n         int index;\n         ImRect customRect;\n         ImRect legendRect;\n         ImRect clippingRect;\n         ImRect legendClippingRect;\n      };\n      ImVector<CustomDraw> customDraws;\n      ImVector<CustomDraw> compactCustomDraws;\n      // zoom in/out\n      const int visibleFrameCount = (int)floorf((canvas_size.x - legendWidth) / framePixelWidth);\n      const float barWidthRatio = ImMin(visibleFrameCount / (float)frameCount, 1.f);\n      const float barWidthInPixels = barWidthRatio * (canvas_size.x - legendWidth);\n\n      ImRect regionRect(canvas_pos, canvas_pos + canvas_size);\n\n      static bool panningView = false;\n      static ImVec2 panningViewSource;\n      static int panningViewFrame;\n      if (ImGui::IsWindowFocused() && io.KeyAlt && io.MouseDown[2])\n      {\n         if (!panningView)\n         {\n            panningViewSource = io.MousePos;\n            panningView = true;\n            panningViewFrame = *firstFrame;\n         }\n         *firstFrame = panningViewFrame - int((io.MousePos.x - panningViewSource.x) / framePixelWidth);\n         *firstFrame = ImClamp(*firstFrame, sequence->GetFrameMin(), sequence->GetFrameMax() - visibleFrameCount);\n      }\n      if (panningView && !io.MouseDown[2])\n      {\n         panningView = false;\n      }\n      framePixelWidthTarget = ImClamp(framePixelWidthTarget, 0.1f, 50.f);\n\n      framePixelWidth = ImLerp(framePixelWidth, framePixelWidthTarget, 0.33f);\n\n      frameCount = sequence->GetFrameMax() - sequence->GetFrameMin();\n      if (visibleFrameCount >= frameCount && firstFrame)\n         *firstFrame = sequence->GetFrameMin();\n\n\n      // --\n      if (expanded && !*expanded)\n      {\n         ImGui::InvisibleButton(\"canvas\", ImVec2(canvas_size.x - canvas_pos.x, (float)ItemHeight));\n         draw_list->AddRectFilled(canvas_pos, ImVec2(canvas_size.x + canvas_pos.x, canvas_pos.y + ItemHeight), 0xFF3D3837, 0);\n         char tmps[512];\n         ImFormatString(tmps, IM_ARRAYSIZE(tmps), sequence->GetCollapseFmt(), frameCount, sequenceCount);\n         draw_list->AddText(ImVec2(canvas_pos.x + 26, canvas_pos.y + 2), 0xFFFFFFFF, tmps);\n      }\n      else\n      {\n         bool hasScrollBar(true);\n         /*\n         int framesPixelWidth = int(frameCount * framePixelWidth);\n         if ((framesPixelWidth + legendWidth) >= canvas_size.x)\n         {\n             hasScrollBar = true;\n         }\n         */\n         // test scroll area\n         ImVec2 headerSize(canvas_size.x, (float)ItemHeight);\n         ImVec2 scrollBarSize(canvas_size.x, 14.f);\n         ImGui::InvisibleButton(\"topBar\", headerSize);\n         draw_list->AddRectFilled(canvas_pos, canvas_pos + headerSize, 0xFFFF0000, 0);\n         ImVec2 childFramePos = ImGui::GetCursorScreenPos();\n         ImVec2 childFrameSize(canvas_size.x, canvas_size.y - 8.f - headerSize.y - (hasScrollBar ? scrollBarSize.y : 0));\n         ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);\n         ImGui::BeginChildFrame(889, childFrameSize);\n         sequence->focused = ImGui::IsWindowFocused();\n         ImGui::InvisibleButton(\"contentBar\", ImVec2(canvas_size.x, float(controlHeight)));\n         const ImVec2 contentMin = ImGui::GetItemRectMin();\n         const ImVec2 contentMax = ImGui::GetItemRectMax();\n         const ImRect contentRect(contentMin, contentMax);\n         const float contentHeight = contentMax.y - contentMin.y;\n\n         // full background\n         draw_list->AddRectFilled(canvas_pos, canvas_pos + canvas_size, 0xFF242424, 0);\n\n         // current frame top\n         ImRect topRect(ImVec2(canvas_pos.x + legendWidth, canvas_pos.y), ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + ItemHeight));\n\n         if (!MovingCurrentFrame && !MovingScrollBar && movingEntry == -1 && sequenceOptions & SEQUENCER_CHANGE_FRAME && currentFrame && *currentFrame >= 0 && topRect.Contains(io.MousePos) && io.MouseDown[0])\n         {\n            MovingCurrentFrame = true;\n         }\n         if (MovingCurrentFrame)\n         {\n            if (frameCount)\n            {\n               *currentFrame = (int)((io.MousePos.x - topRect.Min.x) / framePixelWidth) + firstFrameUsed;\n               if (*currentFrame < sequence->GetFrameMin())\n                  *currentFrame = sequence->GetFrameMin();\n               if (*currentFrame >= sequence->GetFrameMax())\n                  *currentFrame = sequence->GetFrameMax();\n            }\n            if (!io.MouseDown[0])\n               MovingCurrentFrame = false;\n         }\n\n         //header\n         draw_list->AddRectFilled(canvas_pos, ImVec2(canvas_size.x + canvas_pos.x, canvas_pos.y + ItemHeight), 0xFF3D3837, 0);\n         if (sequenceOptions & SEQUENCER_ADD)\n         {\n            if (SequencerAddDelButton(draw_list, ImVec2(canvas_pos.x + legendWidth - ItemHeight, canvas_pos.y + 2), true))\n               ImGui::OpenPopup(\"addEntry\");\n\n            if (ImGui::BeginPopup(\"addEntry\"))\n            {\n               for (int i = 0; i < sequence->GetItemTypeCount(); i++)\n                  if (ImGui::Selectable(sequence->GetItemTypeName(i)))\n                  {\n                     sequence->Add(i);\n                     *selectedEntry = sequence->GetItemCount() - 1;\n                  }\n\n               ImGui::EndPopup();\n               popupOpened = true;\n            }\n         }\n\n         //header frame number and lines\n         int modFrameCount = 10;\n         int frameStep = 1;\n         while ((modFrameCount * framePixelWidth) < 150)\n         {\n            modFrameCount *= 2;\n            frameStep *= 2;\n         };\n         int halfModFrameCount = modFrameCount / 2;\n\n         auto drawLine = [&](int i, int regionHeight) {\n            bool baseIndex = ((i % modFrameCount) == 0) || (i == sequence->GetFrameMax() || i == sequence->GetFrameMin());\n            bool halfIndex = (i % halfModFrameCount) == 0;\n            int px = (int)canvas_pos.x + int(i * framePixelWidth) + legendWidth - int(firstFrameUsed * framePixelWidth);\n            int tiretStart = baseIndex ? 4 : (halfIndex ? 10 : 14);\n            int tiretEnd = baseIndex ? regionHeight : ItemHeight;\n\n            if (px <= (canvas_size.x + canvas_pos.x) && px >= (canvas_pos.x + legendWidth))\n            {\n               draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)tiretStart), ImVec2((float)px, canvas_pos.y + (float)tiretEnd - 1), 0xFF606060, 1);\n\n               draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)ItemHeight), ImVec2((float)px, canvas_pos.y + (float)regionHeight - 1), 0x30606060, 1);\n            }\n\n            if (baseIndex && px > (canvas_pos.x + legendWidth))\n            {\n               char tmps[512];\n               ImFormatString(tmps, IM_ARRAYSIZE(tmps), \"%d\", i);\n               draw_list->AddText(ImVec2((float)px + 3.f, canvas_pos.y), 0xFFBBBBBB, tmps);\n            }\n\n         };\n\n         auto drawLineContent = [&](int i, int /*regionHeight*/) {\n            int px = (int)canvas_pos.x + int(i * framePixelWidth) + legendWidth - int(firstFrameUsed * framePixelWidth);\n            int tiretStart = int(contentMin.y);\n            int tiretEnd = int(contentMax.y);\n\n            if (px <= (canvas_size.x + canvas_pos.x) && px >= (canvas_pos.x + legendWidth))\n            {\n               //draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)tiretStart), ImVec2((float)px, canvas_pos.y + (float)tiretEnd - 1), 0xFF606060, 1);\n\n               draw_list->AddLine(ImVec2(float(px), float(tiretStart)), ImVec2(float(px), float(tiretEnd)), 0x30606060, 1);\n            }\n         };\n         for (int i = sequence->GetFrameMin(); i <= sequence->GetFrameMax(); i += frameStep)\n         {\n            drawLine(i, ItemHeight);\n         }\n         drawLine(sequence->GetFrameMin(), ItemHeight);\n         drawLine(sequence->GetFrameMax(), ItemHeight);\n         /*\n                  draw_list->AddLine(canvas_pos, ImVec2(canvas_pos.x, canvas_pos.y + controlHeight), 0xFF000000, 1);\n                  draw_list->AddLine(ImVec2(canvas_pos.x, canvas_pos.y + ItemHeight), ImVec2(canvas_size.x, canvas_pos.y + ItemHeight), 0xFF000000, 1);\n                  */\n                  // clip content\n\n         draw_list->PushClipRect(childFramePos, childFramePos + childFrameSize, true);\n\n         // draw item names in the legend rect on the left\n         size_t customHeight = 0;\n         for (int i = 0; i < sequenceCount; i++)\n         {\n            int type;\n            sequence->Get(i, NULL, NULL, &type, NULL);\n            ImVec2 tpos(contentMin.x + 3, contentMin.y + i * ItemHeight + 2 + customHeight);\n            draw_list->AddText(tpos, 0xFFFFFFFF, sequence->GetItemLabel(i));\n\n            if (sequenceOptions & SEQUENCER_DEL)\n            {\n               if (SequencerAddDelButton(draw_list, ImVec2(contentMin.x + legendWidth - ItemHeight + 2 - 10, tpos.y + 2), false))\n                  delEntry = i;\n\n               if (SequencerAddDelButton(draw_list, ImVec2(contentMin.x + legendWidth - ItemHeight - ItemHeight + 2 - 10, tpos.y + 2), true))\n                  dupEntry = i;\n            }\n            customHeight += sequence->GetCustomHeight(i);\n         }\n\n         // slots background\n         customHeight = 0;\n         for (int i = 0; i < sequenceCount; i++)\n         {\n            unsigned int col = (i & 1) ? 0xFF3A3636 : 0xFF413D3D;\n\n            size_t localCustomHeight = sequence->GetCustomHeight(i);\n            ImVec2 pos = ImVec2(contentMin.x + legendWidth, contentMin.y + ItemHeight * i + 1 + customHeight);\n            ImVec2 sz = ImVec2(canvas_size.x + canvas_pos.x, pos.y + ItemHeight - 1 + localCustomHeight);\n            if (!popupOpened && cy >= pos.y && cy < pos.y + (ItemHeight + localCustomHeight) && movingEntry == -1 && cx>contentMin.x && cx < contentMin.x + canvas_size.x)\n            {\n               col += 0x80201008;\n               pos.x -= legendWidth;\n            }\n            draw_list->AddRectFilled(pos, sz, col, 0);\n            customHeight += localCustomHeight;\n         }\n\n         draw_list->PushClipRect(childFramePos + ImVec2(float(legendWidth), 0.f), childFramePos + childFrameSize, true);\n\n         // vertical frame lines in content area\n         for (int i = sequence->GetFrameMin(); i <= sequence->GetFrameMax(); i += frameStep)\n         {\n            drawLineContent(i, int(contentHeight));\n         }\n         drawLineContent(sequence->GetFrameMin(), int(contentHeight));\n         drawLineContent(sequence->GetFrameMax(), int(contentHeight));\n\n         // selection\n         bool selected = selectedEntry && (*selectedEntry >= 0);\n         if (selected)\n         {\n            customHeight = 0;\n            for (int i = 0; i < *selectedEntry; i++)\n               customHeight += sequence->GetCustomHeight(i);\n            draw_list->AddRectFilled(ImVec2(contentMin.x, contentMin.y + ItemHeight * *selectedEntry + customHeight), ImVec2(contentMin.x + canvas_size.x, contentMin.y + ItemHeight * (*selectedEntry + 1) + customHeight), 0x801080FF, 1.f);\n         }\n\n         // slots\n         customHeight = 0;\n         for (int i = 0; i < sequenceCount; i++)\n         {\n            int* start, * end;\n            unsigned int color;\n            sequence->Get(i, &start, &end, NULL, &color);\n            size_t localCustomHeight = sequence->GetCustomHeight(i);\n\n            ImVec2 pos = ImVec2(contentMin.x + legendWidth - firstFrameUsed * framePixelWidth, contentMin.y + ItemHeight * i + 1 + customHeight);\n            ImVec2 slotP1(pos.x + *start * framePixelWidth, pos.y + 2);\n            ImVec2 slotP2(pos.x + *end * framePixelWidth + framePixelWidth, pos.y + ItemHeight - 2);\n            ImVec2 slotP3(pos.x + *end * framePixelWidth + framePixelWidth, pos.y + ItemHeight - 2 + localCustomHeight);\n            unsigned int slotColor = color | 0xFF000000;\n            unsigned int slotColorHalf = (color & 0xFFFFFF) | 0x40000000;\n\n            if (slotP1.x <= (canvas_size.x + contentMin.x) && slotP2.x >= (contentMin.x + legendWidth))\n            {\n               draw_list->AddRectFilled(slotP1, slotP3, slotColorHalf, 2);\n               draw_list->AddRectFilled(slotP1, slotP2, slotColor, 2);\n            }\n            if (ImRect(slotP1, slotP2).Contains(io.MousePos) && io.MouseDoubleClicked[0])\n            {\n               sequence->DoubleClick(i);\n            }\n            // Ensure grabbable handles\n            const float max_handle_width = slotP2.x - slotP1.x / 3.0f;\n            const float min_handle_width = ImMin(10.0f, max_handle_width);\n            const float handle_width = ImClamp(framePixelWidth / 2.0f, min_handle_width, max_handle_width);\n            ImRect rects[3] = { ImRect(slotP1, ImVec2(slotP1.x + handle_width, slotP2.y))\n                , ImRect(ImVec2(slotP2.x - handle_width, slotP1.y), slotP2)\n                , ImRect(slotP1, slotP2) };\n\n            const unsigned int quadColor[] = { 0xFFFFFFFF, 0xFFFFFFFF, slotColor + (selected ? 0 : 0x202020) };\n            if (movingEntry == -1 && (sequenceOptions & SEQUENCER_EDIT_STARTEND))// TODOFOCUS && backgroundRect.Contains(io.MousePos))\n            {\n               for (int j = 2; j >= 0; j--)\n               {\n                  ImRect& rc = rects[j];\n                  if (!rc.Contains(io.MousePos))\n                     continue;\n                  draw_list->AddRectFilled(rc.Min, rc.Max, quadColor[j], 2);\n               }\n\n               for (int j = 0; j < 3; j++)\n               {\n                  ImRect& rc = rects[j];\n                  if (!rc.Contains(io.MousePos))\n                     continue;\n                  if (!ImRect(childFramePos, childFramePos + childFrameSize).Contains(io.MousePos))\n                     continue;\n                  if (ImGui::IsMouseClicked(0) && !MovingScrollBar && !MovingCurrentFrame)\n                  {\n                     movingEntry = i;\n                     movingPos = cx;\n                     movingPart = j + 1;\n                     sequence->BeginEdit(movingEntry);\n                     break;\n                  }\n               }\n            }\n\n            // custom draw\n            if (localCustomHeight > 0)\n            {\n               ImVec2 rp(canvas_pos.x, contentMin.y + ItemHeight * i + 1 + customHeight);\n               ImRect customRect(rp + ImVec2(legendWidth - (firstFrameUsed - sequence->GetFrameMin() - 0.5f) * framePixelWidth, float(ItemHeight)),\n                  rp + ImVec2(legendWidth + (sequence->GetFrameMax() - firstFrameUsed - 0.5f + 2.f) * framePixelWidth, float(localCustomHeight + ItemHeight)));\n               ImRect clippingRect(rp + ImVec2(float(legendWidth), float(ItemHeight)), rp + ImVec2(canvas_size.x, float(localCustomHeight + ItemHeight)));\n\n               ImRect legendRect(rp + ImVec2(0.f, float(ItemHeight)), rp + ImVec2(float(legendWidth), float(localCustomHeight)));\n               ImRect legendClippingRect(canvas_pos + ImVec2(0.f, float(ItemHeight)), canvas_pos + ImVec2(float(legendWidth), float(localCustomHeight + ItemHeight)));\n               customDraws.push_back({ i, customRect, legendRect, clippingRect, legendClippingRect });\n            }\n            else\n            {\n               ImVec2 rp(canvas_pos.x, contentMin.y + ItemHeight * i + customHeight);\n               ImRect customRect(rp + ImVec2(legendWidth - (firstFrameUsed - sequence->GetFrameMin() - 0.5f) * framePixelWidth, float(0.f)),\n                  rp + ImVec2(legendWidth + (sequence->GetFrameMax() - firstFrameUsed - 0.5f + 2.f) * framePixelWidth, float(ItemHeight)));\n               ImRect clippingRect(rp + ImVec2(float(legendWidth), float(0.f)), rp + ImVec2(canvas_size.x, float(ItemHeight)));\n\n               compactCustomDraws.push_back({ i, customRect, ImRect(), clippingRect, ImRect() });\n            }\n            customHeight += localCustomHeight;\n         }\n\n\n         // moving\n         if (/*backgroundRect.Contains(io.MousePos) && */movingEntry >= 0)\n         {\n#if IMGUI_VERSION_NUM >= 18723\n            ImGui::SetNextFrameWantCaptureMouse(true);\n#else\n            ImGui::CaptureMouseFromApp();\n#endif\n            int diffFrame = int((cx - movingPos) / framePixelWidth);\n            if (std::abs(diffFrame) > 0)\n            {\n               int* start, * end;\n               sequence->Get(movingEntry, &start, &end, NULL, NULL);\n               if (selectedEntry)\n                  *selectedEntry = movingEntry;\n               int& l = *start;\n               int& r = *end;\n               if (movingPart & 1)\n                  l += diffFrame;\n               if (movingPart & 2)\n                  r += diffFrame;\n               if (l < 0)\n               {\n                  if (movingPart & 2)\n                     r -= l;\n                  l = 0;\n               }\n               if (movingPart & 1 && l > r)\n                  l = r;\n               if (movingPart & 2 && r < l)\n                  r = l;\n               movingPos += int(diffFrame * framePixelWidth);\n            }\n            if (!io.MouseDown[0])\n            {\n               // single select\n               if (!diffFrame && movingPart && selectedEntry)\n               {\n                  *selectedEntry = movingEntry;\n                  ret = true;\n               }\n\n               movingEntry = -1;\n               sequence->EndEdit();\n            }\n         }\n\n         // cursor\n         if (currentFrame && firstFrame && *currentFrame >= *firstFrame && *currentFrame <= sequence->GetFrameMax())\n         {\n            static const float cursorWidth = 8.f;\n            float cursorOffset = contentMin.x + legendWidth + (*currentFrame - firstFrameUsed) * framePixelWidth + framePixelWidth / 2 - cursorWidth * 0.5f;\n            draw_list->AddLine(ImVec2(cursorOffset, canvas_pos.y), ImVec2(cursorOffset, contentMax.y), 0xA02A2AFF, cursorWidth);\n            char tmps[512];\n            ImFormatString(tmps, IM_ARRAYSIZE(tmps), \"%d\", *currentFrame);\n            draw_list->AddText(ImVec2(cursorOffset + 10, canvas_pos.y + 2), 0xFF2A2AFF, tmps);\n         }\n\n         draw_list->PopClipRect();\n         draw_list->PopClipRect();\n\n         for (auto& customDraw : customDraws)\n            sequence->CustomDraw(customDraw.index, draw_list, customDraw.customRect, customDraw.legendRect, customDraw.clippingRect, customDraw.legendClippingRect);\n         for (auto& customDraw : compactCustomDraws)\n            sequence->CustomDrawCompact(customDraw.index, draw_list, customDraw.customRect, customDraw.clippingRect);\n\n         // copy paste\n         if (sequenceOptions & SEQUENCER_COPYPASTE)\n         {\n            ImRect rectCopy(ImVec2(contentMin.x + 100, canvas_pos.y + 2)\n               , ImVec2(contentMin.x + 100 + 30, canvas_pos.y + ItemHeight - 2));\n            bool inRectCopy = rectCopy.Contains(io.MousePos);\n            unsigned int copyColor = inRectCopy ? 0xFF1080FF : 0xFF000000;\n            draw_list->AddText(rectCopy.Min, copyColor, \"Copy\");\n\n            ImRect rectPaste(ImVec2(contentMin.x + 140, canvas_pos.y + 2)\n               , ImVec2(contentMin.x + 140 + 30, canvas_pos.y + ItemHeight - 2));\n            bool inRectPaste = rectPaste.Contains(io.MousePos);\n            unsigned int pasteColor = inRectPaste ? 0xFF1080FF : 0xFF000000;\n            draw_list->AddText(rectPaste.Min, pasteColor, \"Paste\");\n\n            if (inRectCopy && io.MouseReleased[0])\n            {\n               sequence->Copy();\n            }\n            if (inRectPaste && io.MouseReleased[0])\n            {\n               sequence->Paste();\n            }\n         }\n         //\n\n         ImGui::EndChildFrame();\n         ImGui::PopStyleColor();\n         if (hasScrollBar)\n         {\n            ImGui::InvisibleButton(\"scrollBar\", scrollBarSize);\n            ImVec2 scrollBarMin = ImGui::GetItemRectMin();\n            ImVec2 scrollBarMax = ImGui::GetItemRectMax();\n\n            // ratio = number of frames visible in control / number to total frames\n\n            float startFrameOffset = ((float)(firstFrameUsed - sequence->GetFrameMin()) / (float)frameCount) * (canvas_size.x - legendWidth);\n            ImVec2 scrollBarA(scrollBarMin.x + legendWidth, scrollBarMin.y - 2);\n            ImVec2 scrollBarB(scrollBarMin.x + canvas_size.x, scrollBarMax.y - 1);\n            draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF222222, 0);\n\n            ImRect scrollBarRect(scrollBarA, scrollBarB);\n            bool inScrollBar = scrollBarRect.Contains(io.MousePos);\n\n            draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF101010, 8);\n\n\n            ImVec2 scrollBarC(scrollBarMin.x + legendWidth + startFrameOffset, scrollBarMin.y);\n            ImVec2 scrollBarD(scrollBarMin.x + legendWidth + barWidthInPixels + startFrameOffset, scrollBarMax.y - 2);\n            draw_list->AddRectFilled(scrollBarC, scrollBarD, (inScrollBar || MovingScrollBar) ? 0xFF606060 : 0xFF505050, 6);\n\n            ImRect barHandleLeft(scrollBarC, ImVec2(scrollBarC.x + 14, scrollBarD.y));\n            ImRect barHandleRight(ImVec2(scrollBarD.x - 14, scrollBarC.y), scrollBarD);\n\n            bool onLeft = barHandleLeft.Contains(io.MousePos);\n            bool onRight = barHandleRight.Contains(io.MousePos);\n\n            static bool sizingRBar = false;\n            static bool sizingLBar = false;\n\n            draw_list->AddRectFilled(barHandleLeft.Min, barHandleLeft.Max, (onLeft || sizingLBar) ? 0xFFAAAAAA : 0xFF666666, 6);\n            draw_list->AddRectFilled(barHandleRight.Min, barHandleRight.Max, (onRight || sizingRBar) ? 0xFFAAAAAA : 0xFF666666, 6);\n\n            ImRect scrollBarThumb(scrollBarC, scrollBarD);\n            static const float MinBarWidth = 44.f;\n            if (sizingRBar)\n            {\n               if (!io.MouseDown[0])\n               {\n                  sizingRBar = false;\n               }\n               else\n               {\n                  float barNewWidth = ImMax(barWidthInPixels + io.MouseDelta.x, MinBarWidth);\n                  float barRatio = barNewWidth / barWidthInPixels;\n                  framePixelWidthTarget = framePixelWidth = framePixelWidth / barRatio;\n                  int newVisibleFrameCount = int((canvas_size.x - legendWidth) / framePixelWidthTarget);\n                  int lastFrame = *firstFrame + newVisibleFrameCount;\n                  if (lastFrame > sequence->GetFrameMax())\n                  {\n                     framePixelWidthTarget = framePixelWidth = (canvas_size.x - legendWidth) / float(sequence->GetFrameMax() - *firstFrame);\n                  }\n               }\n            }\n            else if (sizingLBar)\n            {\n               if (!io.MouseDown[0])\n               {\n                  sizingLBar = false;\n               }\n               else\n               {\n                  if (fabsf(io.MouseDelta.x) > FLT_EPSILON)\n                  {\n                     float barNewWidth = ImMax(barWidthInPixels - io.MouseDelta.x, MinBarWidth);\n                     float barRatio = barNewWidth / barWidthInPixels;\n                     float previousFramePixelWidthTarget = framePixelWidthTarget;\n                     framePixelWidthTarget = framePixelWidth = framePixelWidth / barRatio;\n                     int newVisibleFrameCount = int(visibleFrameCount / barRatio);\n                     int newFirstFrame = *firstFrame + newVisibleFrameCount - visibleFrameCount;\n                     newFirstFrame = ImClamp(newFirstFrame, sequence->GetFrameMin(), ImMax(sequence->GetFrameMax() - visibleFrameCount, sequence->GetFrameMin()));\n                     if (newFirstFrame == *firstFrame)\n                     {\n                        framePixelWidth = framePixelWidthTarget = previousFramePixelWidthTarget;\n                     }\n                     else\n                     {\n                        *firstFrame = newFirstFrame;\n                     }\n                  }\n               }\n            }\n            else\n            {\n               if (MovingScrollBar)\n               {\n                  if (!io.MouseDown[0])\n                  {\n                     MovingScrollBar = false;\n                  }\n                  else\n                  {\n                     float framesPerPixelInBar = barWidthInPixels / (float)visibleFrameCount;\n                     *firstFrame = int((io.MousePos.x - panningViewSource.x) / framesPerPixelInBar) - panningViewFrame;\n                     *firstFrame = ImClamp(*firstFrame, sequence->GetFrameMin(), ImMax(sequence->GetFrameMax() - visibleFrameCount, sequence->GetFrameMin()));\n                  }\n               }\n               else\n               {\n                  if (scrollBarThumb.Contains(io.MousePos) && ImGui::IsMouseClicked(0) && firstFrame && !MovingCurrentFrame && movingEntry == -1)\n                  {\n                     MovingScrollBar = true;\n                     panningViewSource = io.MousePos;\n                     panningViewFrame = -*firstFrame;\n                  }\n                  if (!sizingRBar && onRight && ImGui::IsMouseClicked(0))\n                     sizingRBar = true;\n                  if (!sizingLBar && onLeft && ImGui::IsMouseClicked(0))\n                     sizingLBar = true;\n\n               }\n            }\n         }\n      }\n\n      ImGui::EndGroup();\n\n      if (regionRect.Contains(io.MousePos))\n      {\n         bool overCustomDraw = false;\n         for (auto& custom : customDraws)\n         {\n            if (custom.customRect.Contains(io.MousePos))\n            {\n               overCustomDraw = true;\n            }\n         }\n         if (overCustomDraw)\n         {\n         }\n         else\n         {\n#if 0\n            frameOverCursor = *firstFrame + (int)(visibleFrameCount * ((io.MousePos.x - (float)legendWidth - canvas_pos.x) / (canvas_size.x - legendWidth)));\n            //frameOverCursor = max(min(*firstFrame - visibleFrameCount / 2, frameCount - visibleFrameCount), 0);\n\n            /**firstFrame -= frameOverCursor;\n            *firstFrame *= framePixelWidthTarget / framePixelWidth;\n            *firstFrame += frameOverCursor;*/\n            if (io.MouseWheel < -FLT_EPSILON)\n            {\n               *firstFrame -= frameOverCursor;\n               *firstFrame = int(*firstFrame * 1.1f);\n               framePixelWidthTarget *= 0.9f;\n               *firstFrame += frameOverCursor;\n            }\n\n            if (io.MouseWheel > FLT_EPSILON)\n            {\n               *firstFrame -= frameOverCursor;\n               *firstFrame = int(*firstFrame * 0.9f);\n               framePixelWidthTarget *= 1.1f;\n               *firstFrame += frameOverCursor;\n            }\n#endif\n         }\n      }\n\n      if (expanded)\n      {\n         if (SequencerAddDelButton(draw_list, ImVec2(canvas_pos.x + 2, canvas_pos.y + 2), !*expanded))\n            *expanded = !*expanded;\n      }\n\n      if (delEntry != -1)\n      {\n         sequence->Del(delEntry);\n         if (selectedEntry && (*selectedEntry == delEntry || *selectedEntry >= sequence->GetItemCount()))\n            *selectedEntry = -1;\n      }\n\n      if (dupEntry != -1)\n      {\n         sequence->Duplicate(dupEntry);\n      }\n      return ret;\n   }\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImSequencer.h",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#pragma once\n\n#include <cstddef>\n\nstruct ImDrawList;\nstruct ImRect;\nnamespace ImSequencer\n{\n   enum SEQUENCER_OPTIONS\n   {\n      SEQUENCER_EDIT_NONE = 0,\n      SEQUENCER_EDIT_STARTEND = 1 << 1,\n      SEQUENCER_CHANGE_FRAME = 1 << 3,\n      SEQUENCER_ADD = 1 << 4,\n      SEQUENCER_DEL = 1 << 5,\n      SEQUENCER_COPYPASTE = 1 << 6,\n      SEQUENCER_EDIT_ALL = SEQUENCER_EDIT_STARTEND | SEQUENCER_CHANGE_FRAME\n   };\n\n   struct SequenceInterface\n   {\n      bool focused = false;\n      virtual int GetFrameMin() const = 0;\n      virtual int GetFrameMax() const = 0;\n      virtual int GetItemCount() const = 0;\n\n      virtual void BeginEdit(int /*index*/) {}\n      virtual void EndEdit() {}\n      virtual int GetItemTypeCount() const { return 0; }\n      virtual const char* GetItemTypeName(int /*typeIndex*/) const { return \"\"; }\n      virtual const char* GetItemLabel(int /*index*/) const { return \"\"; }\n      virtual const char* GetCollapseFmt() const { return \"%d Frames / %d entries\"; }\n\n      virtual void Get(int index, int** start, int** end, int* type, unsigned int* color) = 0;\n      virtual void Add(int /*type*/) {}\n      virtual void Del(int /*index*/) {}\n      virtual void Duplicate(int /*index*/) {}\n\n      virtual void Copy() {}\n      virtual void Paste() {}\n\n      virtual size_t GetCustomHeight(int /*index*/) { return 0; }\n      virtual void DoubleClick(int /*index*/) {}\n      virtual void CustomDraw(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*legendRect*/, const ImRect& /*clippingRect*/, const ImRect& /*legendClippingRect*/) {}\n      virtual void CustomDrawCompact(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*clippingRect*/) {}\n   };\n\n\n   // return true if selection is made\n   bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions);\n\n}\n"
  },
  {
    "path": "Source/External/imgui_tools/imguizmo/ImZoomSlider.h",
    "content": "// https://github.com/CedricGuillemet/ImGuizmo\n// v 1.89 WIP\n//\n// The MIT License(MIT)\n//\n// Copyright(c) 2021 Cedric Guillemet\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n//\n#pragma once\n\nnamespace ImZoomSlider\n{\n   typedef int ImGuiZoomSliderFlags;\n   enum ImGuiPopupFlags_\n   {\n      ImGuiZoomSliderFlags_None = 0,\n      ImGuiZoomSliderFlags_Vertical = 1,\n      ImGuiZoomSliderFlags_NoAnchors = 2,\n      ImGuiZoomSliderFlags_NoMiddleCarets = 4,\n      ImGuiZoomSliderFlags_NoWheel = 8,\n   };\n\n   template<typename T> bool ImZoomSlider(const T lower, const T higher, T& viewLower, T& viewHigher, float wheelRatio = 0.01f, ImGuiZoomSliderFlags flags = ImGuiZoomSliderFlags_None)\n   {\n      bool interacted = false;\n      ImGuiIO& io = ImGui::GetIO();\n      ImDrawList* draw_list = ImGui::GetWindowDrawList();\n\n      static const float handleSize = 12;\n      static const float roundRadius = 3.f;\n      static const char* controlName = \"ImZoomSlider\";\n\n      static bool movingScrollBarSvg = false;\n      static bool sizingRBarSvg = false;\n      static bool sizingLBarSvg = false;\n      static ImGuiID editingId = (ImGuiID)-1;\n      static float scrollingSource = 0.f;\n      static float saveViewLower;\n      static float saveViewHigher;\n\n      const bool isVertical = flags & ImGuiZoomSliderFlags_Vertical;\n      const ImVec2 canvasPos = ImGui::GetCursorScreenPos();\n      const ImVec2 canvasSize = ImGui::GetContentRegionAvail();\n      const float canvasSizeLength = isVertical ? ImGui::GetItemRectSize().y : canvasSize.x;\n      const ImVec2 scrollBarSize = isVertical ? ImVec2(14.f, canvasSizeLength) : ImVec2(canvasSizeLength, 14.f);\n\n      ImGui::InvisibleButton(controlName, scrollBarSize);\n      const ImGuiID currentId = ImGui::GetID(controlName);\n\n      const bool usingEditingId = currentId == editingId;\n      const bool canUseControl = usingEditingId || editingId == -1;\n      const bool movingScrollBar = usingEditingId ? movingScrollBarSvg : false;\n      const bool sizingRBar = usingEditingId ? sizingRBarSvg : false;\n      const bool sizingLBar = usingEditingId ? sizingLBarSvg : false;\n      const int componentIndex = isVertical ? 1 : 0;\n      const ImVec2 scrollBarMin = ImGui::GetItemRectMin();\n      const ImVec2 scrollBarMax = ImGui::GetItemRectMax();\n      const ImVec2 scrollBarA = ImVec2(scrollBarMin.x, scrollBarMin.y) - (isVertical ? ImVec2(2,0) : ImVec2(0,2));\n      const ImVec2 scrollBarB = isVertical ? ImVec2(scrollBarMax.x - 1.f, scrollBarMin.y + canvasSizeLength) : ImVec2(scrollBarMin.x + canvasSizeLength, scrollBarMax.y - 1.f);\n      const float scrollStart = ((viewLower - lower) / (higher - lower)) * canvasSizeLength + scrollBarMin[componentIndex];\n      const float scrollEnd = ((viewHigher - lower) / (higher - lower)) * canvasSizeLength + scrollBarMin[componentIndex];\n      const float screenSize = scrollEnd - scrollStart;\n      const ImVec2 scrollTopLeft = isVertical ? ImVec2(scrollBarMin.x, scrollStart) : ImVec2(scrollStart, scrollBarMin.y);\n      const ImVec2 scrollBottomRight = isVertical ? ImVec2(scrollBarMax.x - 2.f, scrollEnd) : ImVec2(scrollEnd, scrollBarMax.y - 2.f);\n      const bool inScrollBar = canUseControl && ImRect(scrollTopLeft, scrollBottomRight).Contains(io.MousePos);\n      const ImRect scrollBarRect(scrollBarA, scrollBarB);\n      const float deltaScreen = io.MousePos[componentIndex] - scrollingSource;\n      const float deltaView = ((higher - lower) / canvasSizeLength) * deltaScreen;\n      const uint32_t barColor = ImGui::GetColorU32((inScrollBar || movingScrollBar) ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);\n      const float middleCoord = (scrollStart + scrollEnd) * 0.5f;\n      const bool insideControl = canUseControl && ImRect(scrollBarMin, scrollBarMax).Contains(io.MousePos);\n      const bool hasAnchors = !(flags & ImGuiZoomSliderFlags_NoAnchors);\n      const float viewMinSize = ((3.f * handleSize) / canvasSizeLength) * (higher - lower);\n      const auto ClipView = [lower, higher, &viewLower, &viewHigher]() {\n         if (viewLower < lower)\n         {\n            const float deltaClip = lower - viewLower;\n            viewLower += deltaClip;\n            viewHigher += deltaClip;\n         }\n         if (viewHigher > higher)\n         {\n            const float deltaClip = viewHigher - higher;\n            viewLower -= deltaClip;\n            viewHigher -= deltaClip;\n         }\n      };\n\n      bool onLeft = false;\n      bool onRight = false;\n\n      draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF101010, roundRadius);\n      draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF222222, 0);\n      draw_list->AddRectFilled(scrollTopLeft, scrollBottomRight, barColor, roundRadius);\n\n      if (!(flags & ImGuiZoomSliderFlags_NoMiddleCarets))\n      {\n         for (float i = 0.5f; i < 3.f; i += 1.f)\n         {\n            const float coordA = middleCoord - handleSize * 0.5f;\n            const float coordB = middleCoord + handleSize * 0.5f;\n            ImVec2 base = scrollBarMin;\n            base.x += scrollBarSize.x * 0.25f * i;\n            base.y += scrollBarSize.y * 0.25f * i;\n\n            if (isVertical)\n            {\n               draw_list->AddLine(ImVec2(base.x, coordA), ImVec2(base.x, coordB), ImGui::GetColorU32(ImGuiCol_SliderGrab));\n            }\n            else\n            {\n               draw_list->AddLine(ImVec2(coordA, base.y), ImVec2(coordB, base.y), ImGui::GetColorU32(ImGuiCol_SliderGrab));\n            }\n         }\n      }\n\n      // Mouse wheel\n      if (io.MouseClicked[0] && insideControl && !inScrollBar)\n      {\n         const float ratio = (io.MousePos[componentIndex] - scrollBarMin[componentIndex]) / (scrollBarMax[componentIndex] - scrollBarMin[componentIndex]);\n         const float size = (higher - lower);\n         const float halfViewSize = (viewHigher - viewLower) * 0.5f;\n         const float middle = ratio * size + lower;\n         viewLower = middle - halfViewSize;\n         viewHigher = middle + halfViewSize;\n         ClipView();\n         interacted = true;\n      }\n\n      if (!(flags & ImGuiZoomSliderFlags_NoWheel) && inScrollBar && fabsf(io.MouseWheel) > 0.f)\n      {\n         const float ratio = (io.MousePos[componentIndex] - scrollStart) / (scrollEnd - scrollStart);\n         const float amount = io.MouseWheel * wheelRatio * (viewHigher - viewLower);\n         \n         viewLower -= ratio * amount;\n         viewHigher += (1.f - ratio) * amount;\n         ClipView();\n         interacted = true;\n      }\n\n      if (screenSize > handleSize * 2.f && hasAnchors)\n      {\n         const ImRect barHandleLeft(scrollTopLeft, isVertical ? ImVec2(scrollBottomRight.x, scrollTopLeft.y + handleSize) : ImVec2(scrollTopLeft.x + handleSize, scrollBottomRight.y));\n         const ImRect barHandleRight(isVertical ? ImVec2(scrollTopLeft.x, scrollBottomRight.y - handleSize) : ImVec2(scrollBottomRight.x - handleSize, scrollTopLeft.y), scrollBottomRight);\n\n         onLeft = barHandleLeft.Contains(io.MousePos);\n         onRight = barHandleRight.Contains(io.MousePos);\n\n         draw_list->AddRectFilled(barHandleLeft.Min, barHandleLeft.Max, ImGui::GetColorU32((onLeft || sizingLBar) ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), roundRadius);\n         draw_list->AddRectFilled(barHandleRight.Min, barHandleRight.Max, ImGui::GetColorU32((onRight || sizingRBar) ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), roundRadius);\n      }\n\n      if (sizingRBar)\n      {\n         if (!io.MouseDown[0])\n         {\n            sizingRBarSvg = false;\n            editingId = (ImGuiID)-1;\n         }\n         else\n         {\n            viewHigher = ImMin(saveViewHigher + deltaView, higher);\n         }\n      }\n      else if (sizingLBar)\n      {\n         if (!io.MouseDown[0])\n         {\n            sizingLBarSvg = false;\n            editingId = (ImGuiID)-1;\n         }\n         else\n         {\n            viewLower = ImMax(saveViewLower + deltaView, lower);\n         }\n      }\n      else\n      {\n         if (movingScrollBar)\n         {\n            if (!io.MouseDown[0])\n            {\n               movingScrollBarSvg = false;\n               editingId = (ImGuiID)-1;\n            }\n            else\n            {\n               viewLower = saveViewLower + deltaView;\n               viewHigher = saveViewHigher + deltaView;\n               ClipView();\n            }\n         }\n         else\n         {\n            if (inScrollBar && ImGui::IsMouseClicked(0))\n            {\n               movingScrollBarSvg = true;\n               scrollingSource = io.MousePos[componentIndex];\n               saveViewLower = viewLower;\n               saveViewHigher = viewHigher;\n               editingId = currentId;\n            }\n            if (!sizingRBar && onRight && ImGui::IsMouseClicked(0) && hasAnchors)\n            {\n               sizingRBarSvg = true;\n               editingId = currentId;\n            }\n            if (!sizingLBar && onLeft && ImGui::IsMouseClicked(0) && hasAnchors)\n            {\n               sizingLBarSvg = true;\n               editingId = currentId;\n            }\n         }\n      }\n\n      // minimal size check\n      if ((viewHigher - viewLower) < viewMinSize)\n      {\n         const float middle = (viewLower + viewHigher) * 0.5f;\n         viewLower = middle - viewMinSize * 0.5f;\n         viewHigher = middle + viewMinSize * 0.5f;\n         ClipView();\n      }\n\n      return movingScrollBar || sizingRBar || sizingLBar || interacted;\n   }\n\n} // namespace\n"
  },
  {
    "path": "Source/External/imgui_tools/imnodes/imnodes.cpp",
    "content": "// the structure of this file:\n//\n// [SECTION] bezier curve helpers\n// [SECTION] draw list helper\n// [SECTION] ui state logic\n// [SECTION] render helpers\n// [SECTION] API implementation\n\n#define IMGUI_DEFINE_MATH_OPERATORS\n#include \"imnodes.h\"\n#include \"imnodes_internal.h\"\n\n#include <imgui_internal.h>\n\n// Check minimum ImGui version\n#define MINIMUM_COMPATIBLE_IMGUI_VERSION 17400\n#if IMGUI_VERSION_NUM < MINIMUM_COMPATIBLE_IMGUI_VERSION\n#error \"Minimum ImGui version requirement not met -- please use a newer version!\"\n#endif\n\n#include <limits.h>\n#include <math.h>\n#include <new>\n#include <stdint.h>\n#include <stdio.h> // for fwrite, ssprintf, sscanf\n#include <stdlib.h>\n#include <string.h> // strlen, strncmp\n\n// Use secure CRT function variants to avoid MSVC compiler errors\n#ifdef _MSC_VER\n#define sscanf sscanf_s\n#endif\n\nImNodesContext* GImNodes = NULL;\n\nnamespace IMNODES_NAMESPACE\n{\nnamespace\n{\n// [SECTION] bezier curve helpers\n\nstruct CubicBezier\n{\n    ImVec2 P0, P1, P2, P3;\n    int    NumSegments;\n};\n\ninline ImVec2 EvalCubicBezier(\n    const float   t,\n    const ImVec2& P0,\n    const ImVec2& P1,\n    const ImVec2& P2,\n    const ImVec2& P3)\n{\n    // B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3\n\n    const float u = 1.0f - t;\n    const float b0 = u * u * u;\n    const float b1 = 3 * u * u * t;\n    const float b2 = 3 * u * t * t;\n    const float b3 = t * t * t;\n    return ImVec2(\n        b0 * P0.x + b1 * P1.x + b2 * P2.x + b3 * P3.x,\n        b0 * P0.y + b1 * P1.y + b2 * P2.y + b3 * P3.y);\n}\n\n// Calculates the closest point along each bezier curve segment.\nImVec2 GetClosestPointOnCubicBezier(const int num_segments, const ImVec2& p, const CubicBezier& cb)\n{\n    IM_ASSERT(num_segments > 0);\n    ImVec2 p_last = cb.P0;\n    ImVec2 p_closest;\n    float  p_closest_dist = FLT_MAX;\n    float  t_step = 1.0f / (float)num_segments;\n    for (int i = 1; i <= num_segments; ++i)\n    {\n        ImVec2 p_current = EvalCubicBezier(t_step * i, cb.P0, cb.P1, cb.P2, cb.P3);\n        ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);\n        float  dist = ImLengthSqr(p - p_line);\n        if (dist < p_closest_dist)\n        {\n            p_closest = p_line;\n            p_closest_dist = dist;\n        }\n        p_last = p_current;\n    }\n    return p_closest;\n}\n\ninline float GetDistanceToCubicBezier(\n    const ImVec2&      pos,\n    const CubicBezier& cubic_bezier,\n    const int          num_segments)\n{\n    const ImVec2 point_on_curve = GetClosestPointOnCubicBezier(num_segments, pos, cubic_bezier);\n\n    const ImVec2 to_curve = point_on_curve - pos;\n    return ImSqrt(ImLengthSqr(to_curve));\n}\n\ninline ImRect GetContainingRectForCubicBezier(const CubicBezier& cb)\n{\n    const ImVec2 min = ImVec2(ImMin(cb.P0.x, cb.P3.x), ImMin(cb.P0.y, cb.P3.y));\n    const ImVec2 max = ImVec2(ImMax(cb.P0.x, cb.P3.x), ImMax(cb.P0.y, cb.P3.y));\n\n    const float hover_distance = GImNodes->Style.LinkHoverDistance;\n\n    ImRect rect(min, max);\n    rect.Add(cb.P1);\n    rect.Add(cb.P2);\n    rect.Expand(ImVec2(hover_distance, hover_distance));\n\n    return rect;\n}\n\ninline CubicBezier GetCubicBezier(\n    ImVec2                     start,\n    ImVec2                     end,\n    const ImNodesAttributeType start_type,\n    const float                line_segments_per_length)\n{\n    IM_ASSERT(\n        (start_type == ImNodesAttributeType_Input) || (start_type == ImNodesAttributeType_Output));\n    if (start_type == ImNodesAttributeType_Input)\n    {\n        ImSwap(start, end);\n    }\n\n    const float  link_length = ImSqrt(ImLengthSqr(end - start));\n    const ImVec2 offset = ImVec2(0.25f * link_length, 0.f);\n    CubicBezier  cubic_bezier;\n    cubic_bezier.P0 = start;\n    cubic_bezier.P1 = start + offset;\n    cubic_bezier.P2 = end - offset;\n    cubic_bezier.P3 = end;\n    cubic_bezier.NumSegments = ImMax(static_cast<int>(link_length * line_segments_per_length), 1);\n    return cubic_bezier;\n}\n\ninline float EvalImplicitLineEq(const ImVec2& p1, const ImVec2& p2, const ImVec2& p)\n{\n    return (p2.y - p1.y) * p.x + (p1.x - p2.x) * p.y + (p2.x * p1.y - p1.x * p2.y);\n}\n\ninline int Sign(float val) { return int(val > 0.0f) - int(val < 0.0f); }\n\ninline bool RectangleOverlapsLineSegment(const ImRect& rect, const ImVec2& p1, const ImVec2& p2)\n{\n    // Trivial case: rectangle contains an endpoint\n    if (rect.Contains(p1) || rect.Contains(p2))\n    {\n        return true;\n    }\n\n    // Flip rectangle if necessary\n    ImRect flip_rect = rect;\n\n    if (flip_rect.Min.x > flip_rect.Max.x)\n    {\n        ImSwap(flip_rect.Min.x, flip_rect.Max.x);\n    }\n\n    if (flip_rect.Min.y > flip_rect.Max.y)\n    {\n        ImSwap(flip_rect.Min.y, flip_rect.Max.y);\n    }\n\n    // Trivial case: line segment lies to one particular side of rectangle\n    if ((p1.x < flip_rect.Min.x && p2.x < flip_rect.Min.x) ||\n        (p1.x > flip_rect.Max.x && p2.x > flip_rect.Max.x) ||\n        (p1.y < flip_rect.Min.y && p2.y < flip_rect.Min.y) ||\n        (p1.y > flip_rect.Max.y && p2.y > flip_rect.Max.y))\n    {\n        return false;\n    }\n\n    const int corner_signs[4] = {\n        Sign(EvalImplicitLineEq(p1, p2, flip_rect.Min)),\n        Sign(EvalImplicitLineEq(p1, p2, ImVec2(flip_rect.Max.x, flip_rect.Min.y))),\n        Sign(EvalImplicitLineEq(p1, p2, ImVec2(flip_rect.Min.x, flip_rect.Max.y))),\n        Sign(EvalImplicitLineEq(p1, p2, flip_rect.Max))};\n\n    int sum = 0;\n    int sum_abs = 0;\n\n    for (int i = 0; i < 4; ++i)\n    {\n        sum += corner_signs[i];\n        sum_abs += abs(corner_signs[i]);\n    }\n\n    // At least one corner of rectangle lies on a different side of line segment\n    return abs(sum) != sum_abs;\n}\n\ninline bool RectangleOverlapsBezier(const ImRect& rectangle, const CubicBezier& cubic_bezier)\n{\n    ImVec2 current =\n        EvalCubicBezier(0.f, cubic_bezier.P0, cubic_bezier.P1, cubic_bezier.P2, cubic_bezier.P3);\n    const float dt = 1.0f / cubic_bezier.NumSegments;\n    for (int s = 0; s < cubic_bezier.NumSegments; ++s)\n    {\n        ImVec2 next = EvalCubicBezier(\n            static_cast<float>((s + 1) * dt),\n            cubic_bezier.P0,\n            cubic_bezier.P1,\n            cubic_bezier.P2,\n            cubic_bezier.P3);\n        if (RectangleOverlapsLineSegment(rectangle, current, next))\n        {\n            return true;\n        }\n        current = next;\n    }\n    return false;\n}\n\ninline bool RectangleOverlapsLink(\n    const ImRect&              rectangle,\n    const ImVec2&              start,\n    const ImVec2&              end,\n    const ImNodesAttributeType start_type)\n{\n    // First level: simple rejection test via rectangle overlap:\n\n    ImRect lrect = ImRect(start, end);\n    if (lrect.Min.x > lrect.Max.x)\n    {\n        ImSwap(lrect.Min.x, lrect.Max.x);\n    }\n\n    if (lrect.Min.y > lrect.Max.y)\n    {\n        ImSwap(lrect.Min.y, lrect.Max.y);\n    }\n\n    if (rectangle.Overlaps(lrect))\n    {\n        // First, check if either one or both endpoinds are trivially contained\n        // in the rectangle\n\n        if (rectangle.Contains(start) || rectangle.Contains(end))\n        {\n            return true;\n        }\n\n        // Second level of refinement: do a more expensive test against the\n        // link\n\n        const CubicBezier cubic_bezier =\n            GetCubicBezier(start, end, start_type, GImNodes->Style.LinkLineSegmentsPerLength);\n        return RectangleOverlapsBezier(rectangle, cubic_bezier);\n    }\n\n    return false;\n}\n\n// [SECTION] coordinate space conversion helpers\n\ninline ImVec2 ScreenSpaceToGridSpace(const ImNodesEditorContext& editor, const ImVec2& v)\n{\n    return v - GImNodes->CanvasOriginScreenSpace - editor.Panning;\n}\n\ninline ImRect ScreenSpaceToGridSpace(const ImNodesEditorContext& editor, const ImRect& r)\n{\n    return ImRect(ScreenSpaceToGridSpace(editor, r.Min), ScreenSpaceToGridSpace(editor, r.Max));\n}\n\ninline ImVec2 GridSpaceToScreenSpace(const ImNodesEditorContext& editor, const ImVec2& v)\n{\n    return v + GImNodes->CanvasOriginScreenSpace + editor.Panning;\n}\n\ninline ImVec2 GridSpaceToEditorSpace(const ImNodesEditorContext& editor, const ImVec2& v)\n{\n    return v + editor.Panning;\n}\n\ninline ImVec2 EditorSpaceToGridSpace(const ImNodesEditorContext& editor, const ImVec2& v)\n{\n    return v - editor.Panning;\n}\n\ninline ImVec2 EditorSpaceToScreenSpace(const ImVec2& v)\n{\n    return GImNodes->CanvasOriginScreenSpace + v;\n}\n\ninline ImVec2 MiniMapSpaceToGridSpace(const ImNodesEditorContext& editor, const ImVec2& v)\n{\n    return (v - editor.MiniMapContentScreenSpace.Min) / editor.MiniMapScaling +\n           editor.GridContentBounds.Min;\n}\n\ninline ImVec2 ScreenSpaceToMiniMapSpace(const ImNodesEditorContext& editor, const ImVec2& v)\n{\n    return (ScreenSpaceToGridSpace(editor, v) - editor.GridContentBounds.Min) *\n               editor.MiniMapScaling +\n           editor.MiniMapContentScreenSpace.Min;\n}\n\ninline ImRect ScreenSpaceToMiniMapSpace(const ImNodesEditorContext& editor, const ImRect& r)\n{\n    return ImRect(\n        ScreenSpaceToMiniMapSpace(editor, r.Min), ScreenSpaceToMiniMapSpace(editor, r.Max));\n}\n\n// [SECTION] draw list helper\n\nvoid ImDrawListGrowChannels(ImDrawList* draw_list, const int num_channels)\n{\n    ImDrawListSplitter& splitter = draw_list->_Splitter;\n\n    if (splitter._Count == 1)\n    {\n        splitter.Split(draw_list, num_channels + 1);\n        return;\n    }\n\n    // NOTE: this logic has been lifted from ImDrawListSplitter::Split with slight modifications\n    // to allow nested splits. The main modification is that we only create new ImDrawChannel\n    // instances after splitter._Count, instead of over the whole splitter._Channels array like\n    // the regular ImDrawListSplitter::Split method does.\n\n    const int old_channel_capacity = splitter._Channels.Size;\n    // NOTE: _Channels is not resized down, and therefore _Count <= _Channels.size()!\n    const int old_channel_count = splitter._Count;\n    const int requested_channel_count = old_channel_count + num_channels;\n    if (old_channel_capacity < old_channel_count + num_channels)\n    {\n        splitter._Channels.resize(requested_channel_count);\n    }\n\n    splitter._Count = requested_channel_count;\n\n    for (int i = old_channel_count; i < requested_channel_count; ++i)\n    {\n        ImDrawChannel& channel = splitter._Channels[i];\n\n        // If we're inside the old capacity region of the array, we need to reuse the existing\n        // memory of the command and index buffers.\n        if (i < old_channel_capacity)\n        {\n            channel._CmdBuffer.resize(0);\n            channel._IdxBuffer.resize(0);\n        }\n        // Else, we need to construct new draw channels.\n        else\n        {\n            IM_PLACEMENT_NEW(&channel) ImDrawChannel();\n        }\n\n        {\n            ImDrawCmd draw_cmd;\n            draw_cmd.ClipRect = draw_list->_ClipRectStack.back();\n            draw_cmd.TextureId = draw_list->_TextureIdStack.back();\n            channel._CmdBuffer.push_back(draw_cmd);\n        }\n    }\n}\n\nvoid ImDrawListSplitterSwapChannels(\n    ImDrawListSplitter& splitter,\n    const int           lhs_idx,\n    const int           rhs_idx)\n{\n    if (lhs_idx == rhs_idx)\n    {\n        return;\n    }\n\n    IM_ASSERT(lhs_idx >= 0 && lhs_idx < splitter._Count);\n    IM_ASSERT(rhs_idx >= 0 && rhs_idx < splitter._Count);\n\n    ImDrawChannel& lhs_channel = splitter._Channels[lhs_idx];\n    ImDrawChannel& rhs_channel = splitter._Channels[rhs_idx];\n    lhs_channel._CmdBuffer.swap(rhs_channel._CmdBuffer);\n    lhs_channel._IdxBuffer.swap(rhs_channel._IdxBuffer);\n\n    const int current_channel = splitter._Current;\n\n    if (current_channel == lhs_idx)\n    {\n        splitter._Current = rhs_idx;\n    }\n    else if (current_channel == rhs_idx)\n    {\n        splitter._Current = lhs_idx;\n    }\n}\n\nvoid DrawListSet(ImDrawList* window_draw_list)\n{\n    GImNodes->CanvasDrawList = window_draw_list;\n    GImNodes->NodeIdxToSubmissionIdx.Clear();\n    GImNodes->NodeIdxSubmissionOrder.clear();\n}\n\n// The draw list channels are structured as follows. First we have our base channel, the canvas grid\n// on which we render the grid lines in BeginNodeEditor(). The base channel is the reason\n// draw_list_submission_idx_to_background_channel_idx offsets the index by one. Each BeginNode()\n// call appends two new draw channels, for the node background and foreground. The node foreground\n// is the channel into which the node's ImGui content is rendered. Finally, in EndNodeEditor() we\n// append one last draw channel for rendering the selection box and the incomplete link on top of\n// everything else.\n//\n// +----------+----------+----------+----------+----------+----------+\n// |          |          |          |          |          |          |\n// |canvas    |node      |node      |...       |...       |click     |\n// |grid      |background|foreground|          |          |interaction\n// |          |          |          |          |          |          |\n// +----------+----------+----------+----------+----------+----------+\n//            |                     |\n//            |   submission idx    |\n//            |                     |\n//            -----------------------\n\nvoid DrawListAddNode(const int node_idx)\n{\n    GImNodes->NodeIdxToSubmissionIdx.SetInt(\n        static_cast<ImGuiID>(node_idx), GImNodes->NodeIdxSubmissionOrder.Size);\n    GImNodes->NodeIdxSubmissionOrder.push_back(node_idx);\n    ImDrawListGrowChannels(GImNodes->CanvasDrawList, 2);\n}\n\nvoid DrawListAppendClickInteractionChannel()\n{\n    // NOTE: don't use this function outside of EndNodeEditor. Using this before all nodes have been\n    // added will screw up the node draw order.\n    ImDrawListGrowChannels(GImNodes->CanvasDrawList, 1);\n}\n\nint DrawListSubmissionIdxToBackgroundChannelIdx(const int submission_idx)\n{\n    // NOTE: the first channel is the canvas background, i.e. the grid\n    return 1 + 2 * submission_idx;\n}\n\nint DrawListSubmissionIdxToForegroundChannelIdx(const int submission_idx)\n{\n    return DrawListSubmissionIdxToBackgroundChannelIdx(submission_idx) + 1;\n}\n\nvoid DrawListActivateClickInteractionChannel()\n{\n    GImNodes->CanvasDrawList->_Splitter.SetCurrentChannel(\n        GImNodes->CanvasDrawList, GImNodes->CanvasDrawList->_Splitter._Count - 1);\n}\n\nvoid DrawListActivateCurrentNodeForeground()\n{\n    const int foreground_channel_idx =\n        DrawListSubmissionIdxToForegroundChannelIdx(GImNodes->NodeIdxSubmissionOrder.Size - 1);\n    GImNodes->CanvasDrawList->_Splitter.SetCurrentChannel(\n        GImNodes->CanvasDrawList, foreground_channel_idx);\n}\n\nvoid DrawListActivateNodeBackground(const int node_idx)\n{\n    const int submission_idx =\n        GImNodes->NodeIdxToSubmissionIdx.GetInt(static_cast<ImGuiID>(node_idx), -1);\n    // There is a discrepancy in the submitted node count and the rendered node count! Did you call\n    // one of the following functions\n    // * EditorContextMoveToNode\n    // * SetNodeScreenSpacePos\n    // * SetNodeGridSpacePos\n    // * SetNodeDraggable\n    // after the BeginNode/EndNode function calls?\n    IM_ASSERT(submission_idx != -1);\n    const int background_channel_idx = DrawListSubmissionIdxToBackgroundChannelIdx(submission_idx);\n    GImNodes->CanvasDrawList->_Splitter.SetCurrentChannel(\n        GImNodes->CanvasDrawList, background_channel_idx);\n}\n\nvoid DrawListSwapSubmissionIndices(const int lhs_idx, const int rhs_idx)\n{\n    IM_ASSERT(lhs_idx != rhs_idx);\n\n    const int lhs_foreground_channel_idx = DrawListSubmissionIdxToForegroundChannelIdx(lhs_idx);\n    const int lhs_background_channel_idx = DrawListSubmissionIdxToBackgroundChannelIdx(lhs_idx);\n    const int rhs_foreground_channel_idx = DrawListSubmissionIdxToForegroundChannelIdx(rhs_idx);\n    const int rhs_background_channel_idx = DrawListSubmissionIdxToBackgroundChannelIdx(rhs_idx);\n\n    ImDrawListSplitterSwapChannels(\n        GImNodes->CanvasDrawList->_Splitter,\n        lhs_background_channel_idx,\n        rhs_background_channel_idx);\n    ImDrawListSplitterSwapChannels(\n        GImNodes->CanvasDrawList->_Splitter,\n        lhs_foreground_channel_idx,\n        rhs_foreground_channel_idx);\n}\n\nvoid DrawListSortChannelsByDepth(const ImVector<int>& node_idx_depth_order)\n{\n    if (GImNodes->NodeIdxToSubmissionIdx.Data.Size < 2)\n    {\n        return;\n    }\n\n    IM_ASSERT(node_idx_depth_order.Size == GImNodes->NodeIdxSubmissionOrder.Size);\n\n    int start_idx = node_idx_depth_order.Size - 1;\n\n    while (node_idx_depth_order[start_idx] == GImNodes->NodeIdxSubmissionOrder[start_idx])\n    {\n        if (--start_idx == 0)\n        {\n            // early out if submission order and depth order are the same\n            return;\n        }\n    }\n\n    // TODO: this is an O(N^2) algorithm. It might be worthwhile revisiting this to see if the time\n    // complexity can be reduced.\n\n    for (int depth_idx = start_idx; depth_idx > 0; --depth_idx)\n    {\n        const int node_idx = node_idx_depth_order[depth_idx];\n\n        // Find the current index of the node_idx in the submission order array\n        int submission_idx = -1;\n        for (int i = 0; i < GImNodes->NodeIdxSubmissionOrder.Size; ++i)\n        {\n            if (GImNodes->NodeIdxSubmissionOrder[i] == node_idx)\n            {\n                submission_idx = i;\n                break;\n            }\n        }\n        IM_ASSERT(submission_idx >= 0);\n\n        if (submission_idx == depth_idx)\n        {\n            continue;\n        }\n\n        for (int j = submission_idx; j < depth_idx; ++j)\n        {\n            DrawListSwapSubmissionIndices(j, j + 1);\n            ImSwap(GImNodes->NodeIdxSubmissionOrder[j], GImNodes->NodeIdxSubmissionOrder[j + 1]);\n        }\n    }\n}\n\n// [SECTION] ui state logic\n\nImVec2 GetScreenSpacePinCoordinates(\n    const ImRect&              node_rect,\n    const ImRect&              attribute_rect,\n    const ImNodesAttributeType type)\n{\n    IM_ASSERT(type == ImNodesAttributeType_Input || type == ImNodesAttributeType_Output);\n    const float x = type == ImNodesAttributeType_Input\n                        ? (node_rect.Min.x - GImNodes->Style.PinOffset)\n                        : (node_rect.Max.x + GImNodes->Style.PinOffset);\n    return ImVec2(x, 0.5f * (attribute_rect.Min.y + attribute_rect.Max.y));\n}\n\nImVec2 GetScreenSpacePinCoordinates(const ImNodesEditorContext& editor, const ImPinData& pin)\n{\n    const ImRect& parent_node_rect = editor.Nodes.Pool[pin.ParentNodeIdx].Rect;\n    return GetScreenSpacePinCoordinates(parent_node_rect, pin.AttributeRect, pin.Type);\n}\n\nbool MouseInCanvas()\n{\n    // This flag should be true either when hovering or clicking something in the canvas.\n    const bool is_window_hovered_or_focused = ImGui::IsWindowHovered() || ImGui::IsWindowFocused();\n\n    return is_window_hovered_or_focused &&\n           GImNodes->CanvasRectScreenSpace.Contains(ImGui::GetMousePos());\n}\n\nvoid BeginNodeSelection(ImNodesEditorContext& editor, const int node_idx)\n{\n    // Don't start selecting a node if we are e.g. already creating and dragging\n    // a new link! New link creation can happen when the mouse is clicked over\n    // a node, but within the hover radius of a pin.\n    if (editor.ClickInteraction.Type != ImNodesClickInteractionType_None)\n    {\n        return;\n    }\n\n    editor.ClickInteraction.Type = ImNodesClickInteractionType_Node;\n    // If the node is not already contained in the selection, then we want only\n    // the interaction node to be selected, effective immediately.\n    //\n    // If the multiple selection modifier is active, we want to add this node\n    // to the current list of selected nodes.\n    //\n    // Otherwise, we want to allow for the possibility of multiple nodes to be\n    // moved at once.\n    if (!editor.SelectedNodeIndices.contains(node_idx))\n    {\n        editor.SelectedLinkIndices.clear();\n        if (!GImNodes->MultipleSelectModifier)\n        {\n            editor.SelectedNodeIndices.clear();\n        }\n        editor.SelectedNodeIndices.push_back(node_idx);\n\n        // Ensure that individually selected nodes get rendered on top\n        ImVector<int>&   depth_stack = editor.NodeDepthOrder;\n        const int* const elem = depth_stack.find(node_idx);\n        IM_ASSERT(elem != depth_stack.end());\n        depth_stack.erase(elem);\n        depth_stack.push_back(node_idx);\n    }\n    // Deselect a previously-selected node\n    else if (GImNodes->MultipleSelectModifier)\n    {\n        const int* const node_ptr = editor.SelectedNodeIndices.find(node_idx);\n        editor.SelectedNodeIndices.erase(node_ptr);\n\n        // Don't allow dragging after deselecting\n        editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n    }\n\n    // To support snapping of multiple nodes, we need to store the offset of\n    // each node in the selection to the origin of the dragged node.\n    const ImVec2 ref_origin = editor.Nodes.Pool[node_idx].Origin;\n    editor.PrimaryNodeOffset =\n        ref_origin + GImNodes->CanvasOriginScreenSpace + editor.Panning - GImNodes->MousePos;\n\n    editor.SelectedNodeOffsets.clear();\n    for (int idx = 0; idx < editor.SelectedNodeIndices.Size; idx++)\n    {\n        const int    node = editor.SelectedNodeIndices[idx];\n        const ImVec2 node_origin = editor.Nodes.Pool[node].Origin - ref_origin;\n        editor.SelectedNodeOffsets.push_back(node_origin);\n    }\n}\n\nvoid BeginLinkSelection(ImNodesEditorContext& editor, const int link_idx)\n{\n    editor.ClickInteraction.Type = ImNodesClickInteractionType_Link;\n    // When a link is selected, clear all other selections, and insert the link\n    // as the sole selection.\n    editor.SelectedNodeIndices.clear();\n    editor.SelectedLinkIndices.clear();\n    editor.SelectedLinkIndices.push_back(link_idx);\n}\n\nvoid BeginLinkDetach(ImNodesEditorContext& editor, const int link_idx, const int detach_pin_idx)\n{\n    const ImLinkData&        link = editor.Links.Pool[link_idx];\n    ImClickInteractionState& state = editor.ClickInteraction;\n    state.Type = ImNodesClickInteractionType_LinkCreation;\n    state.LinkCreation.EndPinIdx.Reset();\n    state.LinkCreation.StartPinIdx =\n        detach_pin_idx == link.StartPinIdx ? link.EndPinIdx : link.StartPinIdx;\n    GImNodes->DeletedLinkIdx = link_idx;\n}\n\nvoid BeginLinkCreation(ImNodesEditorContext& editor, const int hovered_pin_idx)\n{\n    editor.ClickInteraction.Type = ImNodesClickInteractionType_LinkCreation;\n    editor.ClickInteraction.LinkCreation.StartPinIdx = hovered_pin_idx;\n    editor.ClickInteraction.LinkCreation.EndPinIdx.Reset();\n    editor.ClickInteraction.LinkCreation.Type = ImNodesLinkCreationType_Standard;\n    GImNodes->ImNodesUIState |= ImNodesUIState_LinkStarted;\n}\n\nvoid BeginLinkInteraction(\n    ImNodesEditorContext& editor,\n    const int             link_idx,\n    const ImOptionalIndex pin_idx = ImOptionalIndex())\n{\n    // Check if we are clicking the link with the modifier pressed.\n    // This will in a link detach via clicking.\n\n    const bool modifier_pressed = GImNodes->Io.LinkDetachWithModifierClick.Modifier == NULL\n                                      ? false\n                                      : *GImNodes->Io.LinkDetachWithModifierClick.Modifier;\n\n    if (modifier_pressed)\n    {\n        const ImLinkData& link = editor.Links.Pool[link_idx];\n        const ImPinData&  start_pin = editor.Pins.Pool[link.StartPinIdx];\n        const ImPinData&  end_pin = editor.Pins.Pool[link.EndPinIdx];\n        const ImVec2&     mouse_pos = GImNodes->MousePos;\n        const float       dist_to_start = ImLengthSqr(start_pin.Pos - mouse_pos);\n        const float       dist_to_end = ImLengthSqr(end_pin.Pos - mouse_pos);\n        const int closest_pin_idx = dist_to_start < dist_to_end ? link.StartPinIdx : link.EndPinIdx;\n\n        editor.ClickInteraction.Type = ImNodesClickInteractionType_LinkCreation;\n        BeginLinkDetach(editor, link_idx, closest_pin_idx);\n        editor.ClickInteraction.LinkCreation.Type = ImNodesLinkCreationType_FromDetach;\n    }\n    else\n    {\n        if (pin_idx.HasValue())\n        {\n            const int hovered_pin_flags = editor.Pins.Pool[pin_idx.Value()].Flags;\n\n            // Check the 'click and drag to detach' case.\n            if (hovered_pin_flags & ImNodesAttributeFlags_EnableLinkDetachWithDragClick)\n            {\n                BeginLinkDetach(editor, link_idx, pin_idx.Value());\n                editor.ClickInteraction.LinkCreation.Type = ImNodesLinkCreationType_FromDetach;\n            }\n            else\n            {\n                BeginLinkCreation(editor, pin_idx.Value());\n            }\n        }\n        else\n        {\n            BeginLinkSelection(editor, link_idx);\n        }\n    }\n}\n\nstatic inline bool IsMiniMapHovered();\n\nvoid BeginCanvasInteraction(ImNodesEditorContext& editor)\n{\n    const bool any_ui_element_hovered =\n        GImNodes->HoveredNodeIdx.HasValue() || GImNodes->HoveredLinkIdx.HasValue() ||\n        GImNodes->HoveredPinIdx.HasValue() || ImGui::IsAnyItemHovered();\n\n    const bool mouse_not_in_canvas = !MouseInCanvas();\n\n    if (editor.ClickInteraction.Type != ImNodesClickInteractionType_None ||\n        any_ui_element_hovered || mouse_not_in_canvas)\n    {\n        return;\n    }\n\n    const bool started_panning = GImNodes->AltMouseClicked;\n\n    if (started_panning)\n    {\n        editor.ClickInteraction.Type = ImNodesClickInteractionType_Panning;\n    }\n    else if (GImNodes->LeftMouseClicked)\n    {\n        editor.ClickInteraction.Type = ImNodesClickInteractionType_BoxSelection;\n        editor.ClickInteraction.BoxSelector.Rect.Min =\n            ScreenSpaceToGridSpace(editor, GImNodes->MousePos);\n    }\n}\n\nvoid BoxSelectorUpdateSelection(ImNodesEditorContext& editor, ImRect box_rect)\n{\n    // Invert box selector coordinates as needed\n\n    if (box_rect.Min.x > box_rect.Max.x)\n    {\n        ImSwap(box_rect.Min.x, box_rect.Max.x);\n    }\n\n    if (box_rect.Min.y > box_rect.Max.y)\n    {\n        ImSwap(box_rect.Min.y, box_rect.Max.y);\n    }\n\n    // Update node selection\n\n    editor.SelectedNodeIndices.clear();\n\n    // Test for overlap against node rectangles\n\n    for (int node_idx = 0; node_idx < editor.Nodes.Pool.size(); ++node_idx)\n    {\n        if (editor.Nodes.InUse[node_idx])\n        {\n            ImNodeData& node = editor.Nodes.Pool[node_idx];\n            if (box_rect.Overlaps(node.Rect))\n            {\n                editor.SelectedNodeIndices.push_back(node_idx);\n            }\n        }\n    }\n\n    // Update link selection\n\n    editor.SelectedLinkIndices.clear();\n\n    // Test for overlap against links\n\n    for (int link_idx = 0; link_idx < editor.Links.Pool.size(); ++link_idx)\n    {\n        if (editor.Links.InUse[link_idx])\n        {\n            const ImLinkData& link = editor.Links.Pool[link_idx];\n\n            const ImPinData& pin_start = editor.Pins.Pool[link.StartPinIdx];\n            const ImPinData& pin_end = editor.Pins.Pool[link.EndPinIdx];\n            const ImRect&    node_start_rect = editor.Nodes.Pool[pin_start.ParentNodeIdx].Rect;\n            const ImRect&    node_end_rect = editor.Nodes.Pool[pin_end.ParentNodeIdx].Rect;\n\n            const ImVec2 start = GetScreenSpacePinCoordinates(\n                node_start_rect, pin_start.AttributeRect, pin_start.Type);\n            const ImVec2 end =\n                GetScreenSpacePinCoordinates(node_end_rect, pin_end.AttributeRect, pin_end.Type);\n\n            // Test\n            if (RectangleOverlapsLink(box_rect, start, end, pin_start.Type))\n            {\n                editor.SelectedLinkIndices.push_back(link_idx);\n            }\n        }\n    }\n}\n\nImVec2 SnapOriginToGrid(ImVec2 origin)\n{\n    if (GImNodes->Style.Flags & ImNodesStyleFlags_GridSnapping)\n    {\n        const float spacing = GImNodes->Style.GridSpacing;\n        const float spacing2 = spacing * 0.5f;\n\n        // Snap the origin to the nearest grid point in any direction\n        float modx = fmodf(fabsf(origin.x) + spacing2, spacing) - spacing2;\n        float mody = fmodf(fabsf(origin.y) + spacing2, spacing) - spacing2;\n        origin.x += (origin.x < 0.f) ? modx : -modx;\n        origin.y += (origin.y < 0.f) ? mody : -mody;\n    }\n\n    return origin;\n}\n\nvoid TranslateSelectedNodes(ImNodesEditorContext& editor)\n{\n    if (GImNodes->LeftMouseDragging)\n    {\n        // If we have grid snap enabled, don't start moving nodes until we've moved the mouse\n        // slightly\n        const bool shouldTranslate = (GImNodes->Style.Flags & ImNodesStyleFlags_GridSnapping)\n                                         ? ImGui::GetIO().MouseDragMaxDistanceSqr[0] > 5.0\n                                         : true;\n\n        const ImVec2 origin = SnapOriginToGrid(\n            GImNodes->MousePos - GImNodes->CanvasOriginScreenSpace - editor.Panning +\n            editor.PrimaryNodeOffset);\n        for (int i = 0; i < editor.SelectedNodeIndices.size(); ++i)\n        {\n            const ImVec2 node_rel = editor.SelectedNodeOffsets[i];\n            const int    node_idx = editor.SelectedNodeIndices[i];\n            ImNodeData&  node = editor.Nodes.Pool[node_idx];\n            if (node.Draggable && shouldTranslate)\n            {\n                node.Origin = origin + node_rel + editor.AutoPanningDelta;\n            }\n        }\n    }\n}\n\nstruct LinkPredicate\n{\n    bool operator()(const ImLinkData& lhs, const ImLinkData& rhs) const\n    {\n        // Do a unique compare by sorting the pins' addresses.\n        // This catches duplicate links, whether they are in the\n        // same direction or not.\n        // Sorting by pin index should have the uniqueness guarantees as sorting\n        // by id -- each unique id will get one slot in the link pool array.\n\n        int lhs_start = lhs.StartPinIdx;\n        int lhs_end = lhs.EndPinIdx;\n        int rhs_start = rhs.StartPinIdx;\n        int rhs_end = rhs.EndPinIdx;\n\n        if (lhs_start > lhs_end)\n        {\n            ImSwap(lhs_start, lhs_end);\n        }\n\n        if (rhs_start > rhs_end)\n        {\n            ImSwap(rhs_start, rhs_end);\n        }\n\n        return lhs_start == rhs_start && lhs_end == rhs_end;\n    }\n};\n\nImOptionalIndex FindDuplicateLink(\n    const ImNodesEditorContext& editor,\n    const int                   start_pin_idx,\n    const int                   end_pin_idx)\n{\n    ImLinkData test_link(0);\n    test_link.StartPinIdx = start_pin_idx;\n    test_link.EndPinIdx = end_pin_idx;\n    for (int link_idx = 0; link_idx < editor.Links.Pool.size(); ++link_idx)\n    {\n        const ImLinkData& link = editor.Links.Pool[link_idx];\n        if (LinkPredicate()(test_link, link) && editor.Links.InUse[link_idx])\n        {\n            return ImOptionalIndex(link_idx);\n        }\n    }\n\n    return ImOptionalIndex();\n}\n\nbool ShouldLinkSnapToPin(\n    const ImNodesEditorContext& editor,\n    const ImPinData&            start_pin,\n    const int                   hovered_pin_idx,\n    const ImOptionalIndex       duplicate_link)\n{\n    const ImPinData& end_pin = editor.Pins.Pool[hovered_pin_idx];\n\n    // The end pin must be in a different node\n    if (start_pin.ParentNodeIdx == end_pin.ParentNodeIdx)\n    {\n        return false;\n    }\n\n    // The end pin must be of a different type\n    if (start_pin.Type == end_pin.Type)\n    {\n        return false;\n    }\n\n    // The link to be created must not be a duplicate, unless it is the link which was created on\n    // snap. In that case we want to snap, since we want it to appear visually as if the created\n    // link remains snapped to the pin.\n    if (duplicate_link.HasValue() && !(duplicate_link == GImNodes->SnapLinkIdx))\n    {\n        return false;\n    }\n\n    return true;\n}\n\nvoid ClickInteractionUpdate(ImNodesEditorContext& editor)\n{\n    switch (editor.ClickInteraction.Type)\n    {\n    case ImNodesClickInteractionType_BoxSelection:\n    {\n        editor.ClickInteraction.BoxSelector.Rect.Max =\n            ScreenSpaceToGridSpace(editor, GImNodes->MousePos);\n\n        ImRect box_rect = editor.ClickInteraction.BoxSelector.Rect;\n        box_rect.Min = GridSpaceToScreenSpace(editor, box_rect.Min);\n        box_rect.Max = GridSpaceToScreenSpace(editor, box_rect.Max);\n\n        BoxSelectorUpdateSelection(editor, box_rect);\n\n        const ImU32 box_selector_color = GImNodes->Style.Colors[ImNodesCol_BoxSelector];\n        const ImU32 box_selector_outline = GImNodes->Style.Colors[ImNodesCol_BoxSelectorOutline];\n        GImNodes->CanvasDrawList->AddRectFilled(box_rect.Min, box_rect.Max, box_selector_color);\n        GImNodes->CanvasDrawList->AddRect(box_rect.Min, box_rect.Max, box_selector_outline);\n\n        if (GImNodes->LeftMouseReleased)\n        {\n            ImVector<int>&       depth_stack = editor.NodeDepthOrder;\n            const ImVector<int>& selected_idxs = editor.SelectedNodeIndices;\n\n            // Bump the selected node indices, in order, to the top of the depth stack.\n            // NOTE: this algorithm has worst case time complexity of O(N^2), if the node selection\n            // is ~ N (due to selected_idxs.contains()).\n\n            if ((selected_idxs.Size > 0) && (selected_idxs.Size < depth_stack.Size))\n            {\n                int num_moved = 0; // The number of indices moved. Stop after selected_idxs.Size\n                for (int i = 0; i < depth_stack.Size - selected_idxs.Size; ++i)\n                {\n                    for (int node_idx = depth_stack[i]; selected_idxs.contains(node_idx);\n                         node_idx = depth_stack[i])\n                    {\n                        depth_stack.erase(depth_stack.begin() + static_cast<size_t>(i));\n                        depth_stack.push_back(node_idx);\n                        ++num_moved;\n                    }\n\n                    if (num_moved == selected_idxs.Size)\n                    {\n                        break;\n                    }\n                }\n            }\n\n            editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n        }\n    }\n    break;\n    case ImNodesClickInteractionType_Node:\n    {\n        TranslateSelectedNodes(editor);\n\n        if (GImNodes->LeftMouseReleased)\n        {\n            editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n        }\n    }\n    break;\n    case ImNodesClickInteractionType_Link:\n    {\n        if (GImNodes->LeftMouseReleased)\n        {\n            editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n        }\n    }\n    break;\n    case ImNodesClickInteractionType_LinkCreation:\n    {\n        const ImPinData& start_pin =\n            editor.Pins.Pool[editor.ClickInteraction.LinkCreation.StartPinIdx];\n\n        const ImOptionalIndex maybe_duplicate_link_idx =\n            GImNodes->HoveredPinIdx.HasValue()\n                ? FindDuplicateLink(\n                      editor,\n                      editor.ClickInteraction.LinkCreation.StartPinIdx,\n                      GImNodes->HoveredPinIdx.Value())\n                : ImOptionalIndex();\n\n        const bool should_snap =\n            GImNodes->HoveredPinIdx.HasValue() &&\n            ShouldLinkSnapToPin(\n                editor, start_pin, GImNodes->HoveredPinIdx.Value(), maybe_duplicate_link_idx);\n\n        // If we created on snap and the hovered pin is empty or changed, then we need signal that\n        // the link's state has changed.\n        const bool snapping_pin_changed =\n            editor.ClickInteraction.LinkCreation.EndPinIdx.HasValue() &&\n            !(GImNodes->HoveredPinIdx == editor.ClickInteraction.LinkCreation.EndPinIdx);\n\n        // Detach the link that was created by this link event if it's no longer in snap range\n        if (snapping_pin_changed && GImNodes->SnapLinkIdx.HasValue())\n        {\n            BeginLinkDetach(\n                editor,\n                GImNodes->SnapLinkIdx.Value(),\n                editor.ClickInteraction.LinkCreation.EndPinIdx.Value());\n        }\n\n        const ImVec2 start_pos = GetScreenSpacePinCoordinates(editor, start_pin);\n        // If we are within the hover radius of a receiving pin, snap the link\n        // endpoint to it\n        const ImVec2 end_pos = should_snap\n                                   ? GetScreenSpacePinCoordinates(\n                                         editor, editor.Pins.Pool[GImNodes->HoveredPinIdx.Value()])\n                                   : GImNodes->MousePos;\n\n        const CubicBezier cubic_bezier = GetCubicBezier(\n            start_pos, end_pos, start_pin.Type, GImNodes->Style.LinkLineSegmentsPerLength);\n#if IMGUI_VERSION_NUM < 18000\n        GImNodes->CanvasDrawList->AddBezierCurve(\n#else\n        GImNodes->CanvasDrawList->AddBezierCubic(\n#endif\n            cubic_bezier.P0,\n            cubic_bezier.P1,\n            cubic_bezier.P2,\n            cubic_bezier.P3,\n            GImNodes->Style.Colors[ImNodesCol_Link],\n            GImNodes->Style.LinkThickness,\n            cubic_bezier.NumSegments);\n\n        const bool link_creation_on_snap =\n            GImNodes->HoveredPinIdx.HasValue() &&\n            (editor.Pins.Pool[GImNodes->HoveredPinIdx.Value()].Flags &\n             ImNodesAttributeFlags_EnableLinkCreationOnSnap);\n\n        if (!should_snap)\n        {\n            editor.ClickInteraction.LinkCreation.EndPinIdx.Reset();\n        }\n\n        const bool create_link =\n            should_snap && (GImNodes->LeftMouseReleased || link_creation_on_snap);\n\n        if (create_link && !maybe_duplicate_link_idx.HasValue())\n        {\n            // Avoid send OnLinkCreated() events every frame if the snap link is not saved\n            // (only applies for EnableLinkCreationOnSnap)\n            if (!GImNodes->LeftMouseReleased &&\n                editor.ClickInteraction.LinkCreation.EndPinIdx == GImNodes->HoveredPinIdx)\n            {\n                break;\n            }\n\n            GImNodes->ImNodesUIState |= ImNodesUIState_LinkCreated;\n            editor.ClickInteraction.LinkCreation.EndPinIdx = GImNodes->HoveredPinIdx.Value();\n        }\n\n        if (GImNodes->LeftMouseReleased)\n        {\n            editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n            if (!create_link)\n            {\n                GImNodes->ImNodesUIState |= ImNodesUIState_LinkDropped;\n            }\n        }\n    }\n    break;\n    case ImNodesClickInteractionType_Panning:\n    {\n        const bool dragging = GImNodes->AltMouseDragging;\n\n        if (dragging)\n        {\n            editor.Panning += ImGui::GetIO().MouseDelta;\n        }\n        else\n        {\n            editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n        }\n    }\n    break;\n    case ImNodesClickInteractionType_ImGuiItem:\n    {\n        if (GImNodes->LeftMouseReleased)\n        {\n            editor.ClickInteraction.Type = ImNodesClickInteractionType_None;\n        }\n    }\n    case ImNodesClickInteractionType_None:\n        break;\n    default:\n        IM_ASSERT(!\"Unreachable code!\");\n        break;\n    }\n}\n\nvoid ResolveOccludedPins(const ImNodesEditorContext& editor, ImVector<int>& occluded_pin_indices)\n{\n    const ImVector<int>& depth_stack = editor.NodeDepthOrder;\n\n    occluded_pin_indices.resize(0);\n\n    if (depth_stack.Size < 2)\n    {\n        return;\n    }\n\n    // For each node in the depth stack\n    for (int depth_idx = 0; depth_idx < (depth_stack.Size - 1); ++depth_idx)\n    {\n        const ImNodeData& node_below = editor.Nodes.Pool[depth_stack[depth_idx]];\n\n        // Iterate over the rest of the depth stack to find nodes overlapping the pins\n        for (int next_depth_idx = depth_idx + 1; next_depth_idx < depth_stack.Size;\n             ++next_depth_idx)\n        {\n            const ImRect& rect_above = editor.Nodes.Pool[depth_stack[next_depth_idx]].Rect;\n\n            // Iterate over each pin\n            for (int idx = 0; idx < node_below.PinIndices.Size; ++idx)\n            {\n                const int     pin_idx = node_below.PinIndices[idx];\n                const ImVec2& pin_pos = editor.Pins.Pool[pin_idx].Pos;\n\n                if (rect_above.Contains(pin_pos))\n                {\n                    occluded_pin_indices.push_back(pin_idx);\n                }\n            }\n        }\n    }\n}\n\nImOptionalIndex ResolveHoveredPin(\n    const ImObjectPool<ImPinData>& pins,\n    const ImVector<int>&           occluded_pin_indices)\n{\n    float           smallest_distance = FLT_MAX;\n    ImOptionalIndex pin_idx_with_smallest_distance;\n\n    const float hover_radius_sqr = GImNodes->Style.PinHoverRadius * GImNodes->Style.PinHoverRadius;\n\n    for (int idx = 0; idx < pins.Pool.Size; ++idx)\n    {\n        if (!pins.InUse[idx])\n        {\n            continue;\n        }\n\n        if (occluded_pin_indices.contains(idx))\n        {\n            continue;\n        }\n\n        const ImVec2& pin_pos = pins.Pool[idx].Pos;\n        const float   distance_sqr = ImLengthSqr(pin_pos - GImNodes->MousePos);\n\n        // TODO: GImNodes->Style.PinHoverRadius needs to be copied into pin data and the pin-local\n        // value used here. This is no longer called in BeginAttribute/EndAttribute scope and the\n        // detected pin might have a different hover radius than what the user had when calling\n        // BeginAttribute/EndAttribute.\n        if (distance_sqr < hover_radius_sqr && distance_sqr < smallest_distance)\n        {\n            smallest_distance = distance_sqr;\n            pin_idx_with_smallest_distance = idx;\n        }\n    }\n\n    return pin_idx_with_smallest_distance;\n}\n\nImOptionalIndex ResolveHoveredNode(const ImVector<int>& depth_stack)\n{\n    if (GImNodes->NodeIndicesOverlappingWithMouse.size() == 0)\n    {\n        return ImOptionalIndex();\n    }\n\n    if (GImNodes->NodeIndicesOverlappingWithMouse.size() == 1)\n    {\n        return ImOptionalIndex(GImNodes->NodeIndicesOverlappingWithMouse[0]);\n    }\n\n    int largest_depth_idx = -1;\n    int node_idx_on_top = -1;\n\n    for (int i = 0; i < GImNodes->NodeIndicesOverlappingWithMouse.size(); ++i)\n    {\n        const int node_idx = GImNodes->NodeIndicesOverlappingWithMouse[i];\n        for (int depth_idx = 0; depth_idx < depth_stack.size(); ++depth_idx)\n        {\n            if (depth_stack[depth_idx] == node_idx && (depth_idx > largest_depth_idx))\n            {\n                largest_depth_idx = depth_idx;\n                node_idx_on_top = node_idx;\n            }\n        }\n    }\n\n    IM_ASSERT(node_idx_on_top != -1);\n    return ImOptionalIndex(node_idx_on_top);\n}\n\nImOptionalIndex ResolveHoveredLink(\n    const ImObjectPool<ImLinkData>& links,\n    const ImObjectPool<ImPinData>&  pins)\n{\n    float           smallest_distance = FLT_MAX;\n    ImOptionalIndex link_idx_with_smallest_distance;\n\n    // There are two ways a link can be detected as \"hovered\".\n    // 1. The link is within hover distance to the mouse. The closest such link is selected as being\n    // hovered over.\n    // 2. If the link is connected to the currently hovered pin.\n    //\n    // The latter is a requirement for link detaching with drag click to work, as both a link and\n    // pin are required to be hovered over for the feature to work.\n\n    for (int idx = 0; idx < links.Pool.Size; ++idx)\n    {\n        if (!links.InUse[idx])\n        {\n            continue;\n        }\n\n        const ImLinkData& link = links.Pool[idx];\n        const ImPinData&  start_pin = pins.Pool[link.StartPinIdx];\n        const ImPinData&  end_pin = pins.Pool[link.EndPinIdx];\n\n        // If there is a hovered pin links can only be considered hovered if they use that pin\n        if (GImNodes->HoveredPinIdx.HasValue())\n        {\n            if (GImNodes->HoveredPinIdx == link.StartPinIdx ||\n                GImNodes->HoveredPinIdx == link.EndPinIdx)\n            {\n                return idx;\n            }\n            continue;\n        }\n\n        // TODO: the calculated CubicBeziers could be cached since we generate them again when\n        // rendering the links\n\n        const CubicBezier cubic_bezier = GetCubicBezier(\n            start_pin.Pos, end_pin.Pos, start_pin.Type, GImNodes->Style.LinkLineSegmentsPerLength);\n\n        // The distance test\n        {\n            const ImRect link_rect = GetContainingRectForCubicBezier(cubic_bezier);\n\n            // First, do a simple bounding box test against the box containing the link\n            // to see whether calculating the distance to the link is worth doing.\n            if (link_rect.Contains(GImNodes->MousePos))\n            {\n                const float distance = GetDistanceToCubicBezier(\n                    GImNodes->MousePos, cubic_bezier, cubic_bezier.NumSegments);\n\n                // TODO: GImNodes->Style.LinkHoverDistance could be also copied into ImLinkData,\n                // since we're not calling this function in the same scope as ImNodes::Link(). The\n                // rendered/detected link might have a different hover distance than what the user\n                // had specified when calling Link()\n                if (distance < GImNodes->Style.LinkHoverDistance && distance < smallest_distance)\n                {\n                    smallest_distance = distance;\n                    link_idx_with_smallest_distance = idx;\n                }\n            }\n        }\n    }\n\n    return link_idx_with_smallest_distance;\n}\n\n// [SECTION] render helpers\n\ninline ImRect GetItemRect() { return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); }\n\ninline ImVec2 GetNodeTitleBarOrigin(const ImNodeData& node)\n{\n    return node.Origin + node.LayoutStyle.Padding;\n}\n\ninline ImVec2 GetNodeContentOrigin(const ImNodeData& node)\n{\n    const ImVec2 title_bar_height =\n        ImVec2(0.f, node.TitleBarContentRect.GetHeight() + 2.0f * node.LayoutStyle.Padding.y);\n    return node.Origin + title_bar_height + node.LayoutStyle.Padding;\n}\n\ninline ImRect GetNodeTitleRect(const ImNodeData& node)\n{\n    ImRect expanded_title_rect = node.TitleBarContentRect;\n    expanded_title_rect.Expand(node.LayoutStyle.Padding);\n\n    return ImRect(\n        expanded_title_rect.Min,\n        expanded_title_rect.Min + ImVec2(node.Rect.GetWidth(), 0.f) +\n            ImVec2(0.f, expanded_title_rect.GetHeight()));\n}\n\nvoid DrawGrid(ImNodesEditorContext& editor, const ImVec2& canvas_size)\n{\n    const ImVec2 offset = editor.Panning;\n    ImU32        line_color = GImNodes->Style.Colors[ImNodesCol_GridLine];\n    ImU32        line_color_prim = GImNodes->Style.Colors[ImNodesCol_GridLinePrimary];\n    bool         draw_primary = GImNodes->Style.Flags & ImNodesStyleFlags_GridLinesPrimary;\n\n    for (float x = fmodf(offset.x, GImNodes->Style.GridSpacing); x < canvas_size.x;\n         x += GImNodes->Style.GridSpacing)\n    {\n        GImNodes->CanvasDrawList->AddLine(\n            EditorSpaceToScreenSpace(ImVec2(x, 0.0f)),\n            EditorSpaceToScreenSpace(ImVec2(x, canvas_size.y)),\n            offset.x - x == 0.f && draw_primary ? line_color_prim : line_color);\n    }\n\n    for (float y = fmodf(offset.y, GImNodes->Style.GridSpacing); y < canvas_size.y;\n         y += GImNodes->Style.GridSpacing)\n    {\n        GImNodes->CanvasDrawList->AddLine(\n            EditorSpaceToScreenSpace(ImVec2(0.0f, y)),\n            EditorSpaceToScreenSpace(ImVec2(canvas_size.x, y)),\n            offset.y - y == 0.f && draw_primary ? line_color_prim : line_color);\n    }\n}\n\nstruct QuadOffsets\n{\n    ImVec2 TopLeft, BottomLeft, BottomRight, TopRight;\n};\n\nQuadOffsets CalculateQuadOffsets(const float side_length)\n{\n    const float half_side = 0.5f * side_length;\n\n    QuadOffsets offset;\n\n    offset.TopLeft = ImVec2(-half_side, half_side);\n    offset.BottomLeft = ImVec2(-half_side, -half_side);\n    offset.BottomRight = ImVec2(half_side, -half_side);\n    offset.TopRight = ImVec2(half_side, half_side);\n\n    return offset;\n}\n\nstruct TriangleOffsets\n{\n    ImVec2 TopLeft, BottomLeft, Right;\n};\n\nTriangleOffsets CalculateTriangleOffsets(const float side_length)\n{\n    // Calculates the Vec2 offsets from an equilateral triangle's midpoint to\n    // its vertices. Here is how the left_offset and right_offset are\n    // calculated.\n    //\n    // For an equilateral triangle of side length s, the\n    // triangle's height, h, is h = s * sqrt(3) / 2.\n    //\n    // The length from the base to the midpoint is (1 / 3) * h. The length from\n    // the midpoint to the triangle vertex is (2 / 3) * h.\n    const float sqrt_3 = sqrtf(3.0f);\n    const float left_offset = -0.1666666666667f * sqrt_3 * side_length;\n    const float right_offset = 0.333333333333f * sqrt_3 * side_length;\n    const float vertical_offset = 0.5f * side_length;\n\n    TriangleOffsets offset;\n    offset.TopLeft = ImVec2(left_offset, vertical_offset);\n    offset.BottomLeft = ImVec2(left_offset, -vertical_offset);\n    offset.Right = ImVec2(right_offset, 0.f);\n\n    return offset;\n}\n\nvoid DrawPinShape(const ImVec2& pin_pos, const ImPinData& pin, const ImU32 pin_color)\n{\n    static const int CIRCLE_NUM_SEGMENTS = 8;\n\n    switch (pin.Shape)\n    {\n    case ImNodesPinShape_Circle:\n    {\n        GImNodes->CanvasDrawList->AddCircle(\n            pin_pos,\n            GImNodes->Style.PinCircleRadius,\n            pin_color,\n            CIRCLE_NUM_SEGMENTS,\n            GImNodes->Style.PinLineThickness);\n    }\n    break;\n    case ImNodesPinShape_CircleFilled:\n    {\n        GImNodes->CanvasDrawList->AddCircleFilled(\n            pin_pos, GImNodes->Style.PinCircleRadius, pin_color, CIRCLE_NUM_SEGMENTS);\n    }\n    break;\n    case ImNodesPinShape_Quad:\n    {\n        const QuadOffsets offset = CalculateQuadOffsets(GImNodes->Style.PinQuadSideLength);\n        GImNodes->CanvasDrawList->AddQuad(\n            pin_pos + offset.TopLeft,\n            pin_pos + offset.BottomLeft,\n            pin_pos + offset.BottomRight,\n            pin_pos + offset.TopRight,\n            pin_color,\n            GImNodes->Style.PinLineThickness);\n    }\n    break;\n    case ImNodesPinShape_QuadFilled:\n    {\n        const QuadOffsets offset = CalculateQuadOffsets(GImNodes->Style.PinQuadSideLength);\n        GImNodes->CanvasDrawList->AddQuadFilled(\n            pin_pos + offset.TopLeft,\n            pin_pos + offset.BottomLeft,\n            pin_pos + offset.BottomRight,\n            pin_pos + offset.TopRight,\n            pin_color);\n    }\n    break;\n    case ImNodesPinShape_Triangle:\n    {\n        const TriangleOffsets offset =\n            CalculateTriangleOffsets(GImNodes->Style.PinTriangleSideLength);\n        GImNodes->CanvasDrawList->AddTriangle(\n            pin_pos + offset.TopLeft,\n            pin_pos + offset.BottomLeft,\n            pin_pos + offset.Right,\n            pin_color,\n            // NOTE: for some weird reason, the line drawn by AddTriangle is\n            // much thinner than the lines drawn by AddCircle or AddQuad.\n            // Multiplying the line thickness by two seemed to solve the\n            // problem at a few different thickness values.\n            2.f * GImNodes->Style.PinLineThickness);\n    }\n    break;\n    case ImNodesPinShape_TriangleFilled:\n    {\n        const TriangleOffsets offset =\n            CalculateTriangleOffsets(GImNodes->Style.PinTriangleSideLength);\n        GImNodes->CanvasDrawList->AddTriangleFilled(\n            pin_pos + offset.TopLeft,\n            pin_pos + offset.BottomLeft,\n            pin_pos + offset.Right,\n            pin_color);\n    }\n    break;\n    default:\n        IM_ASSERT(!\"Invalid PinShape value!\");\n        break;\n    }\n}\n\nvoid DrawPin(ImNodesEditorContext& editor, const int pin_idx)\n{\n    ImPinData&    pin = editor.Pins.Pool[pin_idx];\n    const ImRect& parent_node_rect = editor.Nodes.Pool[pin.ParentNodeIdx].Rect;\n\n    pin.Pos = GetScreenSpacePinCoordinates(parent_node_rect, pin.AttributeRect, pin.Type);\n\n    ImU32 pin_color = pin.ColorStyle.Background;\n\n    if (GImNodes->HoveredPinIdx == pin_idx)\n    {\n        pin_color = pin.ColorStyle.Hovered;\n    }\n\n    DrawPinShape(pin.Pos, pin, pin_color);\n}\n\nvoid DrawNode(ImNodesEditorContext& editor, const int node_idx)\n{\n    const ImNodeData& node = editor.Nodes.Pool[node_idx];\n    ImGui::SetCursorPos(node.Origin + editor.Panning);\n\n    const bool node_hovered =\n        GImNodes->HoveredNodeIdx == node_idx &&\n        editor.ClickInteraction.Type != ImNodesClickInteractionType_BoxSelection;\n\n    ImU32 node_background = node.ColorStyle.Background;\n    ImU32 titlebar_background = node.ColorStyle.Titlebar;\n\n    if (editor.SelectedNodeIndices.contains(node_idx))\n    {\n        node_background = node.ColorStyle.BackgroundSelected;\n        titlebar_background = node.ColorStyle.TitlebarSelected;\n    }\n    else if (node_hovered)\n    {\n        node_background = node.ColorStyle.BackgroundHovered;\n        titlebar_background = node.ColorStyle.TitlebarHovered;\n    }\n\n    {\n        // node base\n        GImNodes->CanvasDrawList->AddRectFilled(\n            node.Rect.Min, node.Rect.Max, node_background, node.LayoutStyle.CornerRounding);\n\n        // title bar:\n        if (node.TitleBarContentRect.GetHeight() > 0.f)\n        {\n            ImRect title_bar_rect = GetNodeTitleRect(node);\n\n#if IMGUI_VERSION_NUM < 18200\n            GImNodes->CanvasDrawList->AddRectFilled(\n                title_bar_rect.Min,\n                title_bar_rect.Max,\n                titlebar_background,\n                node.LayoutStyle.CornerRounding,\n                ImDrawCornerFlags_Top);\n#else\n            GImNodes->CanvasDrawList->AddRectFilled(\n                title_bar_rect.Min,\n                title_bar_rect.Max,\n                titlebar_background,\n                node.LayoutStyle.CornerRounding,\n                ImDrawFlags_RoundCornersTop);\n\n#endif\n        }\n\n        if ((GImNodes->Style.Flags & ImNodesStyleFlags_NodeOutline) != 0)\n        {\n#if IMGUI_VERSION_NUM < 18200\n            GImNodes->CanvasDrawList->AddRect(\n                node.Rect.Min,\n                node.Rect.Max,\n                node.ColorStyle.Outline,\n                node.LayoutStyle.CornerRounding,\n                ImDrawCornerFlags_All,\n                node.LayoutStyle.BorderThickness);\n#else\n            GImNodes->CanvasDrawList->AddRect(\n                node.Rect.Min,\n                node.Rect.Max,\n                node.ColorStyle.Outline,\n                node.LayoutStyle.CornerRounding,\n                ImDrawFlags_RoundCornersAll,\n                node.LayoutStyle.BorderThickness);\n#endif\n        }\n    }\n\n    for (int i = 0; i < node.PinIndices.size(); ++i)\n    {\n        DrawPin(editor, node.PinIndices[i]);\n    }\n\n    if (node_hovered)\n    {\n        GImNodes->HoveredNodeIdx = node_idx;\n    }\n}\n\nvoid DrawLink(ImNodesEditorContext& editor, const int link_idx)\n{\n    const ImLinkData& link = editor.Links.Pool[link_idx];\n    const ImPinData&  start_pin = editor.Pins.Pool[link.StartPinIdx];\n    const ImPinData&  end_pin = editor.Pins.Pool[link.EndPinIdx];\n\n    const CubicBezier cubic_bezier = GetCubicBezier(\n        start_pin.Pos, end_pin.Pos, start_pin.Type, GImNodes->Style.LinkLineSegmentsPerLength);\n\n    const bool link_hovered =\n        GImNodes->HoveredLinkIdx == link_idx &&\n        editor.ClickInteraction.Type != ImNodesClickInteractionType_BoxSelection;\n\n    if (link_hovered)\n    {\n        GImNodes->HoveredLinkIdx = link_idx;\n    }\n\n    // It's possible for a link to be deleted in begin_link_interaction. A user\n    // may detach a link, resulting in the link wire snapping to the mouse\n    // position.\n    //\n    // In other words, skip rendering the link if it was deleted.\n    if (GImNodes->DeletedLinkIdx == link_idx)\n    {\n        return;\n    }\n\n    ImU32 link_color = link.ColorStyle.Base;\n    if (editor.SelectedLinkIndices.contains(link_idx))\n    {\n        link_color = link.ColorStyle.Selected;\n    }\n    else if (link_hovered)\n    {\n        link_color = link.ColorStyle.Hovered;\n    }\n\n#if IMGUI_VERSION_NUM < 18000\n    GImNodes->CanvasDrawList->AddBezierCurve(\n#else\n    GImNodes->CanvasDrawList->AddBezierCubic(\n#endif\n        cubic_bezier.P0,\n        cubic_bezier.P1,\n        cubic_bezier.P2,\n        cubic_bezier.P3,\n        link_color,\n        GImNodes->Style.LinkThickness,\n        cubic_bezier.NumSegments);\n}\n\nvoid BeginPinAttribute(\n    const int                  id,\n    const ImNodesAttributeType type,\n    const ImNodesPinShape      shape,\n    const int                  node_idx)\n{\n    // Make sure to call BeginNode() before calling\n    // BeginAttribute()\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Node);\n    GImNodes->CurrentScope = ImNodesScope_Attribute;\n\n    ImGui::BeginGroup();\n    ImGui::PushID(id);\n\n    ImNodesEditorContext& editor = EditorContextGet();\n\n    GImNodes->CurrentAttributeId = id;\n\n    const int pin_idx = ObjectPoolFindOrCreateIndex(editor.Pins, id);\n    GImNodes->CurrentPinIdx = pin_idx;\n    ImPinData& pin = editor.Pins.Pool[pin_idx];\n    pin.Id = id;\n    pin.ParentNodeIdx = node_idx;\n    pin.Type = type;\n    pin.Shape = shape;\n    pin.Flags = GImNodes->CurrentAttributeFlags;\n    pin.ColorStyle.Background = GImNodes->Style.Colors[ImNodesCol_Pin];\n    pin.ColorStyle.Hovered = GImNodes->Style.Colors[ImNodesCol_PinHovered];\n}\n\nvoid EndPinAttribute()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Attribute);\n    GImNodes->CurrentScope = ImNodesScope_Node;\n\n    ImGui::PopID();\n    ImGui::EndGroup();\n\n    if (ImGui::IsItemActive())\n    {\n        GImNodes->ActiveAttribute = true;\n        GImNodes->ActiveAttributeId = GImNodes->CurrentAttributeId;\n    }\n\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImPinData&            pin = editor.Pins.Pool[GImNodes->CurrentPinIdx];\n    ImNodeData&           node = editor.Nodes.Pool[GImNodes->CurrentNodeIdx];\n    pin.AttributeRect = GetItemRect();\n    node.PinIndices.push_back(GImNodes->CurrentPinIdx);\n}\n\nvoid Initialize(ImNodesContext* context)\n{\n    context->CanvasOriginScreenSpace = ImVec2(0.0f, 0.0f);\n    context->CanvasRectScreenSpace = ImRect(ImVec2(0.f, 0.f), ImVec2(0.f, 0.f));\n    context->CurrentScope = ImNodesScope_None;\n\n    context->CurrentPinIdx = INT_MAX;\n    context->CurrentNodeIdx = INT_MAX;\n\n    context->DefaultEditorCtx = EditorContextCreate();\n    context->EditorCtx = context->DefaultEditorCtx;\n\n    context->CurrentAttributeFlags = ImNodesAttributeFlags_None;\n    context->AttributeFlagStack.push_back(GImNodes->CurrentAttributeFlags);\n\n    StyleColorsDark(&context->Style);\n}\n\nvoid Shutdown(ImNodesContext* ctx) { EditorContextFree(ctx->DefaultEditorCtx); }\n\n// [SECTION] minimap\n\nstatic inline bool IsMiniMapActive()\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    return editor.MiniMapEnabled && editor.MiniMapSizeFraction > 0.0f;\n}\n\nstatic inline bool IsMiniMapHovered()\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    return IsMiniMapActive() &&\n           ImGui::IsMouseHoveringRect(\n               editor.MiniMapRectScreenSpace.Min, editor.MiniMapRectScreenSpace.Max);\n}\n\nstatic inline void CalcMiniMapLayout()\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    const ImVec2          offset = GImNodes->Style.MiniMapOffset;\n    const ImVec2          border = GImNodes->Style.MiniMapPadding;\n    const ImRect          editor_rect = GImNodes->CanvasRectScreenSpace;\n\n    // Compute the size of the mini-map area\n    ImVec2 mini_map_size;\n    float  mini_map_scaling;\n    {\n        const ImVec2 max_size =\n            ImFloor(editor_rect.GetSize() * editor.MiniMapSizeFraction - border * 2.0f);\n        const float  max_size_aspect_ratio = max_size.x / max_size.y;\n        const ImVec2 grid_content_size = editor.GridContentBounds.IsInverted()\n                                             ? max_size\n                                             : ImFloor(editor.GridContentBounds.GetSize());\n        const float grid_content_aspect_ratio = grid_content_size.x / grid_content_size.y;\n        mini_map_size = ImFloor(\n            grid_content_aspect_ratio > max_size_aspect_ratio\n                ? ImVec2(max_size.x, max_size.x / grid_content_aspect_ratio)\n                : ImVec2(max_size.y * grid_content_aspect_ratio, max_size.y));\n        mini_map_scaling = mini_map_size.x / grid_content_size.x;\n    }\n\n    // Compute location of the mini-map\n    ImVec2 mini_map_pos;\n    {\n        ImVec2 align;\n\n        switch (editor.MiniMapLocation)\n        {\n        case ImNodesMiniMapLocation_BottomRight:\n            align.x = 1.0f;\n            align.y = 1.0f;\n            break;\n        case ImNodesMiniMapLocation_BottomLeft:\n            align.x = 0.0f;\n            align.y = 1.0f;\n            break;\n        case ImNodesMiniMapLocation_TopRight:\n            align.x = 1.0f;\n            align.y = 0.0f;\n            break;\n        case ImNodesMiniMapLocation_TopLeft: // [[fallthrough]]\n        default:\n            align.x = 0.0f;\n            align.y = 0.0f;\n            break;\n        }\n\n        const ImVec2 top_left_pos = editor_rect.Min + offset + border;\n        const ImVec2 bottom_right_pos = editor_rect.Max - offset - border - mini_map_size;\n        mini_map_pos = ImFloor(ImLerp(top_left_pos, bottom_right_pos, align));\n    }\n\n    editor.MiniMapRectScreenSpace =\n        ImRect(mini_map_pos - border, mini_map_pos + mini_map_size + border);\n    editor.MiniMapContentScreenSpace = ImRect(mini_map_pos, mini_map_pos + mini_map_size);\n    editor.MiniMapScaling = mini_map_scaling;\n}\n\nstatic void MiniMapDrawNode(ImNodesEditorContext& editor, const int node_idx)\n{\n    const ImNodeData& node = editor.Nodes.Pool[node_idx];\n\n    const ImRect node_rect = ScreenSpaceToMiniMapSpace(editor, node.Rect);\n\n    // Round to near whole pixel value for corner-rounding to prevent visual glitches\n    const float mini_map_node_rounding =\n        floorf(node.LayoutStyle.CornerRounding * editor.MiniMapScaling);\n\n    ImU32 mini_map_node_background;\n\n    if (editor.ClickInteraction.Type == ImNodesClickInteractionType_None &&\n        ImGui::IsMouseHoveringRect(node_rect.Min, node_rect.Max))\n    {\n        mini_map_node_background = GImNodes->Style.Colors[ImNodesCol_MiniMapNodeBackgroundHovered];\n\n        // Run user callback when hovering a mini-map node\n        if (editor.MiniMapNodeHoveringCallback)\n        {\n            editor.MiniMapNodeHoveringCallback(node.Id, editor.MiniMapNodeHoveringCallbackUserData);\n        }\n    }\n    else if (editor.SelectedNodeIndices.contains(node_idx))\n    {\n        mini_map_node_background = GImNodes->Style.Colors[ImNodesCol_MiniMapNodeBackgroundSelected];\n    }\n    else\n    {\n        mini_map_node_background = GImNodes->Style.Colors[ImNodesCol_MiniMapNodeBackground];\n    }\n\n    const ImU32 mini_map_node_outline = GImNodes->Style.Colors[ImNodesCol_MiniMapNodeOutline];\n\n    GImNodes->CanvasDrawList->AddRectFilled(\n        node_rect.Min, node_rect.Max, mini_map_node_background, mini_map_node_rounding);\n\n    GImNodes->CanvasDrawList->AddRect(\n        node_rect.Min, node_rect.Max, mini_map_node_outline, mini_map_node_rounding);\n}\n\nstatic void MiniMapDrawLink(ImNodesEditorContext& editor, const int link_idx)\n{\n    const ImLinkData& link = editor.Links.Pool[link_idx];\n    const ImPinData&  start_pin = editor.Pins.Pool[link.StartPinIdx];\n    const ImPinData&  end_pin = editor.Pins.Pool[link.EndPinIdx];\n\n    const CubicBezier cubic_bezier = GetCubicBezier(\n        ScreenSpaceToMiniMapSpace(editor, start_pin.Pos),\n        ScreenSpaceToMiniMapSpace(editor, end_pin.Pos),\n        start_pin.Type,\n        GImNodes->Style.LinkLineSegmentsPerLength / editor.MiniMapScaling);\n\n    // It's possible for a link to be deleted in begin_link_interaction. A user\n    // may detach a link, resulting in the link wire snapping to the mouse\n    // position.\n    //\n    // In other words, skip rendering the link if it was deleted.\n    if (GImNodes->DeletedLinkIdx == link_idx)\n    {\n        return;\n    }\n\n    const ImU32 link_color =\n        GImNodes->Style.Colors\n            [editor.SelectedLinkIndices.contains(link_idx) ? ImNodesCol_MiniMapLinkSelected\n                                                           : ImNodesCol_MiniMapLink];\n\n#if IMGUI_VERSION_NUM < 18000\n    GImNodes->CanvasDrawList->AddBezierCurve(\n#else\n    GImNodes->CanvasDrawList->AddBezierCubic(\n#endif\n        cubic_bezier.P0,\n        cubic_bezier.P1,\n        cubic_bezier.P2,\n        cubic_bezier.P3,\n        link_color,\n        GImNodes->Style.LinkThickness * editor.MiniMapScaling,\n        cubic_bezier.NumSegments);\n}\n\nstatic void MiniMapUpdate()\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n\n    ImU32 mini_map_background;\n\n    if (IsMiniMapHovered())\n    {\n        mini_map_background = GImNodes->Style.Colors[ImNodesCol_MiniMapBackgroundHovered];\n    }\n    else\n    {\n        mini_map_background = GImNodes->Style.Colors[ImNodesCol_MiniMapBackground];\n    }\n\n    // Create a child window bellow mini-map, so it blocks all mouse interaction on canvas.\n    int flags = ImGuiWindowFlags_NoBackground;\n    ImGui::SetCursorScreenPos(editor.MiniMapRectScreenSpace.Min);\n    ImGui::BeginChild(\"minimap\", editor.MiniMapRectScreenSpace.GetSize(), false, flags);\n\n    const ImRect& mini_map_rect = editor.MiniMapRectScreenSpace;\n\n    // Draw minimap background and border\n    GImNodes->CanvasDrawList->AddRectFilled(\n        mini_map_rect.Min, mini_map_rect.Max, mini_map_background);\n\n    GImNodes->CanvasDrawList->AddRect(\n        mini_map_rect.Min, mini_map_rect.Max, GImNodes->Style.Colors[ImNodesCol_MiniMapOutline]);\n\n    // Clip draw list items to mini-map rect (after drawing background/outline)\n    GImNodes->CanvasDrawList->PushClipRect(\n        mini_map_rect.Min, mini_map_rect.Max, true /* intersect with editor clip-rect */);\n\n    // Draw links first so they appear under nodes, and we can use the same draw channel\n    for (int link_idx = 0; link_idx < editor.Links.Pool.size(); ++link_idx)\n    {\n        if (editor.Links.InUse[link_idx])\n        {\n            MiniMapDrawLink(editor, link_idx);\n        }\n    }\n\n    for (int node_idx = 0; node_idx < editor.Nodes.Pool.size(); ++node_idx)\n    {\n        if (editor.Nodes.InUse[node_idx])\n        {\n            MiniMapDrawNode(editor, node_idx);\n        }\n    }\n\n    // Draw editor canvas rect inside mini-map\n    {\n        const ImU32  canvas_color = GImNodes->Style.Colors[ImNodesCol_MiniMapCanvas];\n        const ImU32  outline_color = GImNodes->Style.Colors[ImNodesCol_MiniMapCanvasOutline];\n        const ImRect rect = ScreenSpaceToMiniMapSpace(editor, GImNodes->CanvasRectScreenSpace);\n\n        GImNodes->CanvasDrawList->AddRectFilled(rect.Min, rect.Max, canvas_color);\n        GImNodes->CanvasDrawList->AddRect(rect.Min, rect.Max, outline_color);\n    }\n\n    // Have to pop mini-map clip rect\n    GImNodes->CanvasDrawList->PopClipRect();\n\n    bool mini_map_is_hovered = ImGui::IsWindowHovered();\n\n    ImGui::EndChild();\n\n    bool center_on_click = mini_map_is_hovered && ImGui::IsMouseDown(ImGuiMouseButton_Left) &&\n                           editor.ClickInteraction.Type == ImNodesClickInteractionType_None &&\n                           !GImNodes->NodeIdxSubmissionOrder.empty();\n    if (center_on_click)\n    {\n        ImVec2 target = MiniMapSpaceToGridSpace(editor, ImGui::GetMousePos());\n        ImVec2 center = GImNodes->CanvasRectScreenSpace.GetSize() * 0.5f;\n        editor.Panning = ImFloor(center - target);\n    }\n\n    // Reset callback info after use\n    editor.MiniMapNodeHoveringCallback = NULL;\n    editor.MiniMapNodeHoveringCallbackUserData = NULL;\n}\n\n// [SECTION] selection helpers\n\ntemplate<typename T>\nvoid SelectObject(const ImObjectPool<T>& objects, ImVector<int>& selected_indices, const int id)\n{\n    const int idx = ObjectPoolFind(objects, id);\n    IM_ASSERT(idx >= 0);\n    IM_ASSERT(selected_indices.find(idx) == selected_indices.end());\n    selected_indices.push_back(idx);\n}\n\ntemplate<typename T>\nvoid ClearObjectSelection(\n    const ImObjectPool<T>& objects,\n    ImVector<int>&         selected_indices,\n    const int              id)\n{\n    const int idx = ObjectPoolFind(objects, id);\n    IM_ASSERT(idx >= 0);\n    IM_ASSERT(selected_indices.find(idx) != selected_indices.end());\n    selected_indices.find_erase_unsorted(idx);\n}\n\ntemplate<typename T>\nbool IsObjectSelected(const ImObjectPool<T>& objects, ImVector<int>& selected_indices, const int id)\n{\n    const int idx = ObjectPoolFind(objects, id);\n    return selected_indices.find(idx) != selected_indices.end();\n}\n\n} // namespace\n} // namespace IMNODES_NAMESPACE\n\n// [SECTION] API implementation\n\nImNodesIO::EmulateThreeButtonMouse::EmulateThreeButtonMouse() : Modifier(NULL) {}\n\nImNodesIO::LinkDetachWithModifierClick::LinkDetachWithModifierClick() : Modifier(NULL) {}\n\nImNodesIO::MultipleSelectModifier::MultipleSelectModifier() : Modifier(NULL) {}\n\nImNodesIO::ImNodesIO()\n    : EmulateThreeButtonMouse(), LinkDetachWithModifierClick(),\n      AltMouseButton(ImGuiMouseButton_Middle), AutoPanningSpeed(1000.0f)\n{\n}\n\nImNodesStyle::ImNodesStyle()\n    : GridSpacing(24.f), NodeCornerRounding(4.f), NodePadding(8.f, 8.f), NodeBorderThickness(1.f),\n      LinkThickness(3.f), LinkLineSegmentsPerLength(0.1f), LinkHoverDistance(10.f),\n      PinCircleRadius(4.f), PinQuadSideLength(7.f), PinTriangleSideLength(9.5),\n      PinLineThickness(1.f), PinHoverRadius(10.f), PinOffset(0.f), MiniMapPadding(8.0f, 8.0f),\n      MiniMapOffset(4.0f, 4.0f), Flags(ImNodesStyleFlags_NodeOutline | ImNodesStyleFlags_GridLines),\n      Colors()\n{\n}\n\nnamespace IMNODES_NAMESPACE\n{\nImNodesContext* CreateContext()\n{\n    ImNodesContext* ctx = IM_NEW(ImNodesContext)();\n    if (GImNodes == NULL)\n        SetCurrentContext(ctx);\n    Initialize(ctx);\n    return ctx;\n}\n\nvoid DestroyContext(ImNodesContext* ctx)\n{\n    if (ctx == NULL)\n        ctx = GImNodes;\n    Shutdown(ctx);\n    if (GImNodes == ctx)\n        SetCurrentContext(NULL);\n    IM_DELETE(ctx);\n}\n\nImNodesContext* GetCurrentContext() { return GImNodes; }\n\nvoid SetCurrentContext(ImNodesContext* ctx) { GImNodes = ctx; }\n\nImNodesEditorContext* EditorContextCreate()\n{\n    void* mem = ImGui::MemAlloc(sizeof(ImNodesEditorContext));\n    new (mem) ImNodesEditorContext();\n    return (ImNodesEditorContext*)mem;\n}\n\nvoid EditorContextFree(ImNodesEditorContext* ctx)\n{\n    ctx->~ImNodesEditorContext();\n    ImGui::MemFree(ctx);\n}\n\nvoid EditorContextSet(ImNodesEditorContext* ctx) { GImNodes->EditorCtx = ctx; }\n\nImVec2 EditorContextGetPanning()\n{\n    const ImNodesEditorContext& editor = EditorContextGet();\n    return editor.Panning;\n}\n\nvoid EditorContextResetPanning(const ImVec2& pos)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    editor.Panning = pos;\n}\n\nvoid EditorContextMoveToNode(const int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = ObjectPoolFindOrCreateObject(editor.Nodes, node_id);\n\n    editor.Panning.x = -node.Origin.x;\n    editor.Panning.y = -node.Origin.y;\n}\n\nvoid SetImGuiContext(ImGuiContext* ctx) { ImGui::SetCurrentContext(ctx); }\n\nImNodesIO& GetIO() { return GImNodes->Io; }\n\nImNodesStyle& GetStyle() { return GImNodes->Style; }\n\nvoid StyleColorsDark(ImNodesStyle* dest)\n{\n    if (dest == nullptr)\n    {\n        dest = &GImNodes->Style;\n    }\n\n    dest->Colors[ImNodesCol_NodeBackground] = IM_COL32(50, 50, 50, 255);\n    dest->Colors[ImNodesCol_NodeBackgroundHovered] = IM_COL32(75, 75, 75, 255);\n    dest->Colors[ImNodesCol_NodeBackgroundSelected] = IM_COL32(75, 75, 75, 255);\n    dest->Colors[ImNodesCol_NodeOutline] = IM_COL32(100, 100, 100, 255);\n    // title bar colors match ImGui's titlebg colors\n    dest->Colors[ImNodesCol_TitleBar] = IM_COL32(41, 74, 122, 255);\n    dest->Colors[ImNodesCol_TitleBarHovered] = IM_COL32(66, 150, 250, 255);\n    dest->Colors[ImNodesCol_TitleBarSelected] = IM_COL32(66, 150, 250, 255);\n    // link colors match ImGui's slider grab colors\n    dest->Colors[ImNodesCol_Link] = IM_COL32(61, 133, 224, 200);\n    dest->Colors[ImNodesCol_LinkHovered] = IM_COL32(66, 150, 250, 255);\n    dest->Colors[ImNodesCol_LinkSelected] = IM_COL32(66, 150, 250, 255);\n    // pin colors match ImGui's button colors\n    dest->Colors[ImNodesCol_Pin] = IM_COL32(53, 150, 250, 180);\n    dest->Colors[ImNodesCol_PinHovered] = IM_COL32(53, 150, 250, 255);\n\n    dest->Colors[ImNodesCol_BoxSelector] = IM_COL32(61, 133, 224, 30);\n    dest->Colors[ImNodesCol_BoxSelectorOutline] = IM_COL32(61, 133, 224, 150);\n\n    dest->Colors[ImNodesCol_GridBackground] = IM_COL32(40, 40, 50, 200);\n    dest->Colors[ImNodesCol_GridLine] = IM_COL32(200, 200, 200, 40);\n    dest->Colors[ImNodesCol_GridLinePrimary] = IM_COL32(240, 240, 240, 60);\n\n    // minimap colors\n    dest->Colors[ImNodesCol_MiniMapBackground] = IM_COL32(25, 25, 25, 150);\n    dest->Colors[ImNodesCol_MiniMapBackgroundHovered] = IM_COL32(25, 25, 25, 200);\n    dest->Colors[ImNodesCol_MiniMapOutline] = IM_COL32(150, 150, 150, 100);\n    dest->Colors[ImNodesCol_MiniMapOutlineHovered] = IM_COL32(150, 150, 150, 200);\n    dest->Colors[ImNodesCol_MiniMapNodeBackground] = IM_COL32(200, 200, 200, 100);\n    dest->Colors[ImNodesCol_MiniMapNodeBackgroundHovered] = IM_COL32(200, 200, 200, 255);\n    dest->Colors[ImNodesCol_MiniMapNodeBackgroundSelected] =\n        dest->Colors[ImNodesCol_MiniMapNodeBackgroundHovered];\n    dest->Colors[ImNodesCol_MiniMapNodeOutline] = IM_COL32(200, 200, 200, 100);\n    dest->Colors[ImNodesCol_MiniMapLink] = dest->Colors[ImNodesCol_Link];\n    dest->Colors[ImNodesCol_MiniMapLinkSelected] = dest->Colors[ImNodesCol_LinkSelected];\n    dest->Colors[ImNodesCol_MiniMapCanvas] = IM_COL32(200, 200, 200, 25);\n    dest->Colors[ImNodesCol_MiniMapCanvasOutline] = IM_COL32(200, 200, 200, 200);\n}\n\nvoid StyleColorsClassic(ImNodesStyle* dest)\n{\n    if (dest == nullptr)\n    {\n        dest = &GImNodes->Style;\n    }\n\n    dest->Colors[ImNodesCol_NodeBackground] = IM_COL32(50, 50, 50, 255);\n    dest->Colors[ImNodesCol_NodeBackgroundHovered] = IM_COL32(75, 75, 75, 255);\n    dest->Colors[ImNodesCol_NodeBackgroundSelected] = IM_COL32(75, 75, 75, 255);\n    dest->Colors[ImNodesCol_NodeOutline] = IM_COL32(100, 100, 100, 255);\n    dest->Colors[ImNodesCol_TitleBar] = IM_COL32(69, 69, 138, 255);\n    dest->Colors[ImNodesCol_TitleBarHovered] = IM_COL32(82, 82, 161, 255);\n    dest->Colors[ImNodesCol_TitleBarSelected] = IM_COL32(82, 82, 161, 255);\n    dest->Colors[ImNodesCol_Link] = IM_COL32(255, 255, 255, 100);\n    dest->Colors[ImNodesCol_LinkHovered] = IM_COL32(105, 99, 204, 153);\n    dest->Colors[ImNodesCol_LinkSelected] = IM_COL32(105, 99, 204, 153);\n    dest->Colors[ImNodesCol_Pin] = IM_COL32(89, 102, 156, 170);\n    dest->Colors[ImNodesCol_PinHovered] = IM_COL32(102, 122, 179, 200);\n    dest->Colors[ImNodesCol_BoxSelector] = IM_COL32(82, 82, 161, 100);\n    dest->Colors[ImNodesCol_BoxSelectorOutline] = IM_COL32(82, 82, 161, 255);\n    dest->Colors[ImNodesCol_GridBackground] = IM_COL32(40, 40, 50, 200);\n    dest->Colors[ImNodesCol_GridLine] = IM_COL32(200, 200, 200, 40);\n    dest->Colors[ImNodesCol_GridLinePrimary] = IM_COL32(240, 240, 240, 60);\n\n    // minimap colors\n    dest->Colors[ImNodesCol_MiniMapBackground] = IM_COL32(25, 25, 25, 100);\n    dest->Colors[ImNodesCol_MiniMapBackgroundHovered] = IM_COL32(25, 25, 25, 200);\n    dest->Colors[ImNodesCol_MiniMapOutline] = IM_COL32(150, 150, 150, 100);\n    dest->Colors[ImNodesCol_MiniMapOutlineHovered] = IM_COL32(150, 150, 150, 200);\n    dest->Colors[ImNodesCol_MiniMapNodeBackground] = IM_COL32(200, 200, 200, 100);\n    dest->Colors[ImNodesCol_MiniMapNodeBackgroundSelected] =\n        dest->Colors[ImNodesCol_MiniMapNodeBackgroundHovered];\n    dest->Colors[ImNodesCol_MiniMapNodeBackgroundSelected] = IM_COL32(200, 200, 240, 255);\n    dest->Colors[ImNodesCol_MiniMapNodeOutline] = IM_COL32(200, 200, 200, 100);\n    dest->Colors[ImNodesCol_MiniMapLink] = dest->Colors[ImNodesCol_Link];\n    dest->Colors[ImNodesCol_MiniMapLinkSelected] = dest->Colors[ImNodesCol_LinkSelected];\n    dest->Colors[ImNodesCol_MiniMapCanvas] = IM_COL32(200, 200, 200, 25);\n    dest->Colors[ImNodesCol_MiniMapCanvasOutline] = IM_COL32(200, 200, 200, 200);\n}\n\nvoid StyleColorsLight(ImNodesStyle* dest)\n{\n    if (dest == nullptr)\n    {\n        dest = &GImNodes->Style;\n    }\n\n    dest->Colors[ImNodesCol_NodeBackground] = IM_COL32(240, 240, 240, 255);\n    dest->Colors[ImNodesCol_NodeBackgroundHovered] = IM_COL32(240, 240, 240, 255);\n    dest->Colors[ImNodesCol_NodeBackgroundSelected] = IM_COL32(240, 240, 240, 255);\n    dest->Colors[ImNodesCol_NodeOutline] = IM_COL32(100, 100, 100, 255);\n    dest->Colors[ImNodesCol_TitleBar] = IM_COL32(248, 248, 248, 255);\n    dest->Colors[ImNodesCol_TitleBarHovered] = IM_COL32(209, 209, 209, 255);\n    dest->Colors[ImNodesCol_TitleBarSelected] = IM_COL32(209, 209, 209, 255);\n    // original imgui values: 66, 150, 250\n    dest->Colors[ImNodesCol_Link] = IM_COL32(66, 150, 250, 100);\n    // original imgui values: 117, 138, 204\n    dest->Colors[ImNodesCol_LinkHovered] = IM_COL32(66, 150, 250, 242);\n    dest->Colors[ImNodesCol_LinkSelected] = IM_COL32(66, 150, 250, 242);\n    // original imgui values: 66, 150, 250\n    dest->Colors[ImNodesCol_Pin] = IM_COL32(66, 150, 250, 160);\n    dest->Colors[ImNodesCol_PinHovered] = IM_COL32(66, 150, 250, 255);\n    dest->Colors[ImNodesCol_BoxSelector] = IM_COL32(90, 170, 250, 30);\n    dest->Colors[ImNodesCol_BoxSelectorOutline] = IM_COL32(90, 170, 250, 150);\n    dest->Colors[ImNodesCol_GridBackground] = IM_COL32(225, 225, 225, 255);\n    dest->Colors[ImNodesCol_GridLine] = IM_COL32(180, 180, 180, 100);\n    dest->Colors[ImNodesCol_GridLinePrimary] = IM_COL32(120, 120, 120, 100);\n\n    // minimap colors\n    dest->Colors[ImNodesCol_MiniMapBackground] = IM_COL32(25, 25, 25, 100);\n    dest->Colors[ImNodesCol_MiniMapBackgroundHovered] = IM_COL32(25, 25, 25, 200);\n    dest->Colors[ImNodesCol_MiniMapOutline] = IM_COL32(150, 150, 150, 100);\n    dest->Colors[ImNodesCol_MiniMapOutlineHovered] = IM_COL32(150, 150, 150, 200);\n    dest->Colors[ImNodesCol_MiniMapNodeBackground] = IM_COL32(200, 200, 200, 100);\n    dest->Colors[ImNodesCol_MiniMapNodeBackgroundSelected] =\n        dest->Colors[ImNodesCol_MiniMapNodeBackgroundHovered];\n    dest->Colors[ImNodesCol_MiniMapNodeBackgroundSelected] = IM_COL32(200, 200, 240, 255);\n    dest->Colors[ImNodesCol_MiniMapNodeOutline] = IM_COL32(200, 200, 200, 100);\n    dest->Colors[ImNodesCol_MiniMapLink] = dest->Colors[ImNodesCol_Link];\n    dest->Colors[ImNodesCol_MiniMapLinkSelected] = dest->Colors[ImNodesCol_LinkSelected];\n    dest->Colors[ImNodesCol_MiniMapCanvas] = IM_COL32(200, 200, 200, 25);\n    dest->Colors[ImNodesCol_MiniMapCanvasOutline] = IM_COL32(200, 200, 200, 200);\n}\n\nvoid BeginNodeEditor()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    GImNodes->CurrentScope = ImNodesScope_Editor;\n\n    // Reset state from previous pass\n\n    ImNodesEditorContext& editor = EditorContextGet();\n    editor.AutoPanningDelta = ImVec2(0, 0);\n    editor.GridContentBounds = ImRect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);\n    editor.MiniMapEnabled = false;\n    ObjectPoolReset(editor.Nodes);\n    ObjectPoolReset(editor.Pins);\n    ObjectPoolReset(editor.Links);\n\n    GImNodes->HoveredNodeIdx.Reset();\n    GImNodes->HoveredLinkIdx.Reset();\n    GImNodes->HoveredPinIdx.Reset();\n    GImNodes->DeletedLinkIdx.Reset();\n    GImNodes->SnapLinkIdx.Reset();\n\n    GImNodes->NodeIndicesOverlappingWithMouse.clear();\n\n    GImNodes->ImNodesUIState = ImNodesUIState_None;\n\n    GImNodes->MousePos = ImGui::GetIO().MousePos;\n    GImNodes->LeftMouseClicked = ImGui::IsMouseClicked(0);\n    GImNodes->LeftMouseReleased = ImGui::IsMouseReleased(0);\n    GImNodes->LeftMouseDragging = ImGui::IsMouseDragging(0, 0.0f);\n    GImNodes->AltMouseClicked =\n        (GImNodes->Io.EmulateThreeButtonMouse.Modifier != NULL &&\n         *GImNodes->Io.EmulateThreeButtonMouse.Modifier && GImNodes->LeftMouseClicked) ||\n        ImGui::IsMouseClicked(GImNodes->Io.AltMouseButton);\n    GImNodes->AltMouseDragging =\n        (GImNodes->Io.EmulateThreeButtonMouse.Modifier != NULL && GImNodes->LeftMouseDragging &&\n         (*GImNodes->Io.EmulateThreeButtonMouse.Modifier)) ||\n        ImGui::IsMouseDragging(GImNodes->Io.AltMouseButton, 0.0f);\n    GImNodes->AltMouseScrollDelta = ImGui::GetIO().MouseWheel;\n    GImNodes->MultipleSelectModifier =\n        (GImNodes->Io.MultipleSelectModifier.Modifier != NULL\n             ? *GImNodes->Io.MultipleSelectModifier.Modifier\n             : ImGui::GetIO().KeyCtrl);\n\n    GImNodes->ActiveAttribute = false;\n\n    ImGui::BeginGroup();\n    {\n        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1.f, 1.f));\n        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 0.f));\n        ImGui::PushStyleColor(ImGuiCol_ChildBg, GImNodes->Style.Colors[ImNodesCol_GridBackground]);\n        ImGui::BeginChild(\n            \"scrolling_region\",\n            ImVec2(0.f, 0.f),\n            true,\n            ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove |\n                ImGuiWindowFlags_NoScrollWithMouse);\n        GImNodes->CanvasOriginScreenSpace = ImGui::GetCursorScreenPos();\n\n        // NOTE: we have to fetch the canvas draw list *after* we call\n        // BeginChild(), otherwise the ImGui UI elements are going to be\n        // rendered into the parent window draw list.\n        DrawListSet(ImGui::GetWindowDrawList());\n\n        {\n            const ImVec2 canvas_size = ImGui::GetWindowSize();\n            GImNodes->CanvasRectScreenSpace = ImRect(\n                EditorSpaceToScreenSpace(ImVec2(0.f, 0.f)), EditorSpaceToScreenSpace(canvas_size));\n\n            if (GImNodes->Style.Flags & ImNodesStyleFlags_GridLines)\n            {\n                DrawGrid(editor, canvas_size);\n            }\n        }\n    }\n}\n\nvoid EndNodeEditor()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Editor);\n    GImNodes->CurrentScope = ImNodesScope_None;\n\n    ImNodesEditorContext& editor = EditorContextGet();\n\n    bool no_grid_content = editor.GridContentBounds.IsInverted();\n    if (no_grid_content)\n    {\n        editor.GridContentBounds = ScreenSpaceToGridSpace(editor, GImNodes->CanvasRectScreenSpace);\n    }\n\n    // Detect ImGui interaction first, because it blocks interaction with the rest of the UI\n\n    if (GImNodes->LeftMouseClicked && ImGui::IsAnyItemActive())\n    {\n        editor.ClickInteraction.Type = ImNodesClickInteractionType_ImGuiItem;\n    }\n\n    // Detect which UI element is being hovered over. Detection is done in a hierarchical fashion,\n    // because a UI element being hovered excludes any other as being hovered over.\n\n    // Don't do hovering detection for nodes/links/pins when interacting with the mini-map, since\n    // its an *overlay* with its own interaction behavior and must have precedence during mouse\n    // interaction.\n\n    if ((editor.ClickInteraction.Type == ImNodesClickInteractionType_None ||\n         editor.ClickInteraction.Type == ImNodesClickInteractionType_LinkCreation) &&\n        MouseInCanvas() && !IsMiniMapHovered())\n    {\n        // Pins needs some special care. We need to check the depth stack to see which pins are\n        // being occluded by other nodes.\n        ResolveOccludedPins(editor, GImNodes->OccludedPinIndices);\n\n        GImNodes->HoveredPinIdx = ResolveHoveredPin(editor.Pins, GImNodes->OccludedPinIndices);\n\n        if (!GImNodes->HoveredPinIdx.HasValue())\n        {\n            // Resolve which node is actually on top and being hovered using the depth stack.\n            GImNodes->HoveredNodeIdx = ResolveHoveredNode(editor.NodeDepthOrder);\n        }\n\n        // We don't check for hovered pins here, because if we want to detach a link by clicking and\n        // dragging, we need to have both a link and pin hovered.\n        if (!GImNodes->HoveredNodeIdx.HasValue())\n        {\n            GImNodes->HoveredLinkIdx = ResolveHoveredLink(editor.Links, editor.Pins);\n        }\n    }\n\n    for (int node_idx = 0; node_idx < editor.Nodes.Pool.size(); ++node_idx)\n    {\n        if (editor.Nodes.InUse[node_idx])\n        {\n            DrawListActivateNodeBackground(node_idx);\n            DrawNode(editor, node_idx);\n        }\n    }\n\n    // In order to render the links underneath the nodes, we want to first select the bottom draw\n    // channel.\n    GImNodes->CanvasDrawList->ChannelsSetCurrent(0);\n\n    for (int link_idx = 0; link_idx < editor.Links.Pool.size(); ++link_idx)\n    {\n        if (editor.Links.InUse[link_idx])\n        {\n            DrawLink(editor, link_idx);\n        }\n    }\n\n    // Render the click interaction UI elements (partial links, box selector) on top of everything\n    // else.\n\n    DrawListAppendClickInteractionChannel();\n    DrawListActivateClickInteractionChannel();\n\n    if (IsMiniMapActive())\n    {\n        CalcMiniMapLayout();\n        MiniMapUpdate();\n    }\n\n    // Handle node graph interaction\n\n    if (!IsMiniMapHovered())\n    {\n        if (GImNodes->LeftMouseClicked && GImNodes->HoveredLinkIdx.HasValue())\n        {\n            BeginLinkInteraction(editor, GImNodes->HoveredLinkIdx.Value(), GImNodes->HoveredPinIdx);\n        }\n\n        else if (GImNodes->LeftMouseClicked && GImNodes->HoveredPinIdx.HasValue())\n        {\n            BeginLinkCreation(editor, GImNodes->HoveredPinIdx.Value());\n        }\n\n        else if (GImNodes->LeftMouseClicked && GImNodes->HoveredNodeIdx.HasValue())\n        {\n            BeginNodeSelection(editor, GImNodes->HoveredNodeIdx.Value());\n        }\n\n        else if (\n            GImNodes->LeftMouseClicked || GImNodes->LeftMouseReleased ||\n            GImNodes->AltMouseClicked || GImNodes->AltMouseScrollDelta != 0.f)\n        {\n            BeginCanvasInteraction(editor);\n        }\n\n        bool should_auto_pan =\n            editor.ClickInteraction.Type == ImNodesClickInteractionType_BoxSelection ||\n            editor.ClickInteraction.Type == ImNodesClickInteractionType_LinkCreation ||\n            editor.ClickInteraction.Type == ImNodesClickInteractionType_Node;\n        if (should_auto_pan && !MouseInCanvas())\n        {\n            ImVec2 mouse = ImGui::GetMousePos();\n            ImVec2 center = GImNodes->CanvasRectScreenSpace.GetCenter();\n            ImVec2 direction = (center - mouse);\n            direction = direction * ImInvLength(direction, 0.0);\n\n            editor.AutoPanningDelta =\n                direction * ImGui::GetIO().DeltaTime * GImNodes->Io.AutoPanningSpeed;\n            editor.Panning += editor.AutoPanningDelta;\n        }\n    }\n    ClickInteractionUpdate(editor);\n\n    // At this point, draw commands have been issued for all nodes (and pins). Update the node pool\n    // to detect unused node slots and remove those indices from the depth stack before sorting the\n    // node draw commands by depth.\n    ObjectPoolUpdate(editor.Nodes);\n    ObjectPoolUpdate(editor.Pins);\n\n    DrawListSortChannelsByDepth(editor.NodeDepthOrder);\n\n    // After the links have been rendered, the link pool can be updated as well.\n    ObjectPoolUpdate(editor.Links);\n\n    // Finally, merge the draw channels\n    GImNodes->CanvasDrawList->ChannelsMerge();\n\n    // pop style\n    ImGui::EndChild();      // end scrolling region\n    ImGui::PopStyleColor(); // pop child window background color\n    ImGui::PopStyleVar();   // pop window padding\n    ImGui::PopStyleVar();   // pop frame padding\n    ImGui::EndGroup();\n}\n\nvoid MiniMap(\n    const float                                      minimap_size_fraction,\n    const ImNodesMiniMapLocation                     location,\n    const ImNodesMiniMapNodeHoveringCallback         node_hovering_callback,\n    const ImNodesMiniMapNodeHoveringCallbackUserData node_hovering_callback_data)\n{\n    // Check that editor size fraction is sane; must be in the range (0, 1]\n    IM_ASSERT(minimap_size_fraction > 0.f && minimap_size_fraction <= 1.f);\n\n    // Remember to call before EndNodeEditor\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Editor);\n\n    ImNodesEditorContext& editor = EditorContextGet();\n\n    editor.MiniMapEnabled = true;\n    editor.MiniMapSizeFraction = minimap_size_fraction;\n    editor.MiniMapLocation = location;\n\n    // Set node hovering callback information\n    editor.MiniMapNodeHoveringCallback = node_hovering_callback;\n    editor.MiniMapNodeHoveringCallbackUserData = node_hovering_callback_data;\n\n    // Actual drawing/updating of the MiniMap is done in EndNodeEditor so that\n    // mini map is draw over everything and all pin/link positions are updated\n    // correctly relative to their respective nodes. Hence, we must store some of\n    // of the state for the mini map in GImNodes for the actual drawing/updating\n}\n\nvoid BeginNode(const int node_id)\n{\n    // Remember to call BeginNodeEditor before calling BeginNode\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Editor);\n    GImNodes->CurrentScope = ImNodesScope_Node;\n\n    ImNodesEditorContext& editor = EditorContextGet();\n\n    const int node_idx = ObjectPoolFindOrCreateIndex(editor.Nodes, node_id);\n    GImNodes->CurrentNodeIdx = node_idx;\n\n    ImNodeData& node = editor.Nodes.Pool[node_idx];\n    node.ColorStyle.Background = GImNodes->Style.Colors[ImNodesCol_NodeBackground];\n    node.ColorStyle.BackgroundHovered = GImNodes->Style.Colors[ImNodesCol_NodeBackgroundHovered];\n    node.ColorStyle.BackgroundSelected = GImNodes->Style.Colors[ImNodesCol_NodeBackgroundSelected];\n    node.ColorStyle.Outline = GImNodes->Style.Colors[ImNodesCol_NodeOutline];\n    node.ColorStyle.Titlebar = GImNodes->Style.Colors[ImNodesCol_TitleBar];\n    node.ColorStyle.TitlebarHovered = GImNodes->Style.Colors[ImNodesCol_TitleBarHovered];\n    node.ColorStyle.TitlebarSelected = GImNodes->Style.Colors[ImNodesCol_TitleBarSelected];\n    node.LayoutStyle.CornerRounding = GImNodes->Style.NodeCornerRounding;\n    node.LayoutStyle.Padding = GImNodes->Style.NodePadding;\n    node.LayoutStyle.BorderThickness = GImNodes->Style.NodeBorderThickness;\n\n    // ImGui::SetCursorPos sets the cursor position, local to the current widget\n    // (in this case, the child object started in BeginNodeEditor). Use\n    // ImGui::SetCursorScreenPos to set the screen space coordinates directly.\n    ImGui::SetCursorPos(GridSpaceToEditorSpace(editor, GetNodeTitleBarOrigin(node)));\n\n    DrawListAddNode(node_idx);\n    DrawListActivateCurrentNodeForeground();\n\n    ImGui::PushID(node.Id);\n    ImGui::BeginGroup();\n}\n\nvoid EndNode()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Node);\n    GImNodes->CurrentScope = ImNodesScope_Editor;\n\n    ImNodesEditorContext& editor = EditorContextGet();\n\n    // The node's rectangle depends on the ImGui UI group size.\n    ImGui::EndGroup();\n    ImGui::PopID();\n\n    ImNodeData& node = editor.Nodes.Pool[GImNodes->CurrentNodeIdx];\n    node.Rect = GetItemRect();\n    node.Rect.Expand(node.LayoutStyle.Padding);\n\n    editor.GridContentBounds.Add(node.Origin);\n    editor.GridContentBounds.Add(node.Origin + node.Rect.GetSize());\n\n    if (node.Rect.Contains(GImNodes->MousePos))\n    {\n        GImNodes->NodeIndicesOverlappingWithMouse.push_back(GImNodes->CurrentNodeIdx);\n    }\n}\n\nImVec2 GetNodeDimensions(int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    const int             node_idx = ObjectPoolFind(editor.Nodes, node_id);\n    IM_ASSERT(node_idx != -1); // invalid node_id\n    const ImNodeData& node = editor.Nodes.Pool[node_idx];\n    return node.Rect.GetSize();\n}\n\nvoid BeginNodeTitleBar()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Node);\n    ImGui::BeginGroup();\n}\n\nvoid EndNodeTitleBar()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Node);\n    ImGui::EndGroup();\n\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = editor.Nodes.Pool[GImNodes->CurrentNodeIdx];\n    node.TitleBarContentRect = GetItemRect();\n\n    ImGui::ItemAdd(GetNodeTitleRect(node), ImGui::GetID(\"title_bar\"));\n\n    ImGui::SetCursorPos(GridSpaceToEditorSpace(editor, GetNodeContentOrigin(node)));\n}\n\nvoid BeginInputAttribute(const int id, const ImNodesPinShape shape)\n{\n    BeginPinAttribute(id, ImNodesAttributeType_Input, shape, GImNodes->CurrentNodeIdx);\n}\n\nvoid EndInputAttribute() { EndPinAttribute(); }\n\nvoid BeginOutputAttribute(const int id, const ImNodesPinShape shape)\n{\n    BeginPinAttribute(id, ImNodesAttributeType_Output, shape, GImNodes->CurrentNodeIdx);\n}\n\nvoid EndOutputAttribute() { EndPinAttribute(); }\n\nvoid BeginStaticAttribute(const int id)\n{\n    // Make sure to call BeginNode() before calling BeginAttribute()\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Node);\n    GImNodes->CurrentScope = ImNodesScope_Attribute;\n\n    GImNodes->CurrentAttributeId = id;\n\n    ImGui::BeginGroup();\n    ImGui::PushID(id);\n}\n\nvoid EndStaticAttribute()\n{\n    // Make sure to call BeginNode() before calling BeginAttribute()\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Attribute);\n    GImNodes->CurrentScope = ImNodesScope_Node;\n\n    ImGui::PopID();\n    ImGui::EndGroup();\n\n    if (ImGui::IsItemActive())\n    {\n        GImNodes->ActiveAttribute = true;\n        GImNodes->ActiveAttributeId = GImNodes->CurrentAttributeId;\n    }\n}\n\nvoid PushAttributeFlag(const ImNodesAttributeFlags flag)\n{\n    GImNodes->CurrentAttributeFlags |= flag;\n    GImNodes->AttributeFlagStack.push_back(GImNodes->CurrentAttributeFlags);\n}\n\nvoid PopAttributeFlag()\n{\n    // PopAttributeFlag called without a matching PushAttributeFlag!\n    // The bottom value is always the default value, pushed in Initialize().\n    IM_ASSERT(GImNodes->AttributeFlagStack.size() > 1);\n\n    GImNodes->AttributeFlagStack.pop_back();\n    GImNodes->CurrentAttributeFlags = GImNodes->AttributeFlagStack.back();\n}\n\nvoid Link(const int id, const int start_attr_id, const int end_attr_id)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_Editor);\n\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImLinkData&           link = ObjectPoolFindOrCreateObject(editor.Links, id);\n    link.Id = id;\n    link.StartPinIdx = ObjectPoolFindOrCreateIndex(editor.Pins, start_attr_id);\n    link.EndPinIdx = ObjectPoolFindOrCreateIndex(editor.Pins, end_attr_id);\n    link.ColorStyle.Base = GImNodes->Style.Colors[ImNodesCol_Link];\n    link.ColorStyle.Hovered = GImNodes->Style.Colors[ImNodesCol_LinkHovered];\n    link.ColorStyle.Selected = GImNodes->Style.Colors[ImNodesCol_LinkSelected];\n\n    // Check if this link was created by the current link event\n    if ((editor.ClickInteraction.Type == ImNodesClickInteractionType_LinkCreation &&\n         editor.Pins.Pool[link.EndPinIdx].Flags & ImNodesAttributeFlags_EnableLinkCreationOnSnap &&\n         editor.ClickInteraction.LinkCreation.StartPinIdx == link.StartPinIdx &&\n         editor.ClickInteraction.LinkCreation.EndPinIdx == link.EndPinIdx) ||\n        (editor.ClickInteraction.LinkCreation.StartPinIdx == link.EndPinIdx &&\n         editor.ClickInteraction.LinkCreation.EndPinIdx == link.StartPinIdx))\n    {\n        GImNodes->SnapLinkIdx = ObjectPoolFindOrCreateIndex(editor.Links, id);\n    }\n}\n\nvoid PushColorStyle(const ImNodesCol item, unsigned int color)\n{\n    GImNodes->ColorModifierStack.push_back(ImNodesColElement(GImNodes->Style.Colors[item], item));\n    GImNodes->Style.Colors[item] = color;\n}\n\nvoid PopColorStyle()\n{\n    IM_ASSERT(GImNodes->ColorModifierStack.size() > 0);\n    const ImNodesColElement elem = GImNodes->ColorModifierStack.back();\n    GImNodes->Style.Colors[elem.Item] = elem.Color;\n    GImNodes->ColorModifierStack.pop_back();\n}\n\nstruct ImNodesStyleVarInfo\n{\n    ImGuiDataType Type;\n    ImU32         Count;\n    ImU32         Offset;\n    void* GetVarPtr(ImNodesStyle* style) const { return (void*)((unsigned char*)style + Offset); }\n};\n\nstatic const ImNodesStyleVarInfo GStyleVarInfo[] = {\n    // ImNodesStyleVar_GridSpacing\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, GridSpacing)},\n    // ImNodesStyleVar_NodeCornerRounding\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, NodeCornerRounding)},\n    // ImNodesStyleVar_NodePadding\n    {ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImNodesStyle, NodePadding)},\n    // ImNodesStyleVar_NodeBorderThickness\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, NodeBorderThickness)},\n    // ImNodesStyleVar_LinkThickness\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, LinkThickness)},\n    // ImNodesStyleVar_LinkLineSegmentsPerLength\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, LinkLineSegmentsPerLength)},\n    // ImNodesStyleVar_LinkHoverDistance\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, LinkHoverDistance)},\n    // ImNodesStyleVar_PinCircleRadius\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, PinCircleRadius)},\n    // ImNodesStyleVar_PinQuadSideLength\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, PinQuadSideLength)},\n    // ImNodesStyleVar_PinTriangleSideLength\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, PinTriangleSideLength)},\n    // ImNodesStyleVar_PinLineThickness\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, PinLineThickness)},\n    // ImNodesStyleVar_PinHoverRadius\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, PinHoverRadius)},\n    // ImNodesStyleVar_PinOffset\n    {ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImNodesStyle, PinOffset)},\n    // ImNodesStyleVar_MiniMapPadding\n    {ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImNodesStyle, MiniMapPadding)},\n    // ImNodesStyleVar_MiniMapOffset\n    {ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImNodesStyle, MiniMapOffset)},\n};\n\nstatic const ImNodesStyleVarInfo* GetStyleVarInfo(ImNodesStyleVar idx)\n{\n    IM_ASSERT(idx >= 0 && idx < ImNodesStyleVar_COUNT);\n    IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImNodesStyleVar_COUNT);\n    return &GStyleVarInfo[idx];\n}\n\nvoid PushStyleVar(const ImNodesStyleVar item, const float value)\n{\n    const ImNodesStyleVarInfo* var_info = GetStyleVarInfo(item);\n    if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)\n    {\n        float& style_var = *(float*)var_info->GetVarPtr(&GImNodes->Style);\n        GImNodes->StyleModifierStack.push_back(ImNodesStyleVarElement(item, style_var));\n        style_var = value;\n        return;\n    }\n    IM_ASSERT(0 && \"Called PushStyleVar() float variant but variable is not a float!\");\n}\n\nvoid PushStyleVar(const ImNodesStyleVar item, const ImVec2& value)\n{\n    const ImNodesStyleVarInfo* var_info = GetStyleVarInfo(item);\n    if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)\n    {\n        ImVec2& style_var = *(ImVec2*)var_info->GetVarPtr(&GImNodes->Style);\n        GImNodes->StyleModifierStack.push_back(ImNodesStyleVarElement(item, style_var));\n        style_var = value;\n        return;\n    }\n    IM_ASSERT(0 && \"Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!\");\n}\n\nvoid PopStyleVar(int count)\n{\n    while (count > 0)\n    {\n        IM_ASSERT(GImNodes->StyleModifierStack.size() > 0);\n        const ImNodesStyleVarElement style_backup = GImNodes->StyleModifierStack.back();\n        GImNodes->StyleModifierStack.pop_back();\n        const ImNodesStyleVarInfo* var_info = GetStyleVarInfo(style_backup.Item);\n        void*                      style_var = var_info->GetVarPtr(&GImNodes->Style);\n        if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)\n        {\n            ((float*)style_var)[0] = style_backup.FloatValue[0];\n        }\n        else if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)\n        {\n            ((float*)style_var)[0] = style_backup.FloatValue[0];\n            ((float*)style_var)[1] = style_backup.FloatValue[1];\n        }\n        count--;\n    }\n}\n\nvoid SetNodeScreenSpacePos(const int node_id, const ImVec2& screen_space_pos)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = ObjectPoolFindOrCreateObject(editor.Nodes, node_id);\n    node.Origin = ScreenSpaceToGridSpace(editor, screen_space_pos);\n}\n\nvoid SetNodeEditorSpacePos(const int node_id, const ImVec2& editor_space_pos)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = ObjectPoolFindOrCreateObject(editor.Nodes, node_id);\n    node.Origin = EditorSpaceToGridSpace(editor, editor_space_pos);\n}\n\nvoid SetNodeGridSpacePos(const int node_id, const ImVec2& grid_pos)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = ObjectPoolFindOrCreateObject(editor.Nodes, node_id);\n    node.Origin = grid_pos;\n}\n\nvoid SetNodeDraggable(const int node_id, const bool draggable)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = ObjectPoolFindOrCreateObject(editor.Nodes, node_id);\n    node.Draggable = draggable;\n}\n\nImVec2 GetNodeScreenSpacePos(const int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    const int             node_idx = ObjectPoolFind(editor.Nodes, node_id);\n    IM_ASSERT(node_idx != -1);\n    ImNodeData& node = editor.Nodes.Pool[node_idx];\n    return GridSpaceToScreenSpace(editor, node.Origin);\n}\n\nImVec2 GetNodeEditorSpacePos(const int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    const int             node_idx = ObjectPoolFind(editor.Nodes, node_id);\n    IM_ASSERT(node_idx != -1);\n    ImNodeData& node = editor.Nodes.Pool[node_idx];\n    return GridSpaceToEditorSpace(editor, node.Origin);\n}\n\nImVec2 GetNodeGridSpacePos(const int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    const int             node_idx = ObjectPoolFind(editor.Nodes, node_id);\n    IM_ASSERT(node_idx != -1);\n    ImNodeData& node = editor.Nodes.Pool[node_idx];\n    return node.Origin;\n}\n\nvoid SnapNodeToGrid(int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ImNodeData&           node = ObjectPoolFindOrCreateObject(editor.Nodes, node_id);\n    node.Origin = SnapOriginToGrid(node.Origin);\n}\n\nbool IsEditorHovered() { return MouseInCanvas(); }\n\nbool IsNodeHovered(int* const node_id)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    IM_ASSERT(node_id != NULL);\n\n    const bool is_hovered = GImNodes->HoveredNodeIdx.HasValue();\n    if (is_hovered)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        *node_id = editor.Nodes.Pool[GImNodes->HoveredNodeIdx.Value()].Id;\n    }\n    return is_hovered;\n}\n\nbool IsLinkHovered(int* const link_id)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    IM_ASSERT(link_id != NULL);\n\n    const bool is_hovered = GImNodes->HoveredLinkIdx.HasValue();\n    if (is_hovered)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        *link_id = editor.Links.Pool[GImNodes->HoveredLinkIdx.Value()].Id;\n    }\n    return is_hovered;\n}\n\nbool IsPinHovered(int* const attr)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    IM_ASSERT(attr != NULL);\n\n    const bool is_hovered = GImNodes->HoveredPinIdx.HasValue();\n    if (is_hovered)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        *attr = editor.Pins.Pool[GImNodes->HoveredPinIdx.Value()].Id;\n    }\n    return is_hovered;\n}\n\nint NumSelectedNodes()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    const ImNodesEditorContext& editor = EditorContextGet();\n    return editor.SelectedNodeIndices.size();\n}\n\nint NumSelectedLinks()\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    const ImNodesEditorContext& editor = EditorContextGet();\n    return editor.SelectedLinkIndices.size();\n}\n\nvoid GetSelectedNodes(int* node_ids)\n{\n    IM_ASSERT(node_ids != NULL);\n\n    const ImNodesEditorContext& editor = EditorContextGet();\n    for (int i = 0; i < editor.SelectedNodeIndices.size(); ++i)\n    {\n        const int node_idx = editor.SelectedNodeIndices[i];\n        node_ids[i] = editor.Nodes.Pool[node_idx].Id;\n    }\n}\n\nvoid GetSelectedLinks(int* link_ids)\n{\n    IM_ASSERT(link_ids != NULL);\n\n    const ImNodesEditorContext& editor = EditorContextGet();\n    for (int i = 0; i < editor.SelectedLinkIndices.size(); ++i)\n    {\n        const int link_idx = editor.SelectedLinkIndices[i];\n        link_ids[i] = editor.Links.Pool[link_idx].Id;\n    }\n}\n\nvoid ClearNodeSelection()\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    editor.SelectedNodeIndices.clear();\n}\n\nvoid ClearNodeSelection(int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ClearObjectSelection(editor.Nodes, editor.SelectedNodeIndices, node_id);\n}\n\nvoid ClearLinkSelection()\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    editor.SelectedLinkIndices.clear();\n}\n\nvoid ClearLinkSelection(int link_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    ClearObjectSelection(editor.Links, editor.SelectedLinkIndices, link_id);\n}\n\nvoid SelectNode(int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    SelectObject(editor.Nodes, editor.SelectedNodeIndices, node_id);\n}\n\nvoid SelectLink(int link_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    SelectObject(editor.Links, editor.SelectedLinkIndices, link_id);\n}\n\nbool IsNodeSelected(int node_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    return IsObjectSelected(editor.Nodes, editor.SelectedNodeIndices, node_id);\n}\n\nbool IsLinkSelected(int link_id)\n{\n    ImNodesEditorContext& editor = EditorContextGet();\n    return IsObjectSelected(editor.Links, editor.SelectedLinkIndices, link_id);\n}\n\nbool IsAttributeActive()\n{\n    IM_ASSERT((GImNodes->CurrentScope & ImNodesScope_Node) != 0);\n\n    if (!GImNodes->ActiveAttribute)\n    {\n        return false;\n    }\n\n    return GImNodes->ActiveAttributeId == GImNodes->CurrentAttributeId;\n}\n\nbool IsAnyAttributeActive(int* const attribute_id)\n{\n    IM_ASSERT((GImNodes->CurrentScope & (ImNodesScope_Node | ImNodesScope_Attribute)) == 0);\n\n    if (!GImNodes->ActiveAttribute)\n    {\n        return false;\n    }\n\n    if (attribute_id != NULL)\n    {\n        *attribute_id = GImNodes->ActiveAttributeId;\n    }\n\n    return true;\n}\n\nbool IsLinkStarted(int* const started_at_id)\n{\n    // Call this function after EndNodeEditor()!\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    IM_ASSERT(started_at_id != NULL);\n\n    const bool is_started = (GImNodes->ImNodesUIState & ImNodesUIState_LinkStarted) != 0;\n    if (is_started)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        const int                   pin_idx = editor.ClickInteraction.LinkCreation.StartPinIdx;\n        *started_at_id = editor.Pins.Pool[pin_idx].Id;\n    }\n\n    return is_started;\n}\n\nbool IsLinkDropped(int* const started_at_id, const bool including_detached_links)\n{\n    // Call this function after EndNodeEditor()!\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n\n    const ImNodesEditorContext& editor = EditorContextGet();\n\n    const bool link_dropped =\n        (GImNodes->ImNodesUIState & ImNodesUIState_LinkDropped) != 0 &&\n        (including_detached_links ||\n         editor.ClickInteraction.LinkCreation.Type != ImNodesLinkCreationType_FromDetach);\n\n    if (link_dropped && started_at_id)\n    {\n        const int pin_idx = editor.ClickInteraction.LinkCreation.StartPinIdx;\n        *started_at_id = editor.Pins.Pool[pin_idx].Id;\n    }\n\n    return link_dropped;\n}\n\nbool IsLinkCreated(\n    int* const  started_at_pin_id,\n    int* const  ended_at_pin_id,\n    bool* const created_from_snap)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    IM_ASSERT(started_at_pin_id != NULL);\n    IM_ASSERT(ended_at_pin_id != NULL);\n\n    const bool is_created = (GImNodes->ImNodesUIState & ImNodesUIState_LinkCreated) != 0;\n\n    if (is_created)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        const int                   start_idx = editor.ClickInteraction.LinkCreation.StartPinIdx;\n        const int        end_idx = editor.ClickInteraction.LinkCreation.EndPinIdx.Value();\n        const ImPinData& start_pin = editor.Pins.Pool[start_idx];\n        const ImPinData& end_pin = editor.Pins.Pool[end_idx];\n\n        if (start_pin.Type == ImNodesAttributeType_Output)\n        {\n            *started_at_pin_id = start_pin.Id;\n            *ended_at_pin_id = end_pin.Id;\n        }\n        else\n        {\n            *started_at_pin_id = end_pin.Id;\n            *ended_at_pin_id = start_pin.Id;\n        }\n\n        if (created_from_snap)\n        {\n            *created_from_snap =\n                editor.ClickInteraction.Type == ImNodesClickInteractionType_LinkCreation;\n        }\n    }\n\n    return is_created;\n}\n\nbool IsLinkCreated(\n    int*  started_at_node_id,\n    int*  started_at_pin_id,\n    int*  ended_at_node_id,\n    int*  ended_at_pin_id,\n    bool* created_from_snap)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n    IM_ASSERT(started_at_node_id != NULL);\n    IM_ASSERT(started_at_pin_id != NULL);\n    IM_ASSERT(ended_at_node_id != NULL);\n    IM_ASSERT(ended_at_pin_id != NULL);\n\n    const bool is_created = (GImNodes->ImNodesUIState & ImNodesUIState_LinkCreated) != 0;\n\n    if (is_created)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        const int                   start_idx = editor.ClickInteraction.LinkCreation.StartPinIdx;\n        const int         end_idx = editor.ClickInteraction.LinkCreation.EndPinIdx.Value();\n        const ImPinData&  start_pin = editor.Pins.Pool[start_idx];\n        const ImNodeData& start_node = editor.Nodes.Pool[start_pin.ParentNodeIdx];\n        const ImPinData&  end_pin = editor.Pins.Pool[end_idx];\n        const ImNodeData& end_node = editor.Nodes.Pool[end_pin.ParentNodeIdx];\n\n        if (start_pin.Type == ImNodesAttributeType_Output)\n        {\n            *started_at_pin_id = start_pin.Id;\n            *started_at_node_id = start_node.Id;\n            *ended_at_pin_id = end_pin.Id;\n            *ended_at_node_id = end_node.Id;\n        }\n        else\n        {\n            *started_at_pin_id = end_pin.Id;\n            *started_at_node_id = end_node.Id;\n            *ended_at_pin_id = start_pin.Id;\n            *ended_at_node_id = start_node.Id;\n        }\n\n        if (created_from_snap)\n        {\n            *created_from_snap =\n                editor.ClickInteraction.Type == ImNodesClickInteractionType_LinkCreation;\n        }\n    }\n\n    return is_created;\n}\n\nbool IsLinkDestroyed(int* const link_id)\n{\n    IM_ASSERT(GImNodes->CurrentScope == ImNodesScope_None);\n\n    const bool link_destroyed = GImNodes->DeletedLinkIdx.HasValue();\n    if (link_destroyed)\n    {\n        const ImNodesEditorContext& editor = EditorContextGet();\n        const int                   link_idx = GImNodes->DeletedLinkIdx.Value();\n        *link_id = editor.Links.Pool[link_idx].Id;\n    }\n\n    return link_destroyed;\n}\n\nnamespace\n{\nvoid NodeLineHandler(ImNodesEditorContext& editor, const char* const line)\n{\n    int id;\n    int x, y;\n    if (sscanf(line, \"[node.%i\", &id) == 1)\n    {\n        const int node_idx = ObjectPoolFindOrCreateIndex(editor.Nodes, id);\n        GImNodes->CurrentNodeIdx = node_idx;\n        ImNodeData& node = editor.Nodes.Pool[node_idx];\n        node.Id = id;\n    }\n    else if (sscanf(line, \"origin=%i,%i\", &x, &y) == 2)\n    {\n        ImNodeData& node = editor.Nodes.Pool[GImNodes->CurrentNodeIdx];\n        node.Origin = SnapOriginToGrid(ImVec2((float)x, (float)y));\n    }\n}\n\nvoid EditorLineHandler(ImNodesEditorContext& editor, const char* const line)\n{\n    (void)sscanf(line, \"panning=%f,%f\", &editor.Panning.x, &editor.Panning.y);\n}\n} // namespace\n\nconst char* SaveCurrentEditorStateToIniString(size_t* const data_size)\n{\n    return SaveEditorStateToIniString(&EditorContextGet(), data_size);\n}\n\nconst char* SaveEditorStateToIniString(\n    const ImNodesEditorContext* const editor_ptr,\n    size_t* const                     data_size)\n{\n    IM_ASSERT(editor_ptr != NULL);\n    const ImNodesEditorContext& editor = *editor_ptr;\n\n    GImNodes->TextBuffer.clear();\n    // TODO: check to make sure that the estimate is the upper bound of element\n    GImNodes->TextBuffer.reserve(64 * editor.Nodes.Pool.size());\n\n    GImNodes->TextBuffer.appendf(\n        \"[editor]\\npanning=%i,%i\\n\", (int)editor.Panning.x, (int)editor.Panning.y);\n\n    for (int i = 0; i < editor.Nodes.Pool.size(); i++)\n    {\n        if (editor.Nodes.InUse[i])\n        {\n            const ImNodeData& node = editor.Nodes.Pool[i];\n            GImNodes->TextBuffer.appendf(\"\\n[node.%d]\\n\", node.Id);\n            GImNodes->TextBuffer.appendf(\"origin=%i,%i\\n\", (int)node.Origin.x, (int)node.Origin.y);\n        }\n    }\n\n    if (data_size != NULL)\n    {\n        *data_size = GImNodes->TextBuffer.size();\n    }\n\n    return GImNodes->TextBuffer.c_str();\n}\n\nvoid LoadCurrentEditorStateFromIniString(const char* const data, const size_t data_size)\n{\n    LoadEditorStateFromIniString(&EditorContextGet(), data, data_size);\n}\n\nvoid LoadEditorStateFromIniString(\n    ImNodesEditorContext* const editor_ptr,\n    const char* const           data,\n    const size_t                data_size)\n{\n    if (data_size == 0u)\n    {\n        return;\n    }\n\n    ImNodesEditorContext& editor = editor_ptr == NULL ? EditorContextGet() : *editor_ptr;\n\n    char*       buf = (char*)ImGui::MemAlloc(data_size + 1);\n    const char* buf_end = buf + data_size;\n    memcpy(buf, data, data_size);\n    buf[data_size] = 0;\n\n    void (*line_handler)(ImNodesEditorContext&, const char*);\n    line_handler = NULL;\n    char* line_end = NULL;\n    for (char* line = buf; line < buf_end; line = line_end + 1)\n    {\n        while (*line == '\\n' || *line == '\\r')\n        {\n            line++;\n        }\n        line_end = line;\n        while (line_end < buf_end && *line_end != '\\n' && *line_end != '\\r')\n        {\n            line_end++;\n        }\n        line_end[0] = 0;\n\n        if (*line == ';' || *line == '\\0')\n        {\n            continue;\n        }\n\n        if (line[0] == '[' && line_end[-1] == ']')\n        {\n            line_end[-1] = 0;\n            if (strncmp(line + 1, \"node\", 4) == 0)\n            {\n                line_handler = NodeLineHandler;\n            }\n            else if (strcmp(line + 1, \"editor\") == 0)\n            {\n                line_handler = EditorLineHandler;\n            }\n        }\n\n        if (line_handler != NULL)\n        {\n            line_handler(editor, line);\n        }\n    }\n    ImGui::MemFree(buf);\n}\n\nvoid SaveCurrentEditorStateToIniFile(const char* const file_name)\n{\n    SaveEditorStateToIniFile(&EditorContextGet(), file_name);\n}\n\nvoid SaveEditorStateToIniFile(const ImNodesEditorContext* const editor, const char* const file_name)\n{\n    size_t      data_size = 0u;\n    const char* data = SaveEditorStateToIniString(editor, &data_size);\n    FILE*       file = ImFileOpen(file_name, \"wt\");\n    if (!file)\n    {\n        return;\n    }\n\n    fwrite(data, sizeof(char), data_size, file);\n    fclose(file);\n}\n\nvoid LoadCurrentEditorStateFromIniFile(const char* const file_name)\n{\n    LoadEditorStateFromIniFile(&EditorContextGet(), file_name);\n}\n\nvoid LoadEditorStateFromIniFile(ImNodesEditorContext* const editor, const char* const file_name)\n{\n    size_t data_size = 0u;\n    char*  file_data = (char*)ImFileLoadToMemory(file_name, \"rb\", &data_size);\n\n    if (!file_data)\n    {\n        return;\n    }\n\n    LoadEditorStateFromIniString(editor, file_data, data_size);\n    ImGui::MemFree(file_data);\n}\n} // namespace IMNODES_NAMESPACE\n"
  },
  {
    "path": "Source/External/imgui_tools/imnodes/imnodes.h",
    "content": "#pragma once\n\n#include <stddef.h>\n#include <imgui.h>\n\n#ifdef IMNODES_USER_CONFIG\n#include IMNODES_USER_CONFIG\n#endif\n\n#ifndef IMNODES_NAMESPACE\n#define IMNODES_NAMESPACE ImNodes\n#endif\n\ntypedef int ImNodesCol;             // -> enum ImNodesCol_\ntypedef int ImNodesStyleVar;        // -> enum ImNodesStyleVar_\ntypedef int ImNodesStyleFlags;      // -> enum ImNodesStyleFlags_\ntypedef int ImNodesPinShape;        // -> enum ImNodesPinShape_\ntypedef int ImNodesAttributeFlags;  // -> enum ImNodesAttributeFlags_\ntypedef int ImNodesMiniMapLocation; // -> enum ImNodesMiniMapLocation_\n\nenum ImNodesCol_\n{\n    ImNodesCol_NodeBackground = 0,\n    ImNodesCol_NodeBackgroundHovered,\n    ImNodesCol_NodeBackgroundSelected,\n    ImNodesCol_NodeOutline,\n    ImNodesCol_TitleBar,\n    ImNodesCol_TitleBarHovered,\n    ImNodesCol_TitleBarSelected,\n    ImNodesCol_Link,\n    ImNodesCol_LinkHovered,\n    ImNodesCol_LinkSelected,\n    ImNodesCol_Pin,\n    ImNodesCol_PinHovered,\n    ImNodesCol_BoxSelector,\n    ImNodesCol_BoxSelectorOutline,\n    ImNodesCol_GridBackground,\n    ImNodesCol_GridLine,\n    ImNodesCol_GridLinePrimary,\n    ImNodesCol_MiniMapBackground,\n    ImNodesCol_MiniMapBackgroundHovered,\n    ImNodesCol_MiniMapOutline,\n    ImNodesCol_MiniMapOutlineHovered,\n    ImNodesCol_MiniMapNodeBackground,\n    ImNodesCol_MiniMapNodeBackgroundHovered,\n    ImNodesCol_MiniMapNodeBackgroundSelected,\n    ImNodesCol_MiniMapNodeOutline,\n    ImNodesCol_MiniMapLink,\n    ImNodesCol_MiniMapLinkSelected,\n    ImNodesCol_MiniMapCanvas,\n    ImNodesCol_MiniMapCanvasOutline,\n    ImNodesCol_COUNT\n};\n\nenum ImNodesStyleVar_\n{\n    ImNodesStyleVar_GridSpacing = 0,\n    ImNodesStyleVar_NodeCornerRounding,\n    ImNodesStyleVar_NodePadding,\n    ImNodesStyleVar_NodeBorderThickness,\n    ImNodesStyleVar_LinkThickness,\n    ImNodesStyleVar_LinkLineSegmentsPerLength,\n    ImNodesStyleVar_LinkHoverDistance,\n    ImNodesStyleVar_PinCircleRadius,\n    ImNodesStyleVar_PinQuadSideLength,\n    ImNodesStyleVar_PinTriangleSideLength,\n    ImNodesStyleVar_PinLineThickness,\n    ImNodesStyleVar_PinHoverRadius,\n    ImNodesStyleVar_PinOffset,\n    ImNodesStyleVar_MiniMapPadding,\n    ImNodesStyleVar_MiniMapOffset,\n    ImNodesStyleVar_COUNT\n};\n\nenum ImNodesStyleFlags_\n{\n    ImNodesStyleFlags_None = 0,\n    ImNodesStyleFlags_NodeOutline = 1 << 0,\n    ImNodesStyleFlags_GridLines = 1 << 2,\n    ImNodesStyleFlags_GridLinesPrimary = 1 << 3,\n    ImNodesStyleFlags_GridSnapping = 1 << 4\n};\n\nenum ImNodesPinShape_\n{\n    ImNodesPinShape_Circle,\n    ImNodesPinShape_CircleFilled,\n    ImNodesPinShape_Triangle,\n    ImNodesPinShape_TriangleFilled,\n    ImNodesPinShape_Quad,\n    ImNodesPinShape_QuadFilled\n};\n\n// This enum controls the way the attribute pins behave.\nenum ImNodesAttributeFlags_\n{\n    ImNodesAttributeFlags_None = 0,\n    // Allow detaching a link by left-clicking and dragging the link at a pin it is connected to.\n    // NOTE: the user has to actually delete the link for this to work. A deleted link can be\n    // detected by calling IsLinkDestroyed() after EndNodeEditor().\n    ImNodesAttributeFlags_EnableLinkDetachWithDragClick = 1 << 0,\n    // Visual snapping of an in progress link will trigger IsLink Created/Destroyed events. Allows\n    // for previewing the creation of a link while dragging it across attributes. See here for demo:\n    // https://github.com/Nelarius/imnodes/issues/41#issuecomment-647132113 NOTE: the user has to\n    // actually delete the link for this to work. A deleted link can be detected by calling\n    // IsLinkDestroyed() after EndNodeEditor().\n    ImNodesAttributeFlags_EnableLinkCreationOnSnap = 1 << 1\n};\n\nstruct ImNodesIO\n{\n    struct EmulateThreeButtonMouse\n    {\n        EmulateThreeButtonMouse();\n\n        // The keyboard modifier to use in combination with mouse left click to pan the editor view.\n        // Set to NULL by default. To enable this feature, set the modifier to point to a boolean\n        // indicating the state of a modifier. For example,\n        //\n        // ImNodes::GetIO().EmulateThreeButtonMouse.Modifier = &ImGui::GetIO().KeyAlt;\n        const bool* Modifier;\n    } EmulateThreeButtonMouse;\n\n    struct LinkDetachWithModifierClick\n    {\n        LinkDetachWithModifierClick();\n\n        // Pointer to a boolean value indicating when the desired modifier is pressed. Set to NULL\n        // by default. To enable the feature, set the modifier to point to a boolean indicating the\n        // state of a modifier. For example,\n        //\n        // ImNodes::GetIO().LinkDetachWithModifierClick.Modifier = &ImGui::GetIO().KeyCtrl;\n        //\n        // Left-clicking a link with this modifier pressed will detach that link. NOTE: the user has\n        // to actually delete the link for this to work. A deleted link can be detected by calling\n        // IsLinkDestroyed() after EndNodeEditor().\n        const bool* Modifier;\n    } LinkDetachWithModifierClick;\n\n    struct MultipleSelectModifier\n    {\n        MultipleSelectModifier();\n\n        // Pointer to a boolean value indicating when the desired modifier is pressed. Set to NULL\n        // by default. To enable the feature, set the modifier to point to a boolean indicating the\n        // state of a modifier. For example,\n        //\n        // ImNodes::GetIO().MultipleSelectModifier.Modifier = &ImGui::GetIO().KeyCtrl;\n        //\n        // Left-clicking a node with this modifier pressed will add the node to the list of\n        // currently selected nodes. If this value is NULL, the Ctrl key will be used.\n        const bool* Modifier;\n    } MultipleSelectModifier;\n\n    // Holding alt mouse button pans the node area, by default middle mouse button will be used\n    // Set based on ImGuiMouseButton values\n    int AltMouseButton;\n\n    // Panning speed when dragging an element and mouse is outside the main editor view.\n    float AutoPanningSpeed;\n\n    ImNodesIO();\n};\n\nstruct ImNodesStyle\n{\n    float GridSpacing;\n\n    float  NodeCornerRounding;\n    ImVec2 NodePadding;\n    float  NodeBorderThickness;\n\n    float LinkThickness;\n    float LinkLineSegmentsPerLength;\n    float LinkHoverDistance;\n\n    // The following variables control the look and behavior of the pins. The default size of each\n    // pin shape is balanced to occupy approximately the same surface area on the screen.\n\n    // The circle radius used when the pin shape is either ImNodesPinShape_Circle or\n    // ImNodesPinShape_CircleFilled.\n    float PinCircleRadius;\n    // The quad side length used when the shape is either ImNodesPinShape_Quad or\n    // ImNodesPinShape_QuadFilled.\n    float PinQuadSideLength;\n    // The equilateral triangle side length used when the pin shape is either\n    // ImNodesPinShape_Triangle or ImNodesPinShape_TriangleFilled.\n    float PinTriangleSideLength;\n    // The thickness of the line used when the pin shape is not filled.\n    float PinLineThickness;\n    // The radius from the pin's center position inside of which it is detected as being hovered\n    // over.\n    float PinHoverRadius;\n    // Offsets the pins' positions from the edge of the node to the outside of the node.\n    float PinOffset;\n\n    // Mini-map padding size between mini-map edge and mini-map content.\n    ImVec2 MiniMapPadding;\n    // Mini-map offset from the screen side.\n    ImVec2 MiniMapOffset;\n\n    // By default, ImNodesStyleFlags_NodeOutline and ImNodesStyleFlags_Gridlines are enabled.\n    ImNodesStyleFlags Flags;\n    // Set these mid-frame using Push/PopColorStyle. You can index this color array with with a\n    // ImNodesCol value.\n    unsigned int Colors[ImNodesCol_COUNT];\n\n    ImNodesStyle();\n};\n\nenum ImNodesMiniMapLocation_\n{\n    ImNodesMiniMapLocation_BottomLeft,\n    ImNodesMiniMapLocation_BottomRight,\n    ImNodesMiniMapLocation_TopLeft,\n    ImNodesMiniMapLocation_TopRight,\n};\n\nstruct ImGuiContext;\nstruct ImVec2;\n\nstruct ImNodesContext;\n\n// An editor context corresponds to a set of nodes in a single workspace (created with a single\n// Begin/EndNodeEditor pair)\n//\n// By default, the library creates an editor context behind the scenes, so using any of the imnodes\n// functions doesn't require you to explicitly create a context.\nstruct ImNodesEditorContext;\n\n// Callback type used to specify special behavior when hovering a node in the minimap\n#ifndef ImNodesMiniMapNodeHoveringCallback\ntypedef void (*ImNodesMiniMapNodeHoveringCallback)(int, void*);\n#endif\n\n#ifndef ImNodesMiniMapNodeHoveringCallbackUserData\ntypedef void* ImNodesMiniMapNodeHoveringCallbackUserData;\n#endif\n\nnamespace IMNODES_NAMESPACE\n{\n// Call this function if you are compiling imnodes in to a dll, separate from ImGui. Calling this\n// function sets the GImGui global variable, which is not shared across dll boundaries.\nvoid SetImGuiContext(ImGuiContext* ctx);\n\nImNodesContext* CreateContext();\nvoid            DestroyContext(ImNodesContext* ctx = NULL); // NULL = destroy current context\nImNodesContext* GetCurrentContext();\nvoid            SetCurrentContext(ImNodesContext* ctx);\n\nImNodesEditorContext* EditorContextCreate();\nvoid                  EditorContextFree(ImNodesEditorContext*);\nvoid                  EditorContextSet(ImNodesEditorContext*);\nImVec2                EditorContextGetPanning();\nvoid                  EditorContextResetPanning(const ImVec2& pos);\nvoid                  EditorContextMoveToNode(const int node_id);\n\nImNodesIO& GetIO();\n\n// Returns the global style struct. See the struct declaration for default values.\nImNodesStyle& GetStyle();\n// Style presets matching the dear imgui styles of the same name. If dest is NULL, the active\n// context's ImNodesStyle instance will be used as the destination.\nvoid StyleColorsDark(ImNodesStyle* dest = NULL); // on by default\nvoid StyleColorsClassic(ImNodesStyle* dest = NULL);\nvoid StyleColorsLight(ImNodesStyle* dest = NULL);\n\n// The top-level function call. Call this before calling BeginNode/EndNode. Calling this function\n// will result the node editor grid workspace being rendered.\nvoid BeginNodeEditor();\nvoid EndNodeEditor();\n\n// Add a navigable minimap to the editor; call before EndNodeEditor after all\n// nodes and links have been specified\nvoid MiniMap(\n    const float                                      minimap_size_fraction = 0.2f,\n    const ImNodesMiniMapLocation                     location = ImNodesMiniMapLocation_TopLeft,\n    const ImNodesMiniMapNodeHoveringCallback         node_hovering_callback = NULL,\n    const ImNodesMiniMapNodeHoveringCallbackUserData node_hovering_callback_data = NULL);\n\n// Use PushColorStyle and PopColorStyle to modify ImNodesStyle::Colors mid-frame.\nvoid PushColorStyle(ImNodesCol item, unsigned int color);\nvoid PopColorStyle();\nvoid PushStyleVar(ImNodesStyleVar style_item, float value);\nvoid PushStyleVar(ImNodesStyleVar style_item, const ImVec2& value);\nvoid PopStyleVar(int count = 1);\n\n// id can be any positive or negative integer, but INT_MIN is currently reserved for internal use.\nvoid BeginNode(int id);\nvoid EndNode();\n\nImVec2 GetNodeDimensions(int id);\n\n// Place your node title bar content (such as the node title, using ImGui::Text) between the\n// following function calls. These functions have to be called before adding any attributes, or the\n// layout of the node will be incorrect.\nvoid BeginNodeTitleBar();\nvoid EndNodeTitleBar();\n\n// Attributes are ImGui UI elements embedded within the node. Attributes can have pin shapes\n// rendered next to them. Links are created between pins.\n//\n// The activity status of an attribute can be checked via the IsAttributeActive() and\n// IsAnyAttributeActive() function calls. This is one easy way of checking for any changes made to\n// an attribute's drag float UI, for instance.\n//\n// Each attribute id must be unique.\n\n// Create an input attribute block. The pin is rendered on left side.\nvoid BeginInputAttribute(int id, ImNodesPinShape shape = ImNodesPinShape_CircleFilled);\nvoid EndInputAttribute();\n// Create an output attribute block. The pin is rendered on the right side.\nvoid BeginOutputAttribute(int id, ImNodesPinShape shape = ImNodesPinShape_CircleFilled);\nvoid EndOutputAttribute();\n// Create a static attribute block. A static attribute has no pin, and therefore can't be linked to\n// anything. However, you can still use IsAttributeActive() and IsAnyAttributeActive() to check for\n// attribute activity.\nvoid BeginStaticAttribute(int id);\nvoid EndStaticAttribute();\n\n// Push a single AttributeFlags value. By default, only AttributeFlags_None is set.\nvoid PushAttributeFlag(ImNodesAttributeFlags flag);\nvoid PopAttributeFlag();\n\n// Render a link between attributes.\n// The attributes ids used here must match the ids used in Begin(Input|Output)Attribute function\n// calls. The order of start_attr and end_attr doesn't make a difference for rendering the link.\nvoid Link(int id, int start_attribute_id, int end_attribute_id);\n\n// Enable or disable the ability to click and drag a specific node.\nvoid SetNodeDraggable(int node_id, const bool draggable);\n\n// The node's position can be expressed in three coordinate systems:\n// * screen space coordinates, -- the origin is the upper left corner of the window.\n// * editor space coordinates -- the origin is the upper left corner of the node editor window\n// * grid space coordinates, -- the origin is the upper left corner of the node editor window,\n// translated by the current editor panning vector (see EditorContextGetPanning() and\n// EditorContextResetPanning())\n\n// Use the following functions to get and set the node's coordinates in these coordinate systems.\n\nvoid SetNodeScreenSpacePos(int node_id, const ImVec2& screen_space_pos);\nvoid SetNodeEditorSpacePos(int node_id, const ImVec2& editor_space_pos);\nvoid SetNodeGridSpacePos(int node_id, const ImVec2& grid_pos);\n\nImVec2 GetNodeScreenSpacePos(const int node_id);\nImVec2 GetNodeEditorSpacePos(const int node_id);\nImVec2 GetNodeGridSpacePos(const int node_id);\n\n// If ImNodesStyleFlags_GridSnapping is enabled, snap the specified node's origin to the grid.\nvoid SnapNodeToGrid(int node_id);\n\n// Returns true if the current node editor canvas is being hovered over by the mouse, and is not\n// blocked by any other windows.\nbool IsEditorHovered();\n// The following functions return true if a UI element is being hovered over by the mouse cursor.\n// Assigns the id of the UI element being hovered over to the function argument. Use these functions\n// after EndNodeEditor() has been called.\nbool IsNodeHovered(int* node_id);\nbool IsLinkHovered(int* link_id);\nbool IsPinHovered(int* attribute_id);\n\n// Use The following two functions to query the number of selected nodes or links in the current\n// editor. Use after calling EndNodeEditor().\nint NumSelectedNodes();\nint NumSelectedLinks();\n// Get the selected node/link ids. The pointer argument should point to an integer array with at\n// least as many elements as the respective NumSelectedNodes/NumSelectedLinks function call\n// returned.\nvoid GetSelectedNodes(int* node_ids);\nvoid GetSelectedLinks(int* link_ids);\n// Clears the list of selected nodes/links. Useful if you want to delete a selected node or link.\nvoid ClearNodeSelection();\nvoid ClearLinkSelection();\n// Use the following functions to add or remove individual nodes or links from the current editors\n// selection. Note that all functions require the id to be an existing valid id for this editor.\n// Select-functions has the precondition that the object is currently considered unselected.\n// Clear-functions has the precondition that the object is currently considered selected.\n// Preconditions listed above can be checked via IsNodeSelected/IsLinkSelected if not already\n// known.\nvoid SelectNode(int node_id);\nvoid ClearNodeSelection(int node_id);\nbool IsNodeSelected(int node_id);\nvoid SelectLink(int link_id);\nvoid ClearLinkSelection(int link_id);\nbool IsLinkSelected(int link_id);\n\n// Was the previous attribute active? This will continuously return true while the left mouse button\n// is being pressed over the UI content of the attribute.\nbool IsAttributeActive();\n// Was any attribute active? If so, sets the active attribute id to the output function argument.\nbool IsAnyAttributeActive(int* attribute_id = NULL);\n\n// Use the following functions to query a change of state for an existing link, or new link. Call\n// these after EndNodeEditor().\n\n// Did the user start dragging a new link from a pin?\nbool IsLinkStarted(int* started_at_attribute_id);\n// Did the user drop the dragged link before attaching it to a pin?\n// There are two different kinds of situations to consider when handling this event:\n// 1) a link which is created at a pin and then dropped\n// 2) an existing link which is detached from a pin and then dropped\n// Use the including_detached_links flag to control whether this function triggers when the user\n// detaches a link and drops it.\nbool IsLinkDropped(int* started_at_attribute_id = NULL, bool including_detached_links = true);\n// Did the user finish creating a new link?\nbool IsLinkCreated(\n    int*  started_at_attribute_id,\n    int*  ended_at_attribute_id,\n    bool* created_from_snap = NULL);\nbool IsLinkCreated(\n    int*  started_at_node_id,\n    int*  started_at_attribute_id,\n    int*  ended_at_node_id,\n    int*  ended_at_attribute_id,\n    bool* created_from_snap = NULL);\n\n// Was an existing link detached from a pin by the user? The detached link's id is assigned to the\n// output argument link_id.\nbool IsLinkDestroyed(int* link_id);\n\n// Use the following functions to write the editor context's state to a string, or directly to a\n// file. The editor context is serialized in the INI file format.\n\nconst char* SaveCurrentEditorStateToIniString(size_t* data_size = NULL);\nconst char* SaveEditorStateToIniString(\n    const ImNodesEditorContext* editor,\n    size_t*                     data_size = NULL);\n\nvoid LoadCurrentEditorStateFromIniString(const char* data, size_t data_size);\nvoid LoadEditorStateFromIniString(ImNodesEditorContext* editor, const char* data, size_t data_size);\n\nvoid SaveCurrentEditorStateToIniFile(const char* file_name);\nvoid SaveEditorStateToIniFile(const ImNodesEditorContext* editor, const char* file_name);\n\nvoid LoadCurrentEditorStateFromIniFile(const char* file_name);\nvoid LoadEditorStateFromIniFile(ImNodesEditorContext* editor, const char* file_name);\n} // namespace IMNODES_NAMESPACE\n"
  },
  {
    "path": "Source/External/imgui_tools/imnodes/imnodes_internal.h",
    "content": "#pragma once\n\n#define IMGUI_DEFINE_MATH_OPERATORS\n#include \"imnodes.h\"\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\n#include <limits.h>\n\n// the structure of this file:\n//\n// [SECTION] internal enums\n// [SECTION] internal data structures\n// [SECTION] global and editor context structs\n// [SECTION] object pool implementation\n\nstruct ImNodesContext;\n\nextern ImNodesContext* GImNodes;\n\n// [SECTION] internal enums\n\ntypedef int ImNodesScope;\ntypedef int ImNodesAttributeType;\ntypedef int ImNodesUIState;\ntypedef int ImNodesClickInteractionType;\ntypedef int ImNodesLinkCreationType;\n\nenum ImNodesScope_\n{\n    ImNodesScope_None = 1,\n    ImNodesScope_Editor = 1 << 1,\n    ImNodesScope_Node = 1 << 2,\n    ImNodesScope_Attribute = 1 << 3\n};\n\nenum ImNodesAttributeType_\n{\n    ImNodesAttributeType_None,\n    ImNodesAttributeType_Input,\n    ImNodesAttributeType_Output\n};\n\nenum ImNodesUIState_\n{\n    ImNodesUIState_None = 0,\n    ImNodesUIState_LinkStarted = 1 << 0,\n    ImNodesUIState_LinkDropped = 1 << 1,\n    ImNodesUIState_LinkCreated = 1 << 2\n};\n\nenum ImNodesClickInteractionType_\n{\n    ImNodesClickInteractionType_Node,\n    ImNodesClickInteractionType_Link,\n    ImNodesClickInteractionType_LinkCreation,\n    ImNodesClickInteractionType_Panning,\n    ImNodesClickInteractionType_BoxSelection,\n    ImNodesClickInteractionType_ImGuiItem,\n    ImNodesClickInteractionType_None\n};\n\nenum ImNodesLinkCreationType_\n{\n    ImNodesLinkCreationType_Standard,\n    ImNodesLinkCreationType_FromDetach\n};\n\n// [SECTION] internal data structures\n\n// The object T must have the following interface:\n//\n// struct T\n// {\n//     T();\n//\n//     int id;\n// };\ntemplate<typename T>\nstruct ImObjectPool\n{\n    ImVector<T>    Pool;\n    ImVector<bool> InUse;\n    ImVector<int>  FreeList;\n    ImGuiStorage   IdMap;\n\n    ImObjectPool() : Pool(), InUse(), FreeList(), IdMap() {}\n};\n\n// Emulates std::optional<int> using the sentinel value `INVALID_INDEX`.\nstruct ImOptionalIndex\n{\n    ImOptionalIndex() : _Index(INVALID_INDEX) {}\n    ImOptionalIndex(const int value) : _Index(value) {}\n\n    // Observers\n\n    inline bool HasValue() const { return _Index != INVALID_INDEX; }\n\n    inline int Value() const\n    {\n        IM_ASSERT(HasValue());\n        return _Index;\n    }\n\n    // Modifiers\n\n    inline ImOptionalIndex& operator=(const int value)\n    {\n        _Index = value;\n        return *this;\n    }\n\n    inline void Reset() { _Index = INVALID_INDEX; }\n\n    inline bool operator==(const ImOptionalIndex& rhs) const { return _Index == rhs._Index; }\n\n    inline bool operator==(const int rhs) const { return _Index == rhs; }\n\n    inline bool operator!=(const ImOptionalIndex& rhs) const { return _Index != rhs._Index; }\n\n    inline bool operator!=(const int rhs) const { return _Index != rhs; }\n\n    static const int INVALID_INDEX = -1;\n\nprivate:\n    int _Index;\n};\n\nstruct ImNodeData\n{\n    int    Id;\n    ImVec2 Origin; // The node origin is in editor space\n    ImRect TitleBarContentRect;\n    ImRect Rect;\n\n    struct\n    {\n        ImU32 Background, BackgroundHovered, BackgroundSelected, Outline, Titlebar, TitlebarHovered,\n            TitlebarSelected;\n    } ColorStyle;\n\n    struct\n    {\n        float  CornerRounding;\n        ImVec2 Padding;\n        float  BorderThickness;\n    } LayoutStyle;\n\n    ImVector<int> PinIndices;\n    bool          Draggable;\n\n    ImNodeData(const int node_id)\n        : Id(node_id), Origin(0.0f, 0.0f), TitleBarContentRect(),\n          Rect(ImVec2(0.0f, 0.0f), ImVec2(0.0f, 0.0f)), ColorStyle(), LayoutStyle(), PinIndices(),\n          Draggable(true)\n    {\n    }\n\n    ~ImNodeData() { Id = INT_MIN; }\n};\n\nstruct ImPinData\n{\n    int                  Id;\n    int                  ParentNodeIdx;\n    ImRect               AttributeRect;\n    ImNodesAttributeType Type;\n    ImNodesPinShape      Shape;\n    ImVec2               Pos; // screen-space coordinates\n    int                  Flags;\n\n    struct\n    {\n        ImU32 Background, Hovered;\n    } ColorStyle;\n\n    ImPinData(const int pin_id)\n        : Id(pin_id), ParentNodeIdx(), AttributeRect(), Type(ImNodesAttributeType_None),\n          Shape(ImNodesPinShape_CircleFilled), Pos(), Flags(ImNodesAttributeFlags_None),\n          ColorStyle()\n    {\n    }\n};\n\nstruct ImLinkData\n{\n    int Id;\n    int StartPinIdx, EndPinIdx;\n\n    struct\n    {\n        ImU32 Base, Hovered, Selected;\n    } ColorStyle;\n\n    ImLinkData(const int link_id) : Id(link_id), StartPinIdx(), EndPinIdx(), ColorStyle() {}\n};\n\nstruct ImClickInteractionState\n{\n    ImNodesClickInteractionType Type;\n\n    struct\n    {\n        int                     StartPinIdx;\n        ImOptionalIndex         EndPinIdx;\n        ImNodesLinkCreationType Type;\n    } LinkCreation;\n\n    struct\n    {\n        ImRect Rect; // Coordinates in grid space\n    } BoxSelector;\n\n    ImClickInteractionState() : Type(ImNodesClickInteractionType_None) {}\n};\n\nstruct ImNodesColElement\n{\n    ImU32      Color;\n    ImNodesCol Item;\n\n    ImNodesColElement(const ImU32 c, const ImNodesCol s) : Color(c), Item(s) {}\n};\n\nstruct ImNodesStyleVarElement\n{\n    ImNodesStyleVar Item;\n    float           FloatValue[2];\n\n    ImNodesStyleVarElement(const ImNodesStyleVar variable, const float value) : Item(variable)\n    {\n        FloatValue[0] = value;\n    }\n\n    ImNodesStyleVarElement(const ImNodesStyleVar variable, const ImVec2 value) : Item(variable)\n    {\n        FloatValue[0] = value.x;\n        FloatValue[1] = value.y;\n    }\n};\n\n// [SECTION] global and editor context structs\n\nstruct ImNodesEditorContext\n{\n    ImObjectPool<ImNodeData> Nodes;\n    ImObjectPool<ImPinData>  Pins;\n    ImObjectPool<ImLinkData> Links;\n\n    ImVector<int> NodeDepthOrder;\n\n    // ui related fields\n    ImVec2 Panning;\n    ImVec2 AutoPanningDelta;\n    // Minimum and maximum extents of all content in grid space. Valid after final\n    // ImNodes::EndNode() call.\n    ImRect GridContentBounds;\n\n    ImVector<int> SelectedNodeIndices;\n    ImVector<int> SelectedLinkIndices;\n\n    // Relative origins of selected nodes for snapping of dragged nodes\n    ImVector<ImVec2> SelectedNodeOffsets;\n    // Offset of the primary node origin relative to the mouse cursor.\n    ImVec2           PrimaryNodeOffset;\n\n    ImClickInteractionState ClickInteraction;\n\n    // Mini-map state set by MiniMap()\n\n    bool                                       MiniMapEnabled;\n    ImNodesMiniMapLocation                     MiniMapLocation;\n    float                                      MiniMapSizeFraction;\n    ImNodesMiniMapNodeHoveringCallback         MiniMapNodeHoveringCallback;\n    ImNodesMiniMapNodeHoveringCallbackUserData MiniMapNodeHoveringCallbackUserData;\n\n    // Mini-map state set during EndNodeEditor() call\n\n    ImRect MiniMapRectScreenSpace;\n    ImRect MiniMapContentScreenSpace;\n    float  MiniMapScaling;\n\n    ImNodesEditorContext()\n        : Nodes(), Pins(), Links(), Panning(0.f, 0.f), SelectedNodeIndices(), SelectedLinkIndices(),\n          SelectedNodeOffsets(), PrimaryNodeOffset(0.f, 0.f), ClickInteraction(),\n          MiniMapEnabled(false), MiniMapSizeFraction(0.0f),\n          MiniMapNodeHoveringCallback(NULL), MiniMapNodeHoveringCallbackUserData(NULL),\n          MiniMapScaling(0.0f)\n    {\n    }\n};\n\nstruct ImNodesContext\n{\n    ImNodesEditorContext* DefaultEditorCtx;\n    ImNodesEditorContext* EditorCtx;\n\n    // Canvas draw list and helper state\n    ImDrawList*   CanvasDrawList;\n    ImGuiStorage  NodeIdxToSubmissionIdx;\n    ImVector<int> NodeIdxSubmissionOrder;\n    ImVector<int> NodeIndicesOverlappingWithMouse;\n    ImVector<int> OccludedPinIndices;\n\n    // Canvas extents\n    ImVec2 CanvasOriginScreenSpace;\n    ImRect CanvasRectScreenSpace;\n\n    // Debug helpers\n    ImNodesScope CurrentScope;\n\n    // Configuration state\n    ImNodesIO                        Io;\n    ImNodesStyle                     Style;\n    ImVector<ImNodesColElement>      ColorModifierStack;\n    ImVector<ImNodesStyleVarElement> StyleModifierStack;\n    ImGuiTextBuffer                  TextBuffer;\n\n    int           CurrentAttributeFlags;\n    ImVector<int> AttributeFlagStack;\n\n    // UI element state\n    int CurrentNodeIdx;\n    int CurrentPinIdx;\n    int CurrentAttributeId;\n\n    ImOptionalIndex HoveredNodeIdx;\n    ImOptionalIndex HoveredLinkIdx;\n    ImOptionalIndex HoveredPinIdx;\n\n    ImOptionalIndex DeletedLinkIdx;\n    ImOptionalIndex SnapLinkIdx;\n\n    // Event helper state\n    // TODO: this should be a part of a state machine, and not a member of the global struct.\n    // Unclear what parts of the code this relates to.\n    int ImNodesUIState;\n\n    int  ActiveAttributeId;\n    bool ActiveAttribute;\n\n    // ImGui::IO cache\n\n    ImVec2 MousePos;\n\n    bool  LeftMouseClicked;\n    bool  LeftMouseReleased;\n    bool  AltMouseClicked;\n    bool  LeftMouseDragging;\n    bool  AltMouseDragging;\n    float AltMouseScrollDelta;\n    bool  MultipleSelectModifier;\n};\n\nnamespace IMNODES_NAMESPACE\n{\nstatic inline ImNodesEditorContext& EditorContextGet()\n{\n    // No editor context was set! Did you forget to call ImNodes::CreateContext()?\n    IM_ASSERT(GImNodes->EditorCtx != NULL);\n    return *GImNodes->EditorCtx;\n}\n\n// [SECTION] ObjectPool implementation\n\ntemplate<typename T>\nstatic inline int ObjectPoolFind(const ImObjectPool<T>& objects, const int id)\n{\n    const int index = objects.IdMap.GetInt(static_cast<ImGuiID>(id), -1);\n    return index;\n}\n\ntemplate<typename T>\nstatic inline void ObjectPoolUpdate(ImObjectPool<T>& objects)\n{\n    for (int i = 0; i < objects.InUse.size(); ++i)\n    {\n        const int id = objects.Pool[i].Id;\n\n        if (!objects.InUse[i] && objects.IdMap.GetInt(id, -1) == i)\n        {\n            objects.IdMap.SetInt(id, -1);\n            objects.FreeList.push_back(i);\n            (objects.Pool.Data + i)->~T();\n        }\n    }\n}\n\ntemplate<>\ninline void ObjectPoolUpdate(ImObjectPool<ImNodeData>& nodes)\n{\n    for (int i = 0; i < nodes.InUse.size(); ++i)\n    {\n        if (nodes.InUse[i])\n        {\n            nodes.Pool[i].PinIndices.clear();\n        }\n        else\n        {\n            const int id = nodes.Pool[i].Id;\n\n            if (nodes.IdMap.GetInt(id, -1) == i)\n            {\n                // Remove node idx form depth stack the first time we detect that this idx slot is\n                // unused\n                ImVector<int>&   depth_stack = EditorContextGet().NodeDepthOrder;\n                const int* const elem = depth_stack.find(i);\n                IM_ASSERT(elem != depth_stack.end());\n                depth_stack.erase(elem);\n\n                nodes.IdMap.SetInt(id, -1);\n                nodes.FreeList.push_back(i);\n                (nodes.Pool.Data + i)->~ImNodeData();\n            }\n        }\n    }\n}\n\ntemplate<typename T>\nstatic inline void ObjectPoolReset(ImObjectPool<T>& objects)\n{\n    if (!objects.InUse.empty())\n    {\n        memset(objects.InUse.Data, 0, objects.InUse.size_in_bytes());\n    }\n}\n\ntemplate<typename T>\nstatic inline int ObjectPoolFindOrCreateIndex(ImObjectPool<T>& objects, const int id)\n{\n    int index = objects.IdMap.GetInt(static_cast<ImGuiID>(id), -1);\n\n    // Construct new object\n    if (index == -1)\n    {\n        if (objects.FreeList.empty())\n        {\n            index = objects.Pool.size();\n            IM_ASSERT(objects.Pool.size() == objects.InUse.size());\n            const int new_size = objects.Pool.size() + 1;\n            objects.Pool.resize(new_size);\n            objects.InUse.resize(new_size);\n        }\n        else\n        {\n            index = objects.FreeList.back();\n            objects.FreeList.pop_back();\n        }\n        IM_PLACEMENT_NEW(objects.Pool.Data + index) T(id);\n        objects.IdMap.SetInt(static_cast<ImGuiID>(id), index);\n    }\n\n    // Flag it as used\n    objects.InUse[index] = true;\n\n    return index;\n}\n\ntemplate<>\ninline int ObjectPoolFindOrCreateIndex(ImObjectPool<ImNodeData>& nodes, const int node_id)\n{\n    int node_idx = nodes.IdMap.GetInt(static_cast<ImGuiID>(node_id), -1);\n\n    // Construct new node\n    if (node_idx == -1)\n    {\n        if (nodes.FreeList.empty())\n        {\n            node_idx = nodes.Pool.size();\n            IM_ASSERT(nodes.Pool.size() == nodes.InUse.size());\n            const int new_size = nodes.Pool.size() + 1;\n            nodes.Pool.resize(new_size);\n            nodes.InUse.resize(new_size);\n        }\n        else\n        {\n            node_idx = nodes.FreeList.back();\n            nodes.FreeList.pop_back();\n        }\n        IM_PLACEMENT_NEW(nodes.Pool.Data + node_idx) ImNodeData(node_id);\n        nodes.IdMap.SetInt(static_cast<ImGuiID>(node_id), node_idx);\n\n        ImNodesEditorContext& editor = EditorContextGet();\n        editor.NodeDepthOrder.push_back(node_idx);\n    }\n\n    // Flag node as used\n    nodes.InUse[node_idx] = true;\n\n    return node_idx;\n}\n\ntemplate<typename T>\nstatic inline T& ObjectPoolFindOrCreateObject(ImObjectPool<T>& objects, const int id)\n{\n    const int index = ObjectPoolFindOrCreateIndex(objects, id);\n    return objects.Pool[index];\n}\n} // namespace IMNODES_NAMESPACE\n"
  },
  {
    "path": "Source/External/imgui_tools/implot/implot.cpp",
    "content": "// MIT License\n\n// Copyright (c) 2022 Evan Pezent\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// ImPlot v0.14\n\n/*\n\nAPI BREAKING CHANGES\n====================\nOccasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.\nBelow is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code.\nWhen you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.\nYou can read releases logs https://github.com/epezent/implot/releases for more details.\n\n- 2022/06/19 (0.14) - The signature of ColormapScale has changed to accommodate a new ImPlotColormapScaleFlags parameter\n- 2022/06/17 (0.14) - **IMPORTANT** All PlotX functions now take an ImPlotX_Flags `flags` parameter. Where applicable, it is located before the existing `offset` and `stride` parameters.\n                      If you were providing offset and stride values, you will need to update your function call to include a `flags` value. If you fail to do this, you will likely see\n                      unexpected results or crashes without a compiler warning since these three are all default args. We apologize for the inconvenience, but this was a necessary evil.\n                    - PlotBarsH has been removed; use PlotBars + ImPlotBarsFlags_Horizontal instead\n                    - PlotErrorBarsH has been removed; use PlotErrorBars + ImPlotErrorBarsFlags_Horizontal\n                    - PlotHistogram/PlotHistogram2D signatures changed; `cumulative`, `density`, and `outliers` options now specified via ImPlotHistogramFlags\n                    - PlotPieChart signature changed; `normalize` option now specified via ImPlotPieChartFlags\n                    - PlotText signature changes; `vertical` option now specified via `ImPlotTextFlags_Vertical`\n                    - `PlotVLines` and `PlotHLines` replaced with `PlotInfLines` (+ ImPlotInfLinesFlags_Horizontal )\n                    - arguments of ImPlotGetter have been reversed to be consistent with other API callbacks\n                    - SetupAxisScale + ImPlotScale have replaced ImPlotAxisFlags_LogScale and ImPlotAxisFlags_Time flags\n                    - ImPlotFormatters should now return an int indicating the size written\n                    - the signature of ImPlotGetter has been reversed so that void* user_data is the last argument and consistent with other callbacks\n- 2021/10/19 (0.13) - MAJOR API OVERHAUL! See #168 and #272\n                    - TRIVIAL RENAME:\n                      - ImPlotLimits                              -> ImPlotRect\n                      - ImPlotYAxis_                              -> ImAxis_\n                      - SetPlotYAxis                              -> SetAxis\n                      - BeginDragDropTarget                       -> BeginDragDropTargetPlot\n                      - BeginDragDropSource                       -> BeginDragDropSourcePlot\n                      - ImPlotFlags_NoMousePos                    -> ImPlotFlags_NoMouseText\n                      - SetNextPlotLimits                         -> SetNextAxesLimits\n                      - SetMouseTextLocation                      -> SetupMouseText\n                    - SIGNATURE MODIFIED:\n                      - PixelsToPlot/PlotToPixels                 -> added optional X-Axis arg\n                      - GetPlotMousePos                           -> added optional X-Axis arg\n                      - GetPlotLimits                             -> added optional X-Axis arg\n                      - GetPlotSelection                          -> added optional X-Axis arg\n                      - DragLineX/Y/DragPoint                     -> now takes int id; removed labels (render with Annotation/Tag instead)\n                    - REPLACED:\n                      - IsPlotXAxisHovered/IsPlotXYAxisHovered    -> IsAxisHovered(ImAxis)\n                      - BeginDragDropTargetX/BeginDragDropTargetY -> BeginDragDropTargetAxis(ImAxis)\n                      - BeginDragDropSourceX/BeginDragDropSourceY -> BeginDragDropSourceAxis(ImAxis)\n                      - ImPlotCol_XAxis, ImPlotCol_YAxis1, etc.   -> ImPlotCol_AxisText (push/pop this around SetupAxis to style individual axes)\n                      - ImPlotCol_XAxisGrid, ImPlotCol_Y1AxisGrid -> ImPlotCol_AxisGrid (push/pop this around SetupAxis to style individual axes)\n                      - SetNextPlotLimitsX/Y                      -> SetNextAxisLimits(ImAxis)\n                      - LinkNextPlotLimits                        -> SetNextAxisLinks(ImAxis)\n                      - FitNextPlotAxes                           -> SetNextAxisToFit(ImAxis)/SetNextAxesToFit\n                      - SetLegendLocation                         -> SetupLegend\n                      - ImPlotFlags_NoHighlight                   -> ImPlotLegendFlags_NoHighlight\n                      - ImPlotOrientation                         -> ImPlotLegendFlags_Horizontal\n                      - Annotate                                  -> Annotation\n                    - REMOVED:\n                      - GetPlotQuery, SetPlotQuery, IsPlotQueried -> use DragRect\n                      - SetNextPlotTicksX, SetNextPlotTicksY      -> use SetupAxisTicks\n                      - SetNextPlotFormatX, SetNextPlotFormatY    -> use SetupAxisFormat\n                      - AnnotateClamped                           -> use Annotation(bool clamp = true)\n                    - OBSOLETED:\n                      - BeginPlot (original signature)            -> use simplified signature + Setup API\n- 2021/07/30 (0.12) - The offset argument of `PlotXG` functions was been removed. Implement offsetting in your getter callback instead.\n- 2021/03/08 (0.9)  - SetColormap and PushColormap(ImVec4*) were removed. Use AddColormap for custom colormap support. LerpColormap was changed to SampleColormap.\n                      ShowColormapScale was changed to ColormapScale and requires additional arguments.\n- 2021/03/07 (0.9)  - The signature of ShowColormapScale was modified to accept a ImVec2 size.\n- 2021/02/28 (0.9)  - BeginLegendDragDropSource was changed to BeginDragDropSourceItem with a number of other drag and drop improvements.\n- 2021/01/18 (0.9)  - The default behavior for opening context menus was change from double right-click to single right-click. ImPlotInputMap and related functions were moved\n                      to implot_internal.h due to its immaturity.\n- 2020/10/16 (0.8)  - ImPlotStyleVar_InfoPadding was changed to ImPlotStyleVar_MousePosPadding\n- 2020/09/10 (0.8)  - The single array versions of PlotLine, PlotScatter, PlotStems, and PlotShaded were given additional arguments for x-scale and x0.\n- 2020/09/07 (0.8)  - Plotting functions which accept a custom getter function pointer have been post-fixed with a G (e.g. PlotLineG)\n- 2020/09/06 (0.7)  - Several flags under ImPlotFlags and ImPlotAxisFlags were inverted (e.g. ImPlotFlags_Legend -> ImPlotFlags_NoLegend) so that the default flagset\n                      is simply 0. This more closely matches ImGui's style and makes it easier to enable non-default but commonly used flags (e.g. ImPlotAxisFlags_Time).\n- 2020/08/28 (0.5)  - ImPlotMarker_ can no longer be combined with bitwise OR, |. This features caused unecessary slow-down, and almost no one used it.\n- 2020/08/25 (0.5)  - ImPlotAxisFlags_Scientific was removed. Logarithmic axes automatically uses scientific notation.\n- 2020/08/17 (0.5)  - PlotText was changed so that text is centered horizontally and vertically about the desired point.\n- 2020/08/16 (0.5)  - An ImPlotContext must be explicitly created and destroyed now with `CreateContext` and `DestroyContext`. Previously, the context was statically initialized in this source file.\n- 2020/06/13 (0.4)  - The flags `ImPlotAxisFlag_Adaptive` and `ImPlotFlags_Cull` were removed. Both are now done internally by default.\n- 2020/06/03 (0.3)  - The signature and behavior of PlotPieChart was changed so that data with sum less than 1 can optionally be normalized. The label format can now be specified as well.\n- 2020/06/01 (0.3)  - SetPalette was changed to `SetColormap` for consistency with other plotting libraries. `RestorePalette` was removed. Use `SetColormap(ImPlotColormap_Default)`.\n- 2020/05/31 (0.3)  - Plot functions taking custom ImVec2* getters were removed. Use the ImPlotPoint* getter versions instead.\n- 2020/05/29 (0.3)  - The signature of ImPlotLimits::Contains was changed to take two doubles instead of ImVec2\n- 2020/05/16 (0.2)  - All plotting functions were reverted to being prefixed with \"Plot\" to maintain a consistent VerbNoun style. `Plot` was split into `PlotLine`\n                      and `PlotScatter` (however, `PlotLine` can still be used to plot scatter points as `Plot` did before.). `Bar` is not `PlotBars`, to indicate\n                      that multiple bars will be plotted.\n- 2020/05/13 (0.2)  - `ImMarker` was change to `ImPlotMarker` and `ImAxisFlags` was changed to `ImPlotAxisFlags`.\n- 2020/05/11 (0.2)  - `ImPlotFlags_Selection` was changed to `ImPlotFlags_BoxSelect`\n- 2020/05/11 (0.2)  - The namespace ImGui:: was replaced with ImPlot::. As a result, the following additional changes were made:\n                      - Functions that were prefixed or decorated with the word \"Plot\" have been truncated. E.g., `ImGui::PlotBars` is now just `ImPlot::Bar`.\n                        It should be fairly obvious what was what.\n                      - Some functions have been given names that would have otherwise collided with the ImGui namespace. This has been done to maintain a consistent\n                        style with ImGui. E.g., 'ImGui::PushPlotStyleVar` is now 'ImPlot::PushStyleVar'.\n- 2020/05/10 (0.2)  - The following function/struct names were changes:\n                     - ImPlotRange       -> ImPlotLimits\n                     - GetPlotRange()    -> GetPlotLimits()\n                     - SetNextPlotRange  -> SetNextPlotLimits\n                     - SetNextPlotRangeX -> SetNextPlotLimitsX\n                     - SetNextPlotRangeY -> SetNextPlotLimitsY\n- 2020/05/10 (0.2)  - Plot queries are pixel based by default. Query rects that maintain relative plot position have been removed. This was done to support multi-y-axis.\n\n*/\n\n#define IMGUI_DEFINE_MATH_OPERATORS\n#include \"implot.h\"\n#include \"implot_internal.h\"\n\n#include <stdlib.h>\n\n// Support for pre-1.82 versions. Users on 1.82+ can use 0 (default) flags to mean \"all corners\" but in order to support older versions we are more explicit.\n#if (IMGUI_VERSION_NUM < 18102) && !defined(ImDrawFlags_RoundCornersAll)\n#define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All\n#endif\n\n// Support for pre-1.89.7 versions.\n#if (IMGUI_VERSION_NUM < 18966)\n#define ImGuiButtonFlags_AllowOverlap ImGuiButtonFlags_AllowItemOverlap\n#endif\n\n// Visual Studio warnings\n#ifdef _MSC_VER\n#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen\n#endif\n\n// Clang/GCC warnings with -Weverything\n#if defined(__clang__)\n#pragma clang diagnostic ignored \"-Wformat-nonliteral\"  // warning: format string is not a string literal\n#elif defined(__GNUC__)\n#pragma GCC diagnostic ignored \"-Wformat-nonliteral\"    // warning: format not a string literal, format string not checked\n#endif\n\n// Global plot context\n#ifndef GImPlot\nImPlotContext* GImPlot = nullptr;\n#endif\n\n//-----------------------------------------------------------------------------\n// Struct Implementations\n//-----------------------------------------------------------------------------\n\nImPlotInputMap::ImPlotInputMap() {\n    ImPlot::MapInputDefault(this);\n}\n\nImPlotStyle::ImPlotStyle() {\n\n    LineWeight         = 1;\n    Marker             = ImPlotMarker_None;\n    MarkerSize         = 4;\n    MarkerWeight       = 1;\n    FillAlpha          = 1;\n    ErrorBarSize       = 5;\n    ErrorBarWeight     = 1.5f;\n    DigitalBitHeight   = 8;\n    DigitalBitGap      = 4;\n\n    PlotBorderSize     = 1;\n    MinorAlpha         = 0.25f;\n    MajorTickLen       = ImVec2(10,10);\n    MinorTickLen       = ImVec2(5,5);\n    MajorTickSize      = ImVec2(1,1);\n    MinorTickSize      = ImVec2(1,1);\n    MajorGridSize      = ImVec2(1,1);\n    MinorGridSize      = ImVec2(1,1);\n    PlotPadding        = ImVec2(10,10);\n    LabelPadding       = ImVec2(5,5);\n    LegendPadding      = ImVec2(10,10);\n    LegendInnerPadding = ImVec2(5,5);\n    LegendSpacing      = ImVec2(5,0);\n    MousePosPadding    = ImVec2(10,10);\n    AnnotationPadding  = ImVec2(2,2);\n    FitPadding         = ImVec2(0,0);\n    PlotDefaultSize    = ImVec2(400,300);\n    PlotMinSize        = ImVec2(200,150);\n\n    ImPlot::StyleColorsAuto(this);\n\n    Colormap = ImPlotColormap_Deep;\n\n    UseLocalTime     = false;\n    Use24HourClock   = false;\n    UseISO8601       = false;\n}\n\n//-----------------------------------------------------------------------------\n// Style\n//-----------------------------------------------------------------------------\n\nnamespace ImPlot {\n\nconst char* GetStyleColorName(ImPlotCol col) {\n    static const char* col_names[ImPlotCol_COUNT] = {\n        \"Line\",\n        \"Fill\",\n        \"MarkerOutline\",\n        \"MarkerFill\",\n        \"ErrorBar\",\n        \"FrameBg\",\n        \"PlotBg\",\n        \"PlotBorder\",\n        \"LegendBg\",\n        \"LegendBorder\",\n        \"LegendText\",\n        \"TitleText\",\n        \"InlayText\",\n        \"AxisText\",\n        \"AxisGrid\",\n        \"AxisTick\",\n        \"AxisBg\",\n        \"AxisBgHovered\",\n        \"AxisBgActive\",\n        \"Selection\",\n        \"Crosshairs\"\n    };\n    return col_names[col];\n}\n\nconst char* GetMarkerName(ImPlotMarker marker) {\n    switch (marker) {\n        case ImPlotMarker_None:     return \"None\";\n        case ImPlotMarker_Circle:   return \"Circle\";\n        case ImPlotMarker_Square:   return \"Square\";\n        case ImPlotMarker_Diamond:  return \"Diamond\";\n        case ImPlotMarker_Up:       return \"Up\";\n        case ImPlotMarker_Down:     return \"Down\";\n        case ImPlotMarker_Left:     return \"Left\";\n        case ImPlotMarker_Right:    return \"Right\";\n        case ImPlotMarker_Cross:    return \"Cross\";\n        case ImPlotMarker_Plus:     return \"Plus\";\n        case ImPlotMarker_Asterisk: return \"Asterisk\";\n        default:                    return \"\";\n    }\n}\n\nImVec4 GetAutoColor(ImPlotCol idx) {\n    ImVec4 col(0,0,0,1);\n    switch(idx) {\n        case ImPlotCol_Line:          return col; // these are plot dependent!\n        case ImPlotCol_Fill:          return col; // these are plot dependent!\n        case ImPlotCol_MarkerOutline: return col; // these are plot dependent!\n        case ImPlotCol_MarkerFill:    return col; // these are plot dependent!\n        case ImPlotCol_ErrorBar:      return ImGui::GetStyleColorVec4(ImGuiCol_Text);\n        case ImPlotCol_FrameBg:       return ImGui::GetStyleColorVec4(ImGuiCol_FrameBg);\n        case ImPlotCol_PlotBg:        return ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);\n        case ImPlotCol_PlotBorder:    return ImGui::GetStyleColorVec4(ImGuiCol_Border);\n        case ImPlotCol_LegendBg:      return ImGui::GetStyleColorVec4(ImGuiCol_PopupBg);\n        case ImPlotCol_LegendBorder:  return GetStyleColorVec4(ImPlotCol_PlotBorder);\n        case ImPlotCol_LegendText:    return GetStyleColorVec4(ImPlotCol_InlayText);\n        case ImPlotCol_TitleText:     return ImGui::GetStyleColorVec4(ImGuiCol_Text);\n        case ImPlotCol_InlayText:     return ImGui::GetStyleColorVec4(ImGuiCol_Text);\n        case ImPlotCol_AxisText:      return ImGui::GetStyleColorVec4(ImGuiCol_Text);\n        case ImPlotCol_AxisGrid:      return GetStyleColorVec4(ImPlotCol_AxisText) * ImVec4(1,1,1,0.25f);\n        case ImPlotCol_AxisTick:      return GetStyleColorVec4(ImPlotCol_AxisGrid);\n        case ImPlotCol_AxisBg:        return ImVec4(0,0,0,0);\n        case ImPlotCol_AxisBgHovered: return ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);\n        case ImPlotCol_AxisBgActive:  return ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive);\n        case ImPlotCol_Selection:     return ImVec4(1,1,0,1);\n        case ImPlotCol_Crosshairs:    return GetStyleColorVec4(ImPlotCol_PlotBorder);\n        default: return col;\n    }\n}\n\nstruct ImPlotStyleVarInfo {\n    ImGuiDataType   Type;\n    ImU32           Count;\n    ImU32           Offset;\n    void*           GetVarPtr(ImPlotStyle* style) const { return (void*)((unsigned char*)style + Offset); }\n};\n\nstatic const ImPlotStyleVarInfo GPlotStyleVarInfo[] =\n{\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, LineWeight)         }, // ImPlotStyleVar_LineWeight\n    { ImGuiDataType_S32,   1, (ImU32)IM_OFFSETOF(ImPlotStyle, Marker)             }, // ImPlotStyleVar_Marker\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerSize)         }, // ImPlotStyleVar_MarkerSize\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight)       }, // ImPlotStyleVar_MarkerWeight\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, FillAlpha)          }, // ImPlotStyleVar_FillAlpha\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize)       }, // ImPlotStyleVar_ErrorBarSize\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight)     }, // ImPlotStyleVar_ErrorBarWeight\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight)   }, // ImPlotStyleVar_DigitalBitHeight\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap)      }, // ImPlotStyleVar_DigitalBitGap\n\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotBorderSize)     }, // ImPlotStyleVar_PlotBorderSize\n    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorAlpha)         }, // ImPlotStyleVar_MinorAlpha\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickLen)       }, // ImPlotStyleVar_MajorTickLen\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickLen)       }, // ImPlotStyleVar_MinorTickLen\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickSize)      }, // ImPlotStyleVar_MajorTickSize\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickSize)      }, // ImPlotStyleVar_MinorTickSize\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorGridSize)      }, // ImPlotStyleVar_MajorGridSize\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorGridSize)      }, // ImPlotStyleVar_MinorGridSize\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotPadding)        }, // ImPlotStyleVar_PlotPadding\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LabelPadding)       }, // ImPlotStyleVar_LabelPaddine\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendPadding)      }, // ImPlotStyleVar_LegendPadding\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendSpacing)      }, // ImPlotStyleVar_LegendSpacing\n\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MousePosPadding)    }, // ImPlotStyleVar_MousePosPadding\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, AnnotationPadding)  }, // ImPlotStyleVar_AnnotationPadding\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, FitPadding)         }, // ImPlotStyleVar_FitPadding\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotDefaultSize)    }, // ImPlotStyleVar_PlotDefaultSize\n    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotMinSize)        }  // ImPlotStyleVar_PlotMinSize\n};\n\nstatic const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) {\n    IM_ASSERT(idx >= 0 && idx < ImPlotStyleVar_COUNT);\n    IM_ASSERT(IM_ARRAYSIZE(GPlotStyleVarInfo) == ImPlotStyleVar_COUNT);\n    return &GPlotStyleVarInfo[idx];\n}\n\n//-----------------------------------------------------------------------------\n// Generic Helpers\n//-----------------------------------------------------------------------------\n\nvoid AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char *text_begin, const char* text_end) {\n    // the code below is based loosely on ImFont::RenderText\n    if (!text_end)\n        text_end = text_begin + strlen(text_begin);\n    ImGuiContext& g = *GImGui;\n    ImFont* font = g.Font;\n    // Align to be pixel perfect\n    pos.x = IM_FLOOR(pos.x);\n    pos.y = IM_FLOOR(pos.y);\n    const float scale = g.FontSize / font->FontSize;\n    const char* s = text_begin;\n    int chars_exp = (int)(text_end - s);\n    int chars_rnd = 0;\n    const int vtx_count_max = chars_exp * 4;\n    const int idx_count_max = chars_exp * 6;\n    DrawList->PrimReserve(idx_count_max, vtx_count_max);\n    while (s < text_end) {\n        unsigned int c = (unsigned int)*s;\n        if (c < 0x80) {\n            s += 1;\n        }\n        else {\n            s += ImTextCharFromUtf8(&c, s, text_end);\n            if (c == 0) // Malformed UTF-8?\n                break;\n        }\n        const ImFontGlyph * glyph = font->FindGlyph((ImWchar)c);\n        if (glyph == nullptr) {\n            continue;\n        }\n        DrawList->PrimQuadUV(pos + ImVec2(glyph->Y0, -glyph->X0) * scale, pos + ImVec2(glyph->Y0, -glyph->X1) * scale,\n                             pos + ImVec2(glyph->Y1, -glyph->X1) * scale, pos + ImVec2(glyph->Y1, -glyph->X0) * scale,\n                             ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V0),\n                             ImVec2(glyph->U1, glyph->V1), ImVec2(glyph->U0, glyph->V1),\n                             col);\n        pos.y -= glyph->AdvanceX * scale;\n        chars_rnd++;\n    }\n    // Give back unused vertices\n    int chars_skp = chars_exp-chars_rnd;\n    DrawList->PrimUnreserve(chars_skp*6, chars_skp*4);\n}\n\nvoid AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end) {\n    float txt_ht = ImGui::GetTextLineHeight();\n    const char* title_end = ImGui::FindRenderedTextEnd(text_begin, text_end);\n    ImVec2 text_size;\n    float  y = 0;\n    while (const char* tmp = (const char*)memchr(text_begin, '\\n', title_end-text_begin)) {\n        text_size = ImGui::CalcTextSize(text_begin,tmp,true);\n        DrawList->AddText(ImVec2(top_center.x - text_size.x * 0.5f, top_center.y+y),col,text_begin,tmp);\n        text_begin = tmp + 1;\n        y += txt_ht;\n    }\n    text_size = ImGui::CalcTextSize(text_begin,title_end,true);\n    DrawList->AddText(ImVec2(top_center.x - text_size.x * 0.5f, top_center.y+y),col,text_begin,title_end);\n}\n\ndouble NiceNum(double x, bool round) {\n    double f;\n    double nf;\n    int expv = (int)floor(ImLog10(x));\n    f = x / ImPow(10.0, (double)expv);\n    if (round)\n        if (f < 1.5)\n            nf = 1;\n        else if (f < 3)\n            nf = 2;\n        else if (f < 7)\n            nf = 5;\n        else\n            nf = 10;\n    else if (f <= 1)\n        nf = 1;\n    else if (f <= 2)\n        nf = 2;\n    else if (f <= 5)\n        nf = 5;\n    else\n        nf = 10;\n    return nf * ImPow(10.0, expv);\n}\n\n//-----------------------------------------------------------------------------\n// Context Utils\n//-----------------------------------------------------------------------------\n\nvoid SetImGuiContext(ImGuiContext* ctx) {\n    ImGui::SetCurrentContext(ctx);\n}\n\nImPlotContext* CreateContext() {\n    ImPlotContext* ctx = IM_NEW(ImPlotContext)();\n    Initialize(ctx);\n    if (GImPlot == nullptr)\n        SetCurrentContext(ctx);\n    return ctx;\n}\n\nvoid DestroyContext(ImPlotContext* ctx) {\n    if (ctx == nullptr)\n        ctx = GImPlot;\n    if (GImPlot == ctx)\n        SetCurrentContext(nullptr);\n    IM_DELETE(ctx);\n}\n\nImPlotContext* GetCurrentContext() {\n    return GImPlot;\n}\n\nvoid SetCurrentContext(ImPlotContext* ctx) {\n    GImPlot = ctx;\n}\n\n#define IMPLOT_APPEND_CMAP(name, qual) ctx->ColormapData.Append(#name, name, sizeof(name)/sizeof(ImU32), qual)\n#define IM_RGB(r,g,b) IM_COL32(r,g,b,255)\n\nvoid Initialize(ImPlotContext* ctx) {\n    ResetCtxForNextPlot(ctx);\n    ResetCtxForNextAlignedPlots(ctx);\n    ResetCtxForNextSubplot(ctx);\n\n    const ImU32 Deep[]     = {4289753676, 4283598045, 4285048917, 4283584196, 4289950337, 4284512403, 4291005402, 4287401100, 4285839820, 4291671396                        };\n    const ImU32 Dark[]     = {4280031972, 4290281015, 4283084621, 4288892568, 4278222847, 4281597951, 4280833702, 4290740727, 4288256409                                    };\n    const ImU32 Pastel[]   = {4289639675, 4293119411, 4291161036, 4293184478, 4289124862, 4291624959, 4290631909, 4293712637, 4294111986                                    };\n    const ImU32 Paired[]   = {4293119554, 4290017311, 4287291314, 4281114675, 4288256763, 4280031971, 4285513725, 4278222847, 4292260554, 4288298346, 4288282623, 4280834481};\n    const ImU32 Viridis[]  = {4283695428, 4285867080, 4287054913, 4287455029, 4287526954, 4287402273, 4286883874, 4285579076, 4283552122, 4280737725, 4280674301            };\n    const ImU32 Plasma[]   = {4287039501, 4288480321, 4289200234, 4288941455, 4287638193, 4286072780, 4284638433, 4283139314, 4281771772, 4280667900, 4280416752            };\n    const ImU32 Hot[]      = {4278190144, 4278190208, 4278190271, 4278190335, 4278206719, 4278223103, 4278239231, 4278255615, 4283826175, 4289396735, 4294967295            };\n    const ImU32 Cool[]     = {4294967040, 4294960666, 4294954035, 4294947661, 4294941030, 4294934656, 4294928025, 4294921651, 4294915020, 4294908646, 4294902015            };\n    const ImU32 Pink[]     = {4278190154, 4282532475, 4284308894, 4285690554, 4286879686, 4287870160, 4288794330, 4289651940, 4291685869, 4293392118, 4294967295            };\n    const ImU32 Jet[]      = {4289331200, 4294901760, 4294923520, 4294945280, 4294967040, 4289396565, 4283826090, 4278255615, 4278233855, 4278212095, 4278190335            };\n    const ImU32 Twilight[] = {IM_RGB(226,217,226),IM_RGB(166,191,202),IM_RGB(109,144,192),IM_RGB(95,88,176),IM_RGB(83,30,124),IM_RGB(47,20,54),IM_RGB(100,25,75),IM_RGB(159,60,80),IM_RGB(192,117,94),IM_RGB(208,179,158),IM_RGB(226,217,226)};\n    const ImU32 RdBu[]     = {IM_RGB(103,0,31),IM_RGB(178,24,43),IM_RGB(214,96,77),IM_RGB(244,165,130),IM_RGB(253,219,199),IM_RGB(247,247,247),IM_RGB(209,229,240),IM_RGB(146,197,222),IM_RGB(67,147,195),IM_RGB(33,102,172),IM_RGB(5,48,97)};\n    const ImU32 BrBG[]     = {IM_RGB(84,48,5),IM_RGB(140,81,10),IM_RGB(191,129,45),IM_RGB(223,194,125),IM_RGB(246,232,195),IM_RGB(245,245,245),IM_RGB(199,234,229),IM_RGB(128,205,193),IM_RGB(53,151,143),IM_RGB(1,102,94),IM_RGB(0,60,48)};\n    const ImU32 PiYG[]     = {IM_RGB(142,1,82),IM_RGB(197,27,125),IM_RGB(222,119,174),IM_RGB(241,182,218),IM_RGB(253,224,239),IM_RGB(247,247,247),IM_RGB(230,245,208),IM_RGB(184,225,134),IM_RGB(127,188,65),IM_RGB(77,146,33),IM_RGB(39,100,25)};\n    const ImU32 Spectral[] = {IM_RGB(158,1,66),IM_RGB(213,62,79),IM_RGB(244,109,67),IM_RGB(253,174,97),IM_RGB(254,224,139),IM_RGB(255,255,191),IM_RGB(230,245,152),IM_RGB(171,221,164),IM_RGB(102,194,165),IM_RGB(50,136,189),IM_RGB(94,79,162)};\n    const ImU32 Greys[]    = {IM_COL32_WHITE, IM_COL32_BLACK                                                                                                                };\n\n    IMPLOT_APPEND_CMAP(Deep, true);\n    IMPLOT_APPEND_CMAP(Dark, true);\n    IMPLOT_APPEND_CMAP(Pastel, true);\n    IMPLOT_APPEND_CMAP(Paired, true);\n    IMPLOT_APPEND_CMAP(Viridis, false);\n    IMPLOT_APPEND_CMAP(Plasma, false);\n    IMPLOT_APPEND_CMAP(Hot, false);\n    IMPLOT_APPEND_CMAP(Cool, false);\n    IMPLOT_APPEND_CMAP(Pink, false);\n    IMPLOT_APPEND_CMAP(Jet, false);\n    IMPLOT_APPEND_CMAP(Twilight, false);\n    IMPLOT_APPEND_CMAP(RdBu, false);\n    IMPLOT_APPEND_CMAP(BrBG, false);\n    IMPLOT_APPEND_CMAP(PiYG, false);\n    IMPLOT_APPEND_CMAP(Spectral, false);\n    IMPLOT_APPEND_CMAP(Greys, false);\n}\n\nvoid ResetCtxForNextPlot(ImPlotContext* ctx) {\n    // end child window if it was made\n    if (ctx->ChildWindowMade)\n        ImGui::EndChild();\n    ctx->ChildWindowMade = false;\n    // reset the next plot/item data\n    ctx->NextPlotData.Reset();\n    ctx->NextItemData.Reset();\n    // reset labels\n    ctx->Annotations.Reset();\n    ctx->Tags.Reset();\n    // reset extents/fit\n    ctx->OpenContextThisFrame = false;\n    // reset digital plot items count\n    ctx->DigitalPlotItemCnt = 0;\n    ctx->DigitalPlotOffset = 0;\n    // nullify plot\n    ctx->CurrentPlot  = nullptr;\n    ctx->CurrentItem  = nullptr;\n    ctx->PreviousItem = nullptr;\n}\n\nvoid ResetCtxForNextAlignedPlots(ImPlotContext* ctx) {\n    ctx->CurrentAlignmentH = nullptr;\n    ctx->CurrentAlignmentV = nullptr;\n}\n\nvoid ResetCtxForNextSubplot(ImPlotContext* ctx) {\n    ctx->CurrentSubplot      = nullptr;\n    ctx->CurrentAlignmentH   = nullptr;\n    ctx->CurrentAlignmentV   = nullptr;\n}\n\n//-----------------------------------------------------------------------------\n// Plot Utils\n//-----------------------------------------------------------------------------\n\nImPlotPlot* GetPlot(const char* title) {\n    ImGuiWindow*   Window = GImGui->CurrentWindow;\n    const ImGuiID  ID     = Window->GetID(title);\n    return GImPlot->Plots.GetByKey(ID);\n}\n\nImPlotPlot* GetCurrentPlot() {\n    return GImPlot->CurrentPlot;\n}\n\nvoid BustPlotCache() {\n    ImPlotContext& gp = *GImPlot;\n    gp.Plots.Clear();\n    gp.Subplots.Clear();\n}\n\n//-----------------------------------------------------------------------------\n// Legend Utils\n//-----------------------------------------------------------------------------\n\nImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation loc, const ImVec2& pad) {\n    ImVec2 pos;\n    if (ImHasFlag(loc, ImPlotLocation_West) && !ImHasFlag(loc, ImPlotLocation_East))\n        pos.x = outer_rect.Min.x + pad.x;\n    else if (!ImHasFlag(loc, ImPlotLocation_West) && ImHasFlag(loc, ImPlotLocation_East))\n        pos.x = outer_rect.Max.x - pad.x - inner_size.x;\n    else\n        pos.x = outer_rect.GetCenter().x - inner_size.x * 0.5f;\n    // legend reference point y\n    if (ImHasFlag(loc, ImPlotLocation_North) && !ImHasFlag(loc, ImPlotLocation_South))\n        pos.y = outer_rect.Min.y + pad.y;\n    else if (!ImHasFlag(loc, ImPlotLocation_North) && ImHasFlag(loc, ImPlotLocation_South))\n        pos.y = outer_rect.Max.y - pad.y - inner_size.y;\n    else\n        pos.y = outer_rect.GetCenter().y - inner_size.y * 0.5f;\n    pos.x = IM_ROUND(pos.x);\n    pos.y = IM_ROUND(pos.y);\n    return pos;\n}\n\nImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical) {\n    // vars\n    const int   nItems      = items.GetLegendCount();\n    const float txt_ht      = ImGui::GetTextLineHeight();\n    const float icon_size   = txt_ht;\n    // get label max width\n    float max_label_width = 0;\n    float sum_label_width = 0;\n    for (int i = 0; i < nItems; ++i) {\n        const char* label       = items.GetLegendLabel(i);\n        const float label_width = ImGui::CalcTextSize(label, nullptr, true).x;\n        max_label_width         = label_width > max_label_width ? label_width : max_label_width;\n        sum_label_width        += label_width;\n    }\n    // calc legend size\n    const ImVec2 legend_size = vertical ?\n                               ImVec2(pad.x * 2 + icon_size + max_label_width, pad.y * 2 + nItems * txt_ht + (nItems - 1) * spacing.y) :\n                               ImVec2(pad.x * 2 + icon_size * nItems + sum_label_width + (nItems - 1) * spacing.x, pad.y * 2 + txt_ht);\n    return legend_size;\n}\n\nint LegendSortingComp(const void* _a, const void* _b) {\n    ImPlotItemGroup* items = GImPlot->SortItems;\n    const int a = *(const int*)_a;\n    const int b = *(const int*)_b;\n    const char* label_a = items->GetLegendLabel(a);\n    const char* label_b = items->GetLegendLabel(b);\n    return strcmp(label_a,label_b);\n}\n\nbool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool hovered, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList) {\n    // vars\n    const float txt_ht      = ImGui::GetTextLineHeight();\n    const float icon_size   = txt_ht;\n    const float icon_shrink = 2;\n    ImU32 col_txt           = GetStyleColorU32(ImPlotCol_LegendText);\n    ImU32 col_txt_dis       = ImAlphaU32(col_txt, 0.25f);\n    // render each legend item\n    float sum_label_width = 0;\n    bool any_item_hovered = false;\n\n    const int num_items = items.GetLegendCount();\n    if (num_items < 1)\n        return hovered;\n    // build render order\n    ImPlotContext& gp = *GImPlot;\n    ImVector<int>& indices = gp.TempInt1;\n    indices.resize(num_items);\n    for (int i = 0; i < num_items; ++i)\n        indices[i] = i;\n    if (ImHasFlag(items.Legend.Flags, ImPlotLegendFlags_Sort) && num_items > 1) {\n        gp.SortItems = &items;\n        qsort(indices.Data, num_items, sizeof(int), LegendSortingComp);\n    }\n    // render\n    for (int i = 0; i < num_items; ++i) {\n        const int idx           = indices[i];\n        ImPlotItem* item        = items.GetLegendItem(idx);\n        const char* label       = items.GetLegendLabel(idx);\n        const float label_width = ImGui::CalcTextSize(label, nullptr, true).x;\n        const ImVec2 top_left   = vertical ?\n                                  legend_bb.Min + pad + ImVec2(0, i * (txt_ht + spacing.y)) :\n                                  legend_bb.Min + pad + ImVec2(i * (icon_size + spacing.x) + sum_label_width, 0);\n        sum_label_width        += label_width;\n        ImRect icon_bb;\n        icon_bb.Min = top_left + ImVec2(icon_shrink,icon_shrink);\n        icon_bb.Max = top_left + ImVec2(icon_size - icon_shrink, icon_size - icon_shrink);\n        ImRect label_bb;\n        label_bb.Min = top_left;\n        label_bb.Max = top_left + ImVec2(label_width + icon_size, icon_size);\n        ImU32 col_txt_hl;\n        ImU32 col_item = ImAlphaU32(item->Color,1);\n\n        ImRect button_bb(icon_bb.Min, label_bb.Max);\n\n        ImGui::KeepAliveID(item->ID);\n\n        bool item_hov = false;\n        bool item_hld = false;\n        bool item_clk = ImHasFlag(items.Legend.Flags, ImPlotLegendFlags_NoButtons)\n                      ? false\n                      : ImGui::ButtonBehavior(button_bb, item->ID, &item_hov, &item_hld);\n\n        if (item_clk)\n            item->Show = !item->Show;\n\n\n        const bool can_hover = (item_hov)\n                             && (!ImHasFlag(items.Legend.Flags, ImPlotLegendFlags_NoHighlightItem)\n                             || !ImHasFlag(items.Legend.Flags, ImPlotLegendFlags_NoHighlightAxis));\n\n        if (can_hover) {\n            item->LegendHoverRect.Min = icon_bb.Min;\n            item->LegendHoverRect.Max = label_bb.Max;\n            item->LegendHovered = true;\n            col_txt_hl = ImMixU32(col_txt, col_item, 64);\n            any_item_hovered = true;\n        }\n        else {\n            col_txt_hl = ImGui::GetColorU32(col_txt);\n        }\n        ImU32 col_icon;\n        if (item_hld)\n            col_icon = item->Show ? ImAlphaU32(col_item,0.5f) : ImGui::GetColorU32(ImGuiCol_TextDisabled, 0.5f);\n        else if (item_hov)\n            col_icon = item->Show ? ImAlphaU32(col_item,0.75f) : ImGui::GetColorU32(ImGuiCol_TextDisabled, 0.75f);\n        else\n            col_icon = item->Show ? col_item : col_txt_dis;\n\n        DrawList.AddRectFilled(icon_bb.Min, icon_bb.Max, col_icon);\n        const char* text_display_end = ImGui::FindRenderedTextEnd(label, nullptr);\n        if (label != text_display_end)\n            DrawList.AddText(top_left + ImVec2(icon_size, 0), item->Show ? col_txt_hl  : col_txt_dis, label, text_display_end);\n    }\n    return hovered && !any_item_hovered;\n}\n\n//-----------------------------------------------------------------------------\n// Locators\n//-----------------------------------------------------------------------------\n\nstatic const float TICK_FILL_X = 0.8f;\nstatic const float TICK_FILL_Y = 1.0f;\n\nvoid Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data) {\n    if (range.Min == range.Max)\n        return;\n    const int nMinor        = 10;\n    const int nMajor        = ImMax(2, (int)IM_ROUND(pixels / (vertical ? 300.0f : 400.0f)));\n    const double nice_range = NiceNum(range.Size() * 0.99, false);\n    const double interval   = NiceNum(nice_range / (nMajor - 1), true);\n    const double graphmin   = floor(range.Min / interval) * interval;\n    const double graphmax   = ceil(range.Max / interval) * interval;\n    bool first_major_set    = false;\n    int  first_major_idx    = 0;\n    const int idx0 = ticker.TickCount(); // ticker may have user custom ticks\n    ImVec2 total_size(0,0);\n    for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) {\n        // is this zero? combat zero formatting issues\n        if (major-interval < 0 && major+interval > 0)\n            major = 0;\n        if (range.Contains(major)) {\n            if (!first_major_set) {\n                first_major_idx = ticker.TickCount();\n                first_major_set = true;\n            }\n            total_size += ticker.AddTick(major, true, 0, true, formatter, formatter_data).LabelSize;\n        }\n        for (int i = 1; i < nMinor; ++i) {\n            double minor = major + i * interval / nMinor;\n            if (range.Contains(minor)) {\n                total_size += ticker.AddTick(minor, false, 0, true, formatter, formatter_data).LabelSize;\n            }\n        }\n    }\n    // prune if necessary\n    if ((!vertical && total_size.x > pixels*TICK_FILL_X) || (vertical && total_size.y > pixels*TICK_FILL_Y)) {\n        for (int i = first_major_idx-1; i >= idx0; i -= 2)\n            ticker.Ticks[i].ShowLabel = false;\n        for (int i = first_major_idx+1; i < ticker.TickCount(); i += 2)\n            ticker.Ticks[i].ShowLabel = false;\n    }\n}\n\nbool CalcLogarithmicExponents(const ImPlotRange& range, float pix, bool vertical, int& exp_min, int& exp_max, int& exp_step) {\n    if (range.Min * range.Max > 0) {\n        const int nMajor = vertical ? ImMax(2, (int)IM_ROUND(pix * 0.02f)) : ImMax(2, (int)IM_ROUND(pix * 0.01f)); // TODO: magic numbers\n        double log_min = ImLog10(ImAbs(range.Min));\n        double log_max = ImLog10(ImAbs(range.Max));\n        double log_a = ImMin(log_min,log_max);\n        double log_b = ImMax(log_min,log_max);\n        exp_step  = ImMax(1,(int)(log_b - log_a) / nMajor);\n        exp_min   = (int)log_a;\n        exp_max   = (int)log_b;\n        if (exp_step != 1) {\n            while(exp_step % 3 != 0)       exp_step++; // make step size multiple of three\n            while(exp_min % exp_step != 0) exp_min--;  // decrease exp_min until exp_min + N * exp_step will be 0\n        }\n        return true;\n    }\n    return false;\n}\n\nvoid AddTicksLogarithmic(const ImPlotRange& range, int exp_min, int exp_max, int exp_step, ImPlotTicker& ticker, ImPlotFormatter formatter, void* data) {\n    const double sign = ImSign(range.Max);\n    for (int e = exp_min - exp_step; e < (exp_max + exp_step); e += exp_step) {\n        double major1 = sign*ImPow(10, (double)(e));\n        double major2 = sign*ImPow(10, (double)(e + 1));\n        double interval = (major2 - major1) / 9;\n        if (major1 >= (range.Min - DBL_EPSILON) && major1 <= (range.Max + DBL_EPSILON))\n            ticker.AddTick(major1, true, 0, true, formatter, data);\n        for (int j = 0; j < exp_step; ++j) {\n            major1 = sign*ImPow(10, (double)(e+j));\n            major2 = sign*ImPow(10, (double)(e+j+1));\n            interval = (major2 - major1) / 9;\n            for (int i = 1; i < (9 + (int)(j < (exp_step - 1))); ++i) {\n                double minor = major1 + i * interval;\n                if (minor >= (range.Min - DBL_EPSILON) && minor <= (range.Max + DBL_EPSILON))\n                    ticker.AddTick(minor, false, 0, false, formatter, data);\n            }\n        }\n    }\n}\n\nvoid Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data) {\n    int exp_min, exp_max, exp_step;\n    if (CalcLogarithmicExponents(range, pixels, vertical, exp_min, exp_max, exp_step))\n        AddTicksLogarithmic(range, exp_min, exp_max, exp_step, ticker, formatter, formatter_data);\n}\n\nfloat CalcSymLogPixel(double plt, const ImPlotRange& range, float pixels) {\n    double scaleToPixels = pixels / range.Size();\n    double scaleMin      = TransformForward_SymLog(range.Min,nullptr);\n    double scaleMax      = TransformForward_SymLog(range.Max,nullptr);\n    double s             = TransformForward_SymLog(plt, nullptr);\n    double t             = (s - scaleMin) / (scaleMax - scaleMin);\n    plt                  = range.Min + range.Size() * t;\n\n    return (float)(0 + scaleToPixels * (plt - range.Min));\n}\n\nvoid Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data) {\n    if (range.Min >= -1 && range.Max <= 1) {\n        Locator_Default(ticker, range, pixels, vertical, formatter, formatter_data);\n    }\n    else if (range.Min * range.Max < 0) { // cross zero\n        const float pix_min = 0;\n        const float pix_max = pixels;\n        const float pix_p1  = CalcSymLogPixel(1, range, pixels);\n        const float pix_n1  = CalcSymLogPixel(-1, range, pixels);\n        int exp_min_p, exp_max_p, exp_step_p;\n        int exp_min_n, exp_max_n, exp_step_n;\n        CalcLogarithmicExponents(ImPlotRange(1,range.Max), ImAbs(pix_max-pix_p1),vertical,exp_min_p,exp_max_p,exp_step_p);\n        CalcLogarithmicExponents(ImPlotRange(range.Min,-1),ImAbs(pix_n1-pix_min),vertical,exp_min_n,exp_max_n,exp_step_n);\n        int exp_step = ImMax(exp_step_n, exp_step_p);\n        ticker.AddTick(0,true,0,true,formatter,formatter_data);\n        AddTicksLogarithmic(ImPlotRange(1,range.Max), exp_min_p,exp_max_p,exp_step,ticker,formatter,formatter_data);\n        AddTicksLogarithmic(ImPlotRange(range.Min,-1),exp_min_n,exp_max_n,exp_step,ticker,formatter,formatter_data);\n    }\n    else {\n        Locator_Log10(ticker, range, pixels, vertical, formatter, formatter_data);\n    }\n}\n\nvoid AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTicker& ticker, ImPlotFormatter formatter, void* data) {\n    for (int i = 0; i < n; ++i) {\n        if (labels != nullptr)\n            ticker.AddTick(values[i], false, 0, true, labels[i]);\n        else\n            ticker.AddTick(values[i], false, 0, true, formatter, data);\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Time Ticks and Utils\n//-----------------------------------------------------------------------------\n\n// this may not be thread safe?\nstatic const double TimeUnitSpans[ImPlotTimeUnit_COUNT] = {\n    0.000001,\n    0.001,\n    1,\n    60,\n    3600,\n    86400,\n    2629800,\n    31557600\n};\n\ninline ImPlotTimeUnit GetUnitForRange(double range) {\n    static double cutoffs[ImPlotTimeUnit_COUNT] = {0.001, 1, 60, 3600, 86400, 2629800, 31557600, IMPLOT_MAX_TIME};\n    for (int i = 0; i < ImPlotTimeUnit_COUNT; ++i) {\n        if (range <= cutoffs[i])\n            return (ImPlotTimeUnit)i;\n    }\n    return ImPlotTimeUnit_Yr;\n}\n\ninline int LowerBoundStep(int max_divs, const int* divs, const int* step, int size) {\n    if (max_divs < divs[0])\n        return 0;\n    for (int i = 1; i < size; ++i) {\n        if (max_divs < divs[i])\n            return step[i-1];\n    }\n    return step[size-1];\n}\n\ninline int GetTimeStep(int max_divs, ImPlotTimeUnit unit) {\n    if (unit == ImPlotTimeUnit_Ms || unit == ImPlotTimeUnit_Us) {\n        static const int step[] = {500,250,200,100,50,25,20,10,5,2,1};\n        static const int divs[] = {2,4,5,10,20,40,50,100,200,500,1000};\n        return LowerBoundStep(max_divs, divs, step, 11);\n    }\n    if (unit == ImPlotTimeUnit_S || unit == ImPlotTimeUnit_Min) {\n        static const int step[] = {30,15,10,5,1};\n        static const int divs[] = {2,4,6,12,60};\n        return LowerBoundStep(max_divs, divs, step, 5);\n    }\n    else if (unit == ImPlotTimeUnit_Hr) {\n        static const int step[] = {12,6,3,2,1};\n        static const int divs[] = {2,4,8,12,24};\n        return LowerBoundStep(max_divs, divs, step, 5);\n    }\n    else if (unit == ImPlotTimeUnit_Day) {\n        static const int step[] = {14,7,2,1};\n        static const int divs[] = {2,4,14,28};\n        return LowerBoundStep(max_divs, divs, step, 4);\n    }\n    else if (unit == ImPlotTimeUnit_Mo) {\n        static const int step[] = {6,3,2,1};\n        static const int divs[] = {2,4,6,12};\n        return LowerBoundStep(max_divs, divs, step, 4);\n    }\n    return 0;\n}\n\nImPlotTime MkGmtTime(struct tm *ptm) {\n    ImPlotTime t;\n#ifdef _WIN32\n    t.S = _mkgmtime(ptm);\n#else\n    t.S = timegm(ptm);\n#endif\n    if (t.S < 0)\n        t.S = 0;\n    return t;\n}\n\ntm* GetGmtTime(const ImPlotTime& t, tm* ptm)\n{\n#ifdef _WIN32\n  if (gmtime_s(ptm, &t.S) == 0)\n    return ptm;\n  else\n    return nullptr;\n#else\n  return gmtime_r(&t.S, ptm);\n#endif\n}\n\nImPlotTime MkLocTime(struct tm *ptm) {\n    ImPlotTime t;\n    t.S = mktime(ptm);\n    if (t.S < 0)\n        t.S = 0;\n    return t;\n}\n\ntm* GetLocTime(const ImPlotTime& t, tm* ptm) {\n#ifdef _WIN32\n  if (localtime_s(ptm, &t.S) == 0)\n    return ptm;\n  else\n    return nullptr;\n#else\n    return localtime_r(&t.S, ptm);\n#endif\n}\n\ninline ImPlotTime MkTime(struct tm *ptm) {\n    if (GetStyle().UseLocalTime)\n        return MkLocTime(ptm);\n    else\n        return MkGmtTime(ptm);\n}\n\ninline tm* GetTime(const ImPlotTime& t, tm* ptm) {\n    if (GetStyle().UseLocalTime)\n        return GetLocTime(t,ptm);\n    else\n        return GetGmtTime(t,ptm);\n}\n\nImPlotTime MakeTime(int year, int month, int day, int hour, int min, int sec, int us) {\n    tm& Tm = GImPlot->Tm;\n\n    int yr = year - 1900;\n    if (yr < 0)\n        yr = 0;\n\n    sec  = sec + us / 1000000;\n    us   = us % 1000000;\n\n    Tm.tm_sec  = sec;\n    Tm.tm_min  = min;\n    Tm.tm_hour = hour;\n    Tm.tm_mday = day;\n    Tm.tm_mon  = month;\n    Tm.tm_year = yr;\n\n    ImPlotTime t = MkTime(&Tm);\n\n    t.Us = us;\n    return t;\n}\n\nint GetYear(const ImPlotTime& t) {\n    tm& Tm = GImPlot->Tm;\n    GetTime(t, &Tm);\n    return Tm.tm_year + 1900;\n}\n\nImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {\n    tm& Tm = GImPlot->Tm;\n    ImPlotTime t_out = t;\n    switch(unit) {\n        case ImPlotTimeUnit_Us:  t_out.Us += count;         break;\n        case ImPlotTimeUnit_Ms:  t_out.Us += count * 1000;  break;\n        case ImPlotTimeUnit_S:   t_out.S  += count;         break;\n        case ImPlotTimeUnit_Min: t_out.S  += count * 60;    break;\n        case ImPlotTimeUnit_Hr:  t_out.S  += count * 3600;  break;\n        case ImPlotTimeUnit_Day: t_out.S  += count * 86400; break;\n        case ImPlotTimeUnit_Mo:  for (int i = 0; i < abs(count); ++i) {\n                                     GetTime(t_out, &Tm);\n                                     if (count > 0)\n                                        t_out.S += 86400 * GetDaysInMonth(Tm.tm_year + 1900, Tm.tm_mon);\n                                     else if (count < 0)\n                                        t_out.S -= 86400 * GetDaysInMonth(Tm.tm_year + 1900 - (Tm.tm_mon == 0 ? 1 : 0), Tm.tm_mon == 0 ? 11 : Tm.tm_mon - 1); // NOT WORKING\n                                 }\n                                 break;\n        case ImPlotTimeUnit_Yr:  for (int i = 0; i < abs(count); ++i) {\n                                    if (count > 0)\n                                        t_out.S += 86400 * (365 + (int)IsLeapYear(GetYear(t_out)));\n                                    else if (count < 0)\n                                        t_out.S -= 86400 * (365 + (int)IsLeapYear(GetYear(t_out) - 1));\n                                    // this is incorrect if leap year and we are past Feb 28\n                                 }\n                                 break;\n        default:                 break;\n    }\n    t_out.RollOver();\n    return t_out;\n}\n\nImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {\n    ImPlotContext& gp = *GImPlot;\n    GetTime(t, &gp.Tm);\n    switch (unit) {\n        case ImPlotTimeUnit_S:   return ImPlotTime(t.S, 0);\n        case ImPlotTimeUnit_Ms:  return ImPlotTime(t.S, (t.Us / 1000) * 1000);\n        case ImPlotTimeUnit_Us:  return t;\n        case ImPlotTimeUnit_Yr:  gp.Tm.tm_mon  = 0; // fall-through\n        case ImPlotTimeUnit_Mo:  gp.Tm.tm_mday = 1; // fall-through\n        case ImPlotTimeUnit_Day: gp.Tm.tm_hour = 0; // fall-through\n        case ImPlotTimeUnit_Hr:  gp.Tm.tm_min  = 0; // fall-through\n        case ImPlotTimeUnit_Min: gp.Tm.tm_sec  = 0; break;\n        default:                 return t;\n    }\n    return MkTime(&gp.Tm);\n}\n\nImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit) {\n    return AddTime(FloorTime(t, unit), unit, 1);\n}\n\nImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit) {\n    ImPlotTime t1 = FloorTime(t, unit);\n    ImPlotTime t2 = AddTime(t1,unit,1);\n    if (t1.S == t2.S)\n        return t.Us - t1.Us < t2.Us - t.Us ? t1 : t2;\n    return t.S - t1.S < t2.S - t.S ? t1 : t2;\n}\n\nImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& tod_part) {\n    ImPlotContext& gp = *GImPlot;\n    tm& Tm = gp.Tm;\n    GetTime(date_part, &gp.Tm);\n    int y = Tm.tm_year;\n    int m = Tm.tm_mon;\n    int d = Tm.tm_mday;\n    GetTime(tod_part, &gp.Tm);\n    Tm.tm_year = y;\n    Tm.tm_mon  = m;\n    Tm.tm_mday = d;\n    ImPlotTime t = MkTime(&Tm);\n    t.Us = tod_part.Us;\n    return t;\n}\n\n// TODO: allow users to define these\nstatic const char* MONTH_NAMES[]  = {\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"};\nstatic const char* WD_ABRVS[]     = {\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"};\nstatic const char* MONTH_ABRVS[]  = {\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"};\n\nint FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk) {\n    tm& Tm = GImPlot->Tm;\n    GetTime(t, &Tm);\n    const int us   = t.Us % 1000;\n    const int ms   = t.Us / 1000;\n    const int sec  = Tm.tm_sec;\n    const int min  = Tm.tm_min;\n    if (use_24_hr_clk) {\n        const int hr   = Tm.tm_hour;\n        switch(fmt) {\n            case ImPlotTimeFmt_Us:        return ImFormatString(buffer, size, \".%03d %03d\", ms, us);\n            case ImPlotTimeFmt_SUs:       return ImFormatString(buffer, size, \":%02d.%03d %03d\", sec, ms, us);\n            case ImPlotTimeFmt_SMs:       return ImFormatString(buffer, size, \":%02d.%03d\", sec, ms);\n            case ImPlotTimeFmt_S:         return ImFormatString(buffer, size, \":%02d\", sec);\n            case ImPlotTimeFmt_MinSMs:    return ImFormatString(buffer, size, \":%02d:%02d.%03d\", min, sec, ms);\n            case ImPlotTimeFmt_HrMinSMs:  return ImFormatString(buffer, size, \"%02d:%02d:%02d.%03d\", hr, min, sec, ms);\n            case ImPlotTimeFmt_HrMinS:    return ImFormatString(buffer, size, \"%02d:%02d:%02d\", hr, min, sec);\n            case ImPlotTimeFmt_HrMin:     return ImFormatString(buffer, size, \"%02d:%02d\", hr, min);\n            case ImPlotTimeFmt_Hr:        return ImFormatString(buffer, size, \"%02d:00\", hr);\n            default:                      return 0;\n        }\n    }\n    else {\n        const char* ap = Tm.tm_hour < 12 ? \"am\" : \"pm\";\n        const int hr   = (Tm.tm_hour == 0 || Tm.tm_hour == 12) ? 12 : Tm.tm_hour % 12;\n        switch(fmt) {\n            case ImPlotTimeFmt_Us:        return ImFormatString(buffer, size, \".%03d %03d\", ms, us);\n            case ImPlotTimeFmt_SUs:       return ImFormatString(buffer, size, \":%02d.%03d %03d\", sec, ms, us);\n            case ImPlotTimeFmt_SMs:       return ImFormatString(buffer, size, \":%02d.%03d\", sec, ms);\n            case ImPlotTimeFmt_S:         return ImFormatString(buffer, size, \":%02d\", sec);\n            case ImPlotTimeFmt_MinSMs:    return ImFormatString(buffer, size, \":%02d:%02d.%03d\", min, sec, ms);\n            case ImPlotTimeFmt_HrMinSMs:  return ImFormatString(buffer, size, \"%d:%02d:%02d.%03d%s\", hr, min, sec, ms, ap);\n            case ImPlotTimeFmt_HrMinS:    return ImFormatString(buffer, size, \"%d:%02d:%02d%s\", hr, min, sec, ap);\n            case ImPlotTimeFmt_HrMin:     return ImFormatString(buffer, size, \"%d:%02d%s\", hr, min, ap);\n            case ImPlotTimeFmt_Hr:        return ImFormatString(buffer, size, \"%d%s\", hr, ap);\n            default:                      return 0;\n        }\n    }\n}\n\nint FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601) {\n    tm& Tm = GImPlot->Tm;\n    GetTime(t, &Tm);\n    const int day  = Tm.tm_mday;\n    const int mon  = Tm.tm_mon + 1;\n    const int year = Tm.tm_year + 1900;\n    const int yr   = year % 100;\n    if (use_iso_8601) {\n        switch (fmt) {\n            case ImPlotDateFmt_DayMo:   return ImFormatString(buffer, size, \"--%02d-%02d\", mon, day);\n            case ImPlotDateFmt_DayMoYr: return ImFormatString(buffer, size, \"%d-%02d-%02d\", year, mon, day);\n            case ImPlotDateFmt_MoYr:    return ImFormatString(buffer, size, \"%d-%02d\", year, mon);\n            case ImPlotDateFmt_Mo:      return ImFormatString(buffer, size, \"--%02d\", mon);\n            case ImPlotDateFmt_Yr:      return ImFormatString(buffer, size, \"%d\", year);\n            default:                    return 0;\n        }\n    }\n    else {\n        switch (fmt) {\n            case ImPlotDateFmt_DayMo:   return ImFormatString(buffer, size, \"%d/%d\", mon, day);\n            case ImPlotDateFmt_DayMoYr: return ImFormatString(buffer, size, \"%d/%d/%02d\", mon, day, yr);\n            case ImPlotDateFmt_MoYr:    return ImFormatString(buffer, size, \"%s %d\", MONTH_ABRVS[Tm.tm_mon], year);\n            case ImPlotDateFmt_Mo:      return ImFormatString(buffer, size, \"%s\", MONTH_ABRVS[Tm.tm_mon]);\n            case ImPlotDateFmt_Yr:      return ImFormatString(buffer, size, \"%d\", year);\n            default:                    return 0;\n        }\n    }\n }\n\nint FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeSpec fmt) {\n    int written = 0;\n    if (fmt.Date != ImPlotDateFmt_None)\n        written += FormatDate(t, buffer, size, fmt.Date, fmt.UseISO8601);\n    if (fmt.Time != ImPlotTimeFmt_None) {\n        if (fmt.Date != ImPlotDateFmt_None)\n            buffer[written++] = ' ';\n        written += FormatTime(t, &buffer[written], size - written, fmt.Time, fmt.Use24HourClock);\n    }\n    return written;\n}\n\ninline float GetDateTimeWidth(ImPlotDateTimeSpec fmt) {\n    static const ImPlotTime t_max_width = MakeTime(2888, 12, 22, 12, 58, 58, 888888); // best guess at time that maximizes pixel width\n    char buffer[32];\n    FormatDateTime(t_max_width, buffer, 32, fmt);\n    return ImGui::CalcTextSize(buffer).x;\n}\n\ninline bool TimeLabelSame(const char* l1, const char* l2) {\n    size_t len1 = strlen(l1);\n    size_t len2 = strlen(l2);\n    size_t n  = len1 < len2 ? len1 : len2;\n    return strcmp(l1 + len1 - n, l2 + len2 - n) == 0;\n}\n\nstatic const ImPlotDateTimeSpec TimeFormatLevel0[ImPlotTimeUnit_COUNT] = {\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,  ImPlotTimeFmt_Us),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,  ImPlotTimeFmt_SMs),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,  ImPlotTimeFmt_S),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,  ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,  ImPlotTimeFmt_Hr),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMo, ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_Mo,    ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_Yr,    ImPlotTimeFmt_None)\n};\n\nstatic const ImPlotDateTimeSpec TimeFormatLevel1[ImPlotTimeUnit_COUNT] = {\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,    ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,    ImPlotTimeFmt_HrMinS),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,    ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,    ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_Yr,      ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_Yr,      ImPlotTimeFmt_None)\n};\n\nstatic const ImPlotDateTimeSpec TimeFormatLevel1First[ImPlotTimeUnit_COUNT] = {\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_HrMinS),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_HrMinS),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr, ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_Yr,      ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_Yr,      ImPlotTimeFmt_None)\n};\n\nstatic const ImPlotDateTimeSpec TimeFormatMouseCursor[ImPlotTimeUnit_COUNT] = {\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,     ImPlotTimeFmt_Us),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,     ImPlotTimeFmt_SUs),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,     ImPlotTimeFmt_SMs),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,     ImPlotTimeFmt_HrMinS),\n    ImPlotDateTimeSpec(ImPlotDateFmt_None,     ImPlotTimeFmt_HrMin),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMo,    ImPlotTimeFmt_Hr),\n    ImPlotDateTimeSpec(ImPlotDateFmt_DayMoYr,  ImPlotTimeFmt_None),\n    ImPlotDateTimeSpec(ImPlotDateFmt_MoYr,     ImPlotTimeFmt_None)\n};\n\ninline ImPlotDateTimeSpec GetDateTimeFmt(const ImPlotDateTimeSpec* ctx, ImPlotTimeUnit idx) {\n    ImPlotStyle& style     = GetStyle();\n    ImPlotDateTimeSpec fmt  = ctx[idx];\n    fmt.UseISO8601         = style.UseISO8601;\n    fmt.Use24HourClock     = style.Use24HourClock;\n    return fmt;\n}\n\nvoid Locator_Time(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data) {\n    IM_ASSERT_USER_ERROR(vertical == false, \"Cannot locate Time ticks on vertical axis!\");\n    (void)vertical;\n    // get units for level 0 and level 1 labels\n    const ImPlotTimeUnit unit0 = GetUnitForRange(range.Size() / (pixels / 100)); // level = 0 (top)\n    const ImPlotTimeUnit unit1 = ImClamp(unit0 + 1, 0, ImPlotTimeUnit_COUNT-1);  // level = 1 (bottom)\n    // get time format specs\n    const ImPlotDateTimeSpec fmt0 = GetDateTimeFmt(TimeFormatLevel0, unit0);\n    const ImPlotDateTimeSpec fmt1 = GetDateTimeFmt(TimeFormatLevel1, unit1);\n    const ImPlotDateTimeSpec fmtf = GetDateTimeFmt(TimeFormatLevel1First, unit1);\n    // min max times\n    const ImPlotTime t_min = ImPlotTime::FromDouble(range.Min);\n    const ImPlotTime t_max = ImPlotTime::FromDouble(range.Max);\n    // maximum allowable density of labels\n    const float max_density = 0.5f;\n    // book keeping\n    int last_major_offset = -1;\n    // formatter data\n    Formatter_Time_Data ftd;\n    ftd.UserFormatter = formatter;\n    ftd.UserFormatterData = formatter_data;\n    if (unit0 != ImPlotTimeUnit_Yr) {\n        // pixels per major (level 1) division\n        const float pix_per_major_div = pixels / (float)(range.Size() / TimeUnitSpans[unit1]);\n        // nominal pixels taken up by labels\n        const float fmt0_width = GetDateTimeWidth(fmt0);\n        const float fmt1_width = GetDateTimeWidth(fmt1);\n        const float fmtf_width = GetDateTimeWidth(fmtf);\n        // the maximum number of minor (level 0) labels that can fit between major (level 1) divisions\n        const int   minor_per_major   = (int)(max_density * pix_per_major_div / fmt0_width);\n        // the minor step size (level 0)\n        const int step = GetTimeStep(minor_per_major, unit0);\n        // generate ticks\n        ImPlotTime t1 = FloorTime(ImPlotTime::FromDouble(range.Min), unit1);\n        while (t1 < t_max) {\n            // get next major\n            const ImPlotTime t2 = AddTime(t1, unit1, 1);\n            // add major tick\n            if (t1 >= t_min && t1 <= t_max) {\n                // minor level 0 tick\n                ftd.Time = t1; ftd.Spec = fmt0;\n                ticker.AddTick(t1.ToDouble(), true, 0, true, Formatter_Time, &ftd);\n                // major level 1 tick\n                ftd.Time = t1; ftd.Spec = last_major_offset < 0 ? fmtf : fmt1;\n                ImPlotTick& tick_maj = ticker.AddTick(t1.ToDouble(), true, 1, true, Formatter_Time, &ftd);\n                const char* this_major = ticker.GetText(tick_maj);\n                if (last_major_offset >= 0 && TimeLabelSame(ticker.TextBuffer.Buf.Data + last_major_offset, this_major))\n                    tick_maj.ShowLabel = false;\n                last_major_offset = tick_maj.TextOffset;\n            }\n            // add minor ticks up until next major\n            if (minor_per_major > 1 && (t_min <= t2 && t1 <= t_max)) {\n                ImPlotTime t12 = AddTime(t1, unit0, step);\n                while (t12 < t2) {\n                    float px_to_t2 = (float)((t2 - t12).ToDouble()/range.Size()) * pixels;\n                    if (t12 >= t_min && t12 <= t_max) {\n                        ftd.Time = t12; ftd.Spec = fmt0;\n                        ticker.AddTick(t12.ToDouble(), false, 0, px_to_t2 >= fmt0_width, Formatter_Time, &ftd);\n                        if (last_major_offset < 0 && px_to_t2 >= fmt0_width && px_to_t2 >= (fmt1_width + fmtf_width) / 2) {\n                            ftd.Time = t12; ftd.Spec = fmtf;\n                            ImPlotTick& tick_maj = ticker.AddTick(t12.ToDouble(), true, 1, true, Formatter_Time, &ftd);\n                            last_major_offset = tick_maj.TextOffset;\n                        }\n                    }\n                    t12 = AddTime(t12, unit0, step);\n                }\n            }\n            t1 = t2;\n        }\n    }\n    else {\n        const ImPlotDateTimeSpec fmty = GetDateTimeFmt(TimeFormatLevel0, ImPlotTimeUnit_Yr);\n        const float label_width = GetDateTimeWidth(fmty);\n        const int   max_labels  = (int)(max_density * pixels / label_width);\n        const int year_min      = GetYear(t_min);\n        const int year_max      = GetYear(CeilTime(t_max, ImPlotTimeUnit_Yr));\n        const double nice_range = NiceNum((year_max - year_min)*0.99,false);\n        const double interval   = NiceNum(nice_range / (max_labels - 1), true);\n        const int graphmin      = (int)(floor(year_min / interval) * interval);\n        const int graphmax      = (int)(ceil(year_max  / interval) * interval);\n        const int step          = (int)interval <= 0 ? 1 : (int)interval;\n\n        for (int y = graphmin; y < graphmax; y += step) {\n            ImPlotTime t = MakeTime(y);\n            if (t >= t_min && t <= t_max) {\n                ftd.Time = t; ftd.Spec = fmty;\n                ticker.AddTick(t.ToDouble(), true, 0, true, Formatter_Time, &ftd);\n            }\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Context Menu\n//-----------------------------------------------------------------------------\n\ntemplate <typename F>\nbool DragFloat(const char*, F*, float, F, F) {\n    return false;\n}\n\ntemplate <>\nbool DragFloat<double>(const char* label, double* v, float v_speed, double v_min, double v_max) {\n    return ImGui::DragScalar(label, ImGuiDataType_Double, v, v_speed, &v_min, &v_max, \"%.3f\", 1);\n}\n\ntemplate <>\nbool DragFloat<float>(const char* label, float* v, float v_speed, float v_min, float v_max) {\n    return ImGui::DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, \"%.3f\", 1);\n}\n\ninline void BeginDisabledControls(bool cond) {\n    if (cond) {\n        ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);\n        ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.25f);\n    }\n}\n\ninline void EndDisabledControls(bool cond) {\n    if (cond) {\n        ImGui::PopItemFlag();\n        ImGui::PopStyleVar();\n    }\n}\n\nvoid ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool /*time_allowed*/) {\n\n    ImGui::PushItemWidth(75);\n    bool always_locked   = axis.IsRangeLocked() || axis.IsAutoFitting();\n    bool label           = axis.HasLabel();\n    bool grid            = axis.HasGridLines();\n    bool ticks           = axis.HasTickMarks();\n    bool labels          = axis.HasTickLabels();\n    double drag_speed    = (axis.Range.Size() <= DBL_EPSILON) ? DBL_EPSILON * 1.0e+13 : 0.01 * axis.Range.Size(); // recover from almost equal axis limits.\n\n    if (axis.Scale == ImPlotScale_Time) {\n        ImPlotTime tmin = ImPlotTime::FromDouble(axis.Range.Min);\n        ImPlotTime tmax = ImPlotTime::FromDouble(axis.Range.Max);\n\n        BeginDisabledControls(always_locked);\n        ImGui::CheckboxFlags(\"##LockMin\", (unsigned int*)&axis.Flags, ImPlotAxisFlags_LockMin);\n        EndDisabledControls(always_locked);\n        ImGui::SameLine();\n        BeginDisabledControls(axis.IsLockedMin() || always_locked);\n        if (ImGui::BeginMenu(\"Min Time\")) {\n            if (ShowTimePicker(\"mintime\", &tmin)) {\n                if (tmin >= tmax)\n                    tmax = AddTime(tmin, ImPlotTimeUnit_S, 1);\n                axis.SetRange(tmin.ToDouble(),tmax.ToDouble());\n            }\n            ImGui::Separator();\n            if (ShowDatePicker(\"mindate\",&axis.PickerLevel,&axis.PickerTimeMin,&tmin,&tmax)) {\n                tmin = CombineDateTime(axis.PickerTimeMin, tmin);\n                if (tmin >= tmax)\n                    tmax = AddTime(tmin, ImPlotTimeUnit_S, 1);\n                axis.SetRange(tmin.ToDouble(), tmax.ToDouble());\n            }\n            ImGui::EndMenu();\n        }\n        EndDisabledControls(axis.IsLockedMin() || always_locked);\n\n        BeginDisabledControls(always_locked);\n        ImGui::CheckboxFlags(\"##LockMax\", (unsigned int*)&axis.Flags, ImPlotAxisFlags_LockMax);\n        EndDisabledControls(always_locked);\n        ImGui::SameLine();\n        BeginDisabledControls(axis.IsLockedMax() || always_locked);\n        if (ImGui::BeginMenu(\"Max Time\")) {\n            if (ShowTimePicker(\"maxtime\", &tmax)) {\n                if (tmax <= tmin)\n                    tmin = AddTime(tmax, ImPlotTimeUnit_S, -1);\n                axis.SetRange(tmin.ToDouble(),tmax.ToDouble());\n            }\n            ImGui::Separator();\n            if (ShowDatePicker(\"maxdate\",&axis.PickerLevel,&axis.PickerTimeMax,&tmin,&tmax)) {\n                tmax = CombineDateTime(axis.PickerTimeMax, tmax);\n                if (tmax <= tmin)\n                    tmin = AddTime(tmax, ImPlotTimeUnit_S, -1);\n                axis.SetRange(tmin.ToDouble(), tmax.ToDouble());\n            }\n            ImGui::EndMenu();\n        }\n        EndDisabledControls(axis.IsLockedMax() || always_locked);\n    }\n    else {\n        BeginDisabledControls(always_locked);\n        ImGui::CheckboxFlags(\"##LockMin\", (unsigned int*)&axis.Flags, ImPlotAxisFlags_LockMin);\n        EndDisabledControls(always_locked);\n        ImGui::SameLine();\n        BeginDisabledControls(axis.IsLockedMin() || always_locked);\n        double temp_min = axis.Range.Min;\n        if (DragFloat(\"Min\", &temp_min, (float)drag_speed, -HUGE_VAL, axis.Range.Max - DBL_EPSILON)) {\n            axis.SetMin(temp_min,true);\n            if (equal_axis != nullptr)\n                equal_axis->SetAspect(axis.GetAspect());\n        }\n        EndDisabledControls(axis.IsLockedMin() || always_locked);\n\n        BeginDisabledControls(always_locked);\n        ImGui::CheckboxFlags(\"##LockMax\", (unsigned int*)&axis.Flags, ImPlotAxisFlags_LockMax);\n        EndDisabledControls(always_locked);\n        ImGui::SameLine();\n        BeginDisabledControls(axis.IsLockedMax() || always_locked);\n        double temp_max = axis.Range.Max;\n        if (DragFloat(\"Max\", &temp_max, (float)drag_speed, axis.Range.Min + DBL_EPSILON, HUGE_VAL)) {\n            axis.SetMax(temp_max,true);\n            if (equal_axis != nullptr)\n                equal_axis->SetAspect(axis.GetAspect());\n        }\n        EndDisabledControls(axis.IsLockedMax() || always_locked);\n    }\n\n    ImGui::Separator();\n\n    ImGui::CheckboxFlags(\"Auto-Fit\",(unsigned int*)&axis.Flags, ImPlotAxisFlags_AutoFit);\n    // TODO\n    // BeginDisabledControls(axis.IsTime() && time_allowed);\n    // ImGui::CheckboxFlags(\"Log Scale\",(unsigned int*)&axis.Flags, ImPlotAxisFlags_LogScale);\n    // EndDisabledControls(axis.IsTime() && time_allowed);\n    // if (time_allowed) {\n    //     BeginDisabledControls(axis.IsLog() || axis.IsSymLog());\n    //     ImGui::CheckboxFlags(\"Time\",(unsigned int*)&axis.Flags, ImPlotAxisFlags_Time);\n    //     EndDisabledControls(axis.IsLog() || axis.IsSymLog());\n    // }\n    ImGui::Separator();\n    ImGui::CheckboxFlags(\"Invert\",(unsigned int*)&axis.Flags, ImPlotAxisFlags_Invert);\n    ImGui::CheckboxFlags(\"Opposite\",(unsigned int*)&axis.Flags, ImPlotAxisFlags_Opposite);\n    ImGui::Separator();\n    BeginDisabledControls(axis.LabelOffset == -1);\n    if (ImGui::Checkbox(\"Label\", &label))\n        ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoLabel);\n    EndDisabledControls(axis.LabelOffset == -1);\n    if (ImGui::Checkbox(\"Grid Lines\", &grid))\n        ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoGridLines);\n    if (ImGui::Checkbox(\"Tick Marks\", &ticks))\n        ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoTickMarks);\n    if (ImGui::Checkbox(\"Tick Labels\", &labels))\n        ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoTickLabels);\n\n}\n\nbool ShowLegendContextMenu(ImPlotLegend& legend, bool visible) {\n    const float s = ImGui::GetFrameHeight();\n    bool ret = false;\n    if (ImGui::Checkbox(\"Show\",&visible))\n        ret = true;\n    if (legend.CanGoInside)\n        ImGui::CheckboxFlags(\"Outside\",(unsigned int*)&legend.Flags, ImPlotLegendFlags_Outside);\n    if (ImGui::RadioButton(\"H\", ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal)))\n        legend.Flags |= ImPlotLegendFlags_Horizontal;\n    ImGui::SameLine();\n    if (ImGui::RadioButton(\"V\", !ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal)))\n        legend.Flags &= ~ImPlotLegendFlags_Horizontal;\n    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2,2));\n    if (ImGui::Button(\"NW\",ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_NorthWest; } ImGui::SameLine();\n    if (ImGui::Button(\"N\", ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_North;     } ImGui::SameLine();\n    if (ImGui::Button(\"NE\",ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_NorthEast; }\n    if (ImGui::Button(\"W\", ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_West;      } ImGui::SameLine();\n    if (ImGui::InvisibleButton(\"C\", ImVec2(1.5f*s,s))) {     } ImGui::SameLine();\n    if (ImGui::Button(\"E\", ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_East;      }\n    if (ImGui::Button(\"SW\",ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_SouthWest; } ImGui::SameLine();\n    if (ImGui::Button(\"S\", ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_South;     } ImGui::SameLine();\n    if (ImGui::Button(\"SE\",ImVec2(1.5f*s,s))) { legend.Location = ImPlotLocation_SouthEast; }\n    ImGui::PopStyleVar();\n    return ret;\n}\n\nvoid ShowSubplotsContextMenu(ImPlotSubplot& subplot) {\n    if ((ImGui::BeginMenu(\"Linking\"))) {\n        if (ImGui::MenuItem(\"Link Rows\",nullptr,ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkRows)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_LinkRows);\n        if (ImGui::MenuItem(\"Link Cols\",nullptr,ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkCols)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_LinkCols);\n        if (ImGui::MenuItem(\"Link All X\",nullptr,ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkAllX)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_LinkAllX);\n        if (ImGui::MenuItem(\"Link All Y\",nullptr,ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkAllY)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_LinkAllY);\n        ImGui::EndMenu();\n    }\n    if ((ImGui::BeginMenu(\"Settings\"))) {\n        BeginDisabledControls(!subplot.HasTitle);\n        if (ImGui::MenuItem(\"Title\",nullptr,subplot.HasTitle && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoTitle)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_NoTitle);\n        EndDisabledControls(!subplot.HasTitle);\n        if (ImGui::MenuItem(\"Resizable\",nullptr,!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoResize)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_NoResize);\n        if (ImGui::MenuItem(\"Align\",nullptr,!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoAlign)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_NoAlign);\n        if (ImGui::MenuItem(\"Share Items\",nullptr,ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems)))\n            ImFlipFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);\n        ImGui::EndMenu();\n    }\n}\n\nvoid ShowPlotContextMenu(ImPlotPlot& plot) {\n    ImPlotContext& gp = *GImPlot;\n    const bool owns_legend = gp.CurrentItems == &plot.Items;\n    const bool equal = ImHasFlag(plot.Flags, ImPlotFlags_Equal);\n\n    char buf[16] = {};\n\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n        ImPlotAxis& x_axis = plot.XAxis(i);\n        if (!x_axis.Enabled || !x_axis.HasMenus())\n            continue;\n        ImGui::PushID(i);\n        ImFormatString(buf, sizeof(buf) - 1, i == 0 ? \"X-Axis\" : \"X-Axis %d\", i + 1);\n        if (ImGui::BeginMenu(x_axis.HasLabel() ? plot.GetAxisLabel(x_axis) : buf)) {\n            ShowAxisContextMenu(x_axis, equal ? x_axis.OrthoAxis : nullptr, false);\n            ImGui::EndMenu();\n        }\n        ImGui::PopID();\n    }\n\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n        ImPlotAxis& y_axis = plot.YAxis(i);\n        if (!y_axis.Enabled || !y_axis.HasMenus())\n            continue;\n        ImGui::PushID(i);\n        ImFormatString(buf, sizeof(buf) - 1, i == 0 ? \"Y-Axis\" : \"Y-Axis %d\", i + 1);\n        if (ImGui::BeginMenu(y_axis.HasLabel() ? plot.GetAxisLabel(y_axis) : buf)) {\n            ShowAxisContextMenu(y_axis, equal ? y_axis.OrthoAxis : nullptr, false);\n            ImGui::EndMenu();\n        }\n        ImGui::PopID();\n    }\n\n    ImGui::Separator();\n    if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlotLegendFlags_NoMenus)) {\n        if ((ImGui::BeginMenu(\"Legend\"))) {\n            if (owns_legend) {\n                if (ShowLegendContextMenu(plot.Items.Legend, !ImHasFlag(plot.Flags, ImPlotFlags_NoLegend)))\n                    ImFlipFlag(plot.Flags, ImPlotFlags_NoLegend);\n            }\n            else if (gp.CurrentSubplot != nullptr) {\n                if (ShowLegendContextMenu(gp.CurrentSubplot->Items.Legend, !ImHasFlag(gp.CurrentSubplot->Flags, ImPlotSubplotFlags_NoLegend)))\n                    ImFlipFlag(gp.CurrentSubplot->Flags, ImPlotSubplotFlags_NoLegend);\n            }\n            ImGui::EndMenu();\n        }\n    }\n    if ((ImGui::BeginMenu(\"Settings\"))) {\n        if (ImGui::MenuItem(\"Equal\", nullptr, ImHasFlag(plot.Flags, ImPlotFlags_Equal)))\n            ImFlipFlag(plot.Flags, ImPlotFlags_Equal);\n        if (ImGui::MenuItem(\"Box Select\",nullptr,!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect)))\n            ImFlipFlag(plot.Flags, ImPlotFlags_NoBoxSelect);\n        BeginDisabledControls(plot.TitleOffset == -1);\n        if (ImGui::MenuItem(\"Title\",nullptr,plot.HasTitle()))\n            ImFlipFlag(plot.Flags, ImPlotFlags_NoTitle);\n        EndDisabledControls(plot.TitleOffset == -1);\n        if (ImGui::MenuItem(\"Mouse Position\",nullptr,!ImHasFlag(plot.Flags, ImPlotFlags_NoMouseText)))\n            ImFlipFlag(plot.Flags, ImPlotFlags_NoMouseText);\n        if (ImGui::MenuItem(\"Crosshairs\",nullptr,ImHasFlag(plot.Flags, ImPlotFlags_Crosshairs)))\n            ImFlipFlag(plot.Flags, ImPlotFlags_Crosshairs);\n        ImGui::EndMenu();\n    }\n    if (gp.CurrentSubplot != nullptr && !ImHasFlag(gp.CurrentPlot->Flags, ImPlotSubplotFlags_NoMenus)) {\n        ImGui::Separator();\n        if ((ImGui::BeginMenu(\"Subplots\"))) {\n            ShowSubplotsContextMenu(*gp.CurrentSubplot);\n            ImGui::EndMenu();\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// Axis Utils\n//-----------------------------------------------------------------------------\n\nstatic inline int AxisPrecision(const ImPlotAxis& axis) {\n    const double range = axis.Ticker.TickCount() > 1 ? (axis.Ticker.Ticks[1].PlotPos - axis.Ticker.Ticks[0].PlotPos) : axis.Range.Size();\n    return Precision(range);\n}\n\nstatic inline double RoundAxisValue(const ImPlotAxis& axis, double value) {\n    return RoundTo(value, AxisPrecision(axis));\n}\n\nvoid LabelAxisValue(const ImPlotAxis& axis, double value, char* buff, int size, bool round) {\n    ImPlotContext& gp = *GImPlot;\n    // TODO: We shouldn't explicitly check that the axis is Time here. Ideally,\n    // Formatter_Time would handle the formatting for us, but the code below\n    // needs additional arguments which are not currently available in ImPlotFormatter\n    if (axis.Locator == Locator_Time) {\n        ImPlotTimeUnit unit = axis.Vertical\n                            ? GetUnitForRange(axis.Range.Size() / (gp.CurrentPlot->PlotRect.GetHeight() / 100)) // TODO: magic value!\n                            : GetUnitForRange(axis.Range.Size() / (gp.CurrentPlot->PlotRect.GetWidth() / 100)); // TODO: magic value!\n        FormatDateTime(ImPlotTime::FromDouble(value), buff, size, GetDateTimeFmt(TimeFormatMouseCursor, unit));\n    }\n    else {\n        if (round)\n            value = RoundAxisValue(axis, value);\n        axis.Formatter(value, buff, size, axis.FormatterData);\n    }\n}\n\nvoid UpdateAxisColors(ImPlotAxis& axis) {\n    const ImVec4 col_grid = GetStyleColorVec4(ImPlotCol_AxisGrid);\n    axis.ColorMaj         = ImGui::GetColorU32(col_grid);\n    axis.ColorMin         = ImGui::GetColorU32(col_grid*ImVec4(1,1,1,GImPlot->Style.MinorAlpha));\n    axis.ColorTick        = GetStyleColorU32(ImPlotCol_AxisTick);\n    axis.ColorTxt         = GetStyleColorU32(ImPlotCol_AxisText);\n    axis.ColorBg          = GetStyleColorU32(ImPlotCol_AxisBg);\n    axis.ColorHov         = GetStyleColorU32(ImPlotCol_AxisBgHovered);\n    axis.ColorAct         = GetStyleColorU32(ImPlotCol_AxisBgActive);\n    // axis.ColorHiLi     = IM_COL32_BLACK_TRANS;\n}\n\nvoid PadAndDatumAxesX(ImPlotPlot& plot, float& pad_T, float& pad_B, ImPlotAlignmentData* align) {\n\n    ImPlotContext& gp = *GImPlot;\n\n    const float T = ImGui::GetTextLineHeight();\n    const float P = gp.Style.LabelPadding.y;\n    const float K = gp.Style.MinorTickLen.x;\n\n    int   count_T = 0;\n    int   count_B = 0;\n    float last_T  = plot.AxesRect.Min.y;\n    float last_B  = plot.AxesRect.Max.y;\n\n    for (int i = IMPLOT_NUM_X_AXES; i-- > 0;) { // FYI: can iterate forward\n        ImPlotAxis& axis = plot.XAxis(i);\n        if (!axis.Enabled)\n            continue;\n        const bool label = axis.HasLabel();\n        const bool ticks = axis.HasTickLabels();\n        const bool opp   = axis.IsOpposite();\n        const bool time  = axis.Scale == ImPlotScale_Time;\n        if (opp) {\n            if (count_T++ > 0)\n                pad_T += K + P;\n            if (label)\n                pad_T += T + P;\n            if (ticks)\n                pad_T += ImMax(T, axis.Ticker.MaxSize.y) + P + (time ? T + P : 0);\n            axis.Datum1 = plot.CanvasRect.Min.y + pad_T;\n            axis.Datum2 = last_T;\n            last_T = axis.Datum1;\n        }\n        else {\n            if (count_B++ > 0)\n                pad_B += K + P;\n            if (label)\n                pad_B += T + P;\n            if (ticks)\n                pad_B += ImMax(T, axis.Ticker.MaxSize.y) + P + (time ? T + P : 0);\n            axis.Datum1 = plot.CanvasRect.Max.y - pad_B;\n            axis.Datum2 = last_B;\n            last_B = axis.Datum1;\n        }\n    }\n\n    if (align) {\n        count_T = count_B = 0;\n        float delta_T, delta_B;\n        align->Update(pad_T,pad_B,delta_T,delta_B);\n        for (int i = IMPLOT_NUM_X_AXES; i-- > 0;) {\n            ImPlotAxis& axis = plot.XAxis(i);\n            if (!axis.Enabled)\n                continue;\n            if (axis.IsOpposite()) {\n                axis.Datum1 += delta_T;\n                axis.Datum2 += count_T++ > 1 ? delta_T : 0;\n            }\n            else {\n                axis.Datum1 -= delta_B;\n                axis.Datum2 -= count_B++ > 1 ? delta_B : 0;\n            }\n        }\n    }\n}\n\nvoid PadAndDatumAxesY(ImPlotPlot& plot, float& pad_L, float& pad_R, ImPlotAlignmentData* align) {\n\n    //   [   pad_L   ]                 [   pad_R   ]\n    //   .................CanvasRect................\n    //   :TPWPK.PTPWP _____PlotRect____ PWPTP.KPWPT:\n    //   :A # |- A # |-               -| # A -| # A:\n    //   :X   |  X   |                 |   X  |   x:\n    //   :I # |- I # |-               -| # I -| # I:\n    //   :S   |  S   |                 |   S  |   S:\n    //   :3 # |- 0 # |-_______________-| # 1 -| # 2:\n    //   :.........................................:\n    //\n    //   T = text height\n    //   P = label padding\n    //   K = minor tick length\n    //   W = label width\n\n    ImPlotContext& gp = *GImPlot;\n\n    const float T = ImGui::GetTextLineHeight();\n    const float P = gp.Style.LabelPadding.x;\n    const float K = gp.Style.MinorTickLen.y;\n\n    int   count_L = 0;\n    int   count_R = 0;\n    float last_L  = plot.AxesRect.Min.x;\n    float last_R  = plot.AxesRect.Max.x;\n\n    for (int i = IMPLOT_NUM_Y_AXES; i-- > 0;) { // FYI: can iterate forward\n        ImPlotAxis& axis = plot.YAxis(i);\n        if (!axis.Enabled)\n            continue;\n        const bool label = axis.HasLabel();\n        const bool ticks = axis.HasTickLabels();\n        const bool opp   = axis.IsOpposite();\n        if (opp) {\n            if (count_R++ > 0)\n                pad_R += K + P;\n            if (label)\n                pad_R += T + P;\n            if (ticks)\n                pad_R += axis.Ticker.MaxSize.x + P;\n            axis.Datum1 = plot.CanvasRect.Max.x - pad_R;\n            axis.Datum2 = last_R;\n            last_R = axis.Datum1;\n        }\n        else {\n            if (count_L++ > 0)\n                pad_L += K + P;\n            if (label)\n                pad_L += T + P;\n            if (ticks)\n                pad_L += axis.Ticker.MaxSize.x + P;\n            axis.Datum1 = plot.CanvasRect.Min.x + pad_L;\n            axis.Datum2 = last_L;\n            last_L = axis.Datum1;\n        }\n    }\n\n    plot.PlotRect.Min.x = plot.CanvasRect.Min.x + pad_L;\n    plot.PlotRect.Max.x = plot.CanvasRect.Max.x - pad_R;\n\n    if (align) {\n        count_L = count_R = 0;\n        float delta_L, delta_R;\n        align->Update(pad_L,pad_R,delta_L,delta_R);\n        for (int i = IMPLOT_NUM_Y_AXES; i-- > 0;) {\n            ImPlotAxis& axis = plot.YAxis(i);\n            if (!axis.Enabled)\n                continue;\n            if (axis.IsOpposite()) {\n                axis.Datum1 -= delta_R;\n                axis.Datum2 -= count_R++ > 1 ? delta_R : 0;\n            }\n            else {\n                axis.Datum1 += delta_L;\n                axis.Datum2 += count_L++ > 1 ? delta_L : 0;\n            }\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// RENDERING\n//-----------------------------------------------------------------------------\n\nstatic inline void RenderGridLinesX(ImDrawList& DrawList, const ImPlotTicker& ticker, const ImRect& rect, ImU32 col_maj, ImU32 col_min, float size_maj, float size_min) {\n    const float density   = ticker.TickCount() / rect.GetWidth();\n    ImVec4 col_min4  = ImGui::ColorConvertU32ToFloat4(col_min);\n    col_min4.w      *= ImClamp(ImRemap(density, 0.1f, 0.2f, 1.0f, 0.0f), 0.0f, 1.0f);\n    col_min = ImGui::ColorConvertFloat4ToU32(col_min4);\n    for (int t = 0; t < ticker.TickCount(); t++) {\n        const ImPlotTick& xt = ticker.Ticks[t];\n        if (xt.PixelPos < rect.Min.x || xt.PixelPos > rect.Max.x)\n            continue;\n        if (xt.Level == 0) {\n            if (xt.Major)\n                DrawList.AddLine(ImVec2(xt.PixelPos, rect.Min.y), ImVec2(xt.PixelPos, rect.Max.y), col_maj, size_maj);\n            else if (density < 0.2f)\n                DrawList.AddLine(ImVec2(xt.PixelPos, rect.Min.y), ImVec2(xt.PixelPos, rect.Max.y), col_min, size_min);\n        }\n    }\n}\n\nstatic inline void RenderGridLinesY(ImDrawList& DrawList, const ImPlotTicker& ticker, const ImRect& rect, ImU32 col_maj, ImU32 col_min, float size_maj, float size_min) {\n    const float density   = ticker.TickCount() / rect.GetHeight();\n    ImVec4 col_min4  = ImGui::ColorConvertU32ToFloat4(col_min);\n    col_min4.w      *= ImClamp(ImRemap(density, 0.1f, 0.2f, 1.0f, 0.0f), 0.0f, 1.0f);\n    col_min = ImGui::ColorConvertFloat4ToU32(col_min4);\n    for (int t = 0; t < ticker.TickCount(); t++) {\n        const ImPlotTick& yt = ticker.Ticks[t];\n        if (yt.PixelPos < rect.Min.y || yt.PixelPos > rect.Max.y)\n            continue;\n        if (yt.Major)\n            DrawList.AddLine(ImVec2(rect.Min.x, yt.PixelPos), ImVec2(rect.Max.x, yt.PixelPos), col_maj, size_maj);\n        else if (density < 0.2f)\n            DrawList.AddLine(ImVec2(rect.Min.x, yt.PixelPos), ImVec2(rect.Max.x, yt.PixelPos), col_min, size_min);\n    }\n}\n\nstatic inline void RenderSelectionRect(ImDrawList& DrawList, const ImVec2& p_min, const ImVec2& p_max, const ImVec4& col) {\n    const ImU32 col_bg = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f));\n    const ImU32 col_bd = ImGui::GetColorU32(col);\n    DrawList.AddRectFilled(p_min, p_max, col_bg);\n    DrawList.AddRect(p_min, p_max, col_bd);\n}\n\n//-----------------------------------------------------------------------------\n// Input Handling\n//-----------------------------------------------------------------------------\n\nstatic const float MOUSE_CURSOR_DRAG_THRESHOLD = 5.0f;\nstatic const float BOX_SELECT_DRAG_THRESHOLD   = 4.0f;\n\nbool UpdateInput(ImPlotPlot& plot) {\n\n    bool changed = false;\n\n    ImPlotContext& gp = *GImPlot;\n    ImGuiIO& IO = ImGui::GetIO();\n\n    // BUTTON STATE -----------------------------------------------------------\n\n    const ImGuiButtonFlags plot_button_flags = ImGuiButtonFlags_AllowOverlap\n                                             | ImGuiButtonFlags_PressedOnClick\n                                             | ImGuiButtonFlags_PressedOnDoubleClick\n                                             | ImGuiButtonFlags_MouseButtonLeft\n                                             | ImGuiButtonFlags_MouseButtonRight\n                                             | ImGuiButtonFlags_MouseButtonMiddle;\n    const ImGuiButtonFlags axis_button_flags = ImGuiButtonFlags_FlattenChildren\n                                             | plot_button_flags;\n\n    const bool plot_clicked = ImGui::ButtonBehavior(plot.PlotRect,plot.ID,&plot.Hovered,&plot.Held,plot_button_flags);\n#if (IMGUI_VERSION_NUM < 18966)\n    ImGui::SetItemAllowOverlap(); // Handled by ButtonBehavior()\n#endif\n\n    if (plot_clicked) {\n        if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) && IO.MouseClicked[gp.InputMap.Select] && ImHasFlag(IO.KeyMods, gp.InputMap.SelectMod)) {\n            plot.Selecting   = true;\n            plot.SelectStart = IO.MousePos;\n            plot.SelectRect  = ImRect(0,0,0,0);\n        }\n        if (IO.MouseDoubleClicked[gp.InputMap.Fit]) {\n            plot.FitThisFrame = true;\n            for (int i = 0; i < ImAxis_COUNT; ++i)\n                plot.Axes[i].FitThisFrame = true;\n        }\n    }\n\n    const bool can_pan = IO.MouseDown[gp.InputMap.Pan] && ImHasFlag(IO.KeyMods, gp.InputMap.PanMod);\n\n    plot.Held = plot.Held && can_pan;\n\n    bool x_click[IMPLOT_NUM_X_AXES] = {false};\n    bool x_held[IMPLOT_NUM_X_AXES]  = {false};\n    bool x_hov[IMPLOT_NUM_X_AXES]   = {false};\n\n    bool y_click[IMPLOT_NUM_Y_AXES] = {false};\n    bool y_held[IMPLOT_NUM_Y_AXES]  = {false};\n    bool y_hov[IMPLOT_NUM_Y_AXES]   = {false};\n\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n        ImPlotAxis& xax = plot.XAxis(i);\n        if (xax.Enabled) {\n            ImGui::KeepAliveID(xax.ID);\n            x_click[i]  = ImGui::ButtonBehavior(xax.HoverRect,xax.ID,&xax.Hovered,&xax.Held,axis_button_flags);\n            if (x_click[i] && IO.MouseDoubleClicked[gp.InputMap.Fit])\n                plot.FitThisFrame = xax.FitThisFrame = true;\n            xax.Held  = xax.Held && can_pan;\n            x_hov[i]  = xax.Hovered || plot.Hovered;\n            x_held[i] = xax.Held    || plot.Held;\n        }\n    }\n\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {\n        ImPlotAxis& yax = plot.YAxis(i);\n        if (yax.Enabled) {\n            ImGui::KeepAliveID(yax.ID);\n            y_click[i]  = ImGui::ButtonBehavior(yax.HoverRect,yax.ID,&yax.Hovered,&yax.Held,axis_button_flags);\n            if (y_click[i] && IO.MouseDoubleClicked[gp.InputMap.Fit])\n                plot.FitThisFrame = yax.FitThisFrame = true;\n            yax.Held  = yax.Held && can_pan;\n            y_hov[i]  = yax.Hovered || plot.Hovered;\n            y_held[i] = yax.Held    || plot.Held;\n        }\n    }\n\n    // cancel due to DND activity\n    if (GImGui->DragDropActive || (IO.KeyMods == gp.InputMap.OverrideMod && gp.InputMap.OverrideMod != 0))\n        return false;\n\n    // STATE -------------------------------------------------------------------\n\n    const bool axis_equal      = ImHasFlag(plot.Flags, ImPlotFlags_Equal);\n\n    const bool any_x_hov       = plot.Hovered || AnyAxesHovered(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);\n    const bool any_x_held      = plot.Held    || AnyAxesHeld(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);\n    const bool any_y_hov       = plot.Hovered || AnyAxesHovered(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);\n    const bool any_y_held      = plot.Held    || AnyAxesHeld(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);\n    const bool any_hov         = any_x_hov    || any_y_hov;\n    const bool any_held        = any_x_held   || any_y_held;\n\n    const ImVec2 select_drag   = ImGui::GetMouseDragDelta(gp.InputMap.Select);\n    const ImVec2 pan_drag      = ImGui::GetMouseDragDelta(gp.InputMap.Pan);\n    const float select_drag_sq = ImLengthSqr(select_drag);\n    const float pan_drag_sq    = ImLengthSqr(pan_drag);\n    const bool selecting       = plot.Selecting && select_drag_sq > MOUSE_CURSOR_DRAG_THRESHOLD;\n    const bool panning         = any_held       && pan_drag_sq    > MOUSE_CURSOR_DRAG_THRESHOLD;\n\n    // CONTEXT MENU -----------------------------------------------------------\n\n    if (IO.MouseReleased[gp.InputMap.Menu] && !plot.ContextLocked)\n        gp.OpenContextThisFrame = true;\n\n    if (selecting || panning)\n        plot.ContextLocked = true;\n    else if (!(IO.MouseDown[gp.InputMap.Menu] || IO.MouseReleased[gp.InputMap.Menu]))\n        plot.ContextLocked = false;\n\n    // DRAG INPUT -------------------------------------------------------------\n\n    if (any_held && !plot.Selecting) {\n        int drag_direction = 0;\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n            ImPlotAxis& x_axis = plot.XAxis(i);\n            if (x_held[i] && !x_axis.IsInputLocked()) {\n                drag_direction |= (1 << 1);\n                bool increasing = x_axis.IsInverted() ? IO.MouseDelta.x > 0 : IO.MouseDelta.x < 0;\n                if (IO.MouseDelta.x != 0 && !x_axis.IsPanLocked(increasing)) {\n                    const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - IO.MouseDelta.x);\n                    const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x - IO.MouseDelta.x);\n                    x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l);\n                    x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r);\n                    if (axis_equal && x_axis.OrthoAxis != nullptr)\n                        x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());\n                    changed = true;\n                }\n            }\n        }\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n            ImPlotAxis& y_axis = plot.YAxis(i);\n            if (y_held[i] && !y_axis.IsInputLocked()) {\n                drag_direction |= (1 << 2);\n                bool increasing = y_axis.IsInverted() ? IO.MouseDelta.y < 0 : IO.MouseDelta.y > 0;\n                if (IO.MouseDelta.y != 0 && !y_axis.IsPanLocked(increasing)) {\n                    const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - IO.MouseDelta.y);\n                    const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y - IO.MouseDelta.y);\n                    y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b);\n                    y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t);\n                    if (axis_equal && y_axis.OrthoAxis != nullptr)\n                        y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());\n                    changed = true;\n                }\n            }\n        }\n        if (IO.MouseDragMaxDistanceSqr[gp.InputMap.Pan] > MOUSE_CURSOR_DRAG_THRESHOLD) {\n            switch (drag_direction) {\n                case 0        : ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); break;\n                case (1 << 1) : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);   break;\n                case (1 << 2) : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);   break;\n                default       : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);  break;\n            }\n        }\n    }\n\n    // SCROLL INPUT -----------------------------------------------------------\n\n    if (any_hov && IO.MouseWheel != 0 && ImHasFlag(IO.KeyMods, gp.InputMap.ZoomMod)) {\n\n        float zoom_rate = gp.InputMap.ZoomRate;\n        if (IO.MouseWheel > 0)\n            zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate));\n        ImVec2 rect_size = plot.PlotRect.GetSize();\n        float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f);\n        float ty = ImRemap(IO.MousePos.y, plot.PlotRect.Min.y, plot.PlotRect.Max.y, 0.0f, 1.0f);\n\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n            ImPlotAxis& x_axis = plot.XAxis(i);\n            const bool equal_zoom   = axis_equal && x_axis.OrthoAxis != nullptr;\n            const bool equal_locked = (equal_zoom != false) && x_axis.OrthoAxis->IsInputLocked();\n            if (x_hov[i] && !x_axis.IsInputLocked() && !equal_locked) {\n                float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;\n                const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction);\n                const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction);\n                x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l);\n                x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r);\n                if (axis_equal && x_axis.OrthoAxis != nullptr)\n                    x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());\n                changed = true;\n            }\n        }\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n            ImPlotAxis& y_axis = plot.YAxis(i);\n            const bool equal_zoom   = axis_equal && y_axis.OrthoAxis != nullptr;\n            const bool equal_locked = equal_zoom && y_axis.OrthoAxis->IsInputLocked();\n            if (y_hov[i] && !y_axis.IsInputLocked() && !equal_locked) {\n                float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;\n                const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction);\n                const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction);\n                y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b);\n                y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t);\n                if (axis_equal && y_axis.OrthoAxis != nullptr)\n                    y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());\n                changed = true;\n            }\n        }\n    }\n\n    // BOX-SELECTION ----------------------------------------------------------\n\n    if (plot.Selecting) {\n        const ImVec2 d = plot.SelectStart - IO.MousePos;\n        const bool x_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.SelectHorzMod) && ImFabs(d.x) > 2;\n        const bool y_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.SelectVertMod) && ImFabs(d.y) > 2;\n        // confirm\n        if (IO.MouseReleased[gp.InputMap.Select]) {\n            for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n                ImPlotAxis& x_axis = plot.XAxis(i);\n                if (!x_axis.IsInputLocked() && x_can_change) {\n                    const double p1 = x_axis.PixelsToPlot(plot.SelectStart.x);\n                    const double p2 = x_axis.PixelsToPlot(IO.MousePos.x);\n                    x_axis.SetMin(ImMin(p1, p2));\n                    x_axis.SetMax(ImMax(p1, p2));\n                    changed = true;\n                }\n            }\n            for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n                ImPlotAxis& y_axis = plot.YAxis(i);\n                if (!y_axis.IsInputLocked() && y_can_change) {\n                    const double p1 = y_axis.PixelsToPlot(plot.SelectStart.y);\n                    const double p2 = y_axis.PixelsToPlot(IO.MousePos.y);\n                    y_axis.SetMin(ImMin(p1, p2));\n                    y_axis.SetMax(ImMax(p1, p2));\n                    changed = true;\n                }\n            }\n            if (x_can_change || y_can_change || (ImHasFlag(IO.KeyMods,gp.InputMap.SelectHorzMod) && ImHasFlag(IO.KeyMods,gp.InputMap.SelectVertMod)))\n                gp.OpenContextThisFrame = false;\n            plot.Selected = plot.Selecting = false;\n        }\n        // cancel\n        else if (IO.MouseReleased[gp.InputMap.SelectCancel]) {\n            plot.Selected = plot.Selecting = false;\n            gp.OpenContextThisFrame = false;\n        }\n        else if (ImLengthSqr(d) > BOX_SELECT_DRAG_THRESHOLD) {\n            // bad selection\n            if (plot.IsInputLocked()) {\n                ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);\n                gp.OpenContextThisFrame = false;\n                plot.Selected      = false;\n            }\n            else {\n                // TODO: Handle only min or max locked cases\n                const bool full_width  = ImHasFlag(IO.KeyMods, gp.InputMap.SelectHorzMod) || AllAxesInputLocked(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);\n                const bool full_height = ImHasFlag(IO.KeyMods, gp.InputMap.SelectVertMod) || AllAxesInputLocked(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);\n                plot.SelectRect.Min.x = full_width  ? plot.PlotRect.Min.x : ImMin(plot.SelectStart.x, IO.MousePos.x);\n                plot.SelectRect.Max.x = full_width  ? plot.PlotRect.Max.x : ImMax(plot.SelectStart.x, IO.MousePos.x);\n                plot.SelectRect.Min.y = full_height ? plot.PlotRect.Min.y : ImMin(plot.SelectStart.y, IO.MousePos.y);\n                plot.SelectRect.Max.y = full_height ? plot.PlotRect.Max.y : ImMax(plot.SelectStart.y, IO.MousePos.y);\n                plot.SelectRect.Min  -= plot.PlotRect.Min;\n                plot.SelectRect.Max  -= plot.PlotRect.Min;\n                plot.Selected = true;\n            }\n        }\n        else {\n            plot.Selected = false;\n        }\n    }\n    return changed;\n}\n\n//-----------------------------------------------------------------------------\n// Next Plot Data (Legacy)\n//-----------------------------------------------------------------------------\n\nvoid ApplyNextPlotData(ImAxis idx) {\n    ImPlotContext& gp = *GImPlot;\n    ImPlotPlot& plot  = *gp.CurrentPlot;\n    ImPlotAxis& axis  = plot.Axes[idx];\n    if (!axis.Enabled)\n        return;\n    double*     npd_lmin = gp.NextPlotData.LinkedMin[idx];\n    double*     npd_lmax = gp.NextPlotData.LinkedMax[idx];\n    bool        npd_rngh = gp.NextPlotData.HasRange[idx];\n    ImPlotCond  npd_rngc = gp.NextPlotData.RangeCond[idx];\n    ImPlotRange     npd_rngv = gp.NextPlotData.Range[idx];\n    axis.LinkedMin = npd_lmin;\n    axis.LinkedMax = npd_lmax;\n    axis.PullLinks();\n    if (npd_rngh) {\n        if (!plot.Initialized || npd_rngc == ImPlotCond_Always)\n            axis.SetRange(npd_rngv);\n    }\n    axis.HasRange         = npd_rngh;\n    axis.RangeCond        = npd_rngc;\n}\n\n//-----------------------------------------------------------------------------\n// Setup\n//-----------------------------------------------------------------------------\n\nvoid SetupAxis(ImAxis idx, const char* label, ImPlotAxisFlags flags) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    // get plot and axis\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    // set ID\n    axis.ID = plot.ID + idx + 1;\n    // check and set flags\n    if (plot.JustCreated || flags != axis.PreviousFlags)\n        axis.Flags = flags;\n    axis.PreviousFlags = flags;\n    // enable axis\n    axis.Enabled = true;\n    // set label\n    plot.SetAxisLabel(axis,label);\n    // cache colors\n    UpdateAxisColors(axis);\n}\n\nvoid SetupAxisLimits(ImAxis idx, double min_lim, double max_lim, ImPlotCond cond) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");    // get plot and axis\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    if (!plot.Initialized || cond == ImPlotCond_Always)\n        axis.SetRange(min_lim, max_lim);\n    axis.HasRange  = true;\n    axis.RangeCond = cond;\n}\n\nvoid SetupAxisFormat(ImAxis idx, const char* fmt) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.HasFormatSpec = fmt != nullptr;\n    if (fmt != nullptr)\n        ImStrncpy(axis.FormatSpec,fmt,sizeof(axis.FormatSpec));\n}\n\nvoid SetupAxisLinks(ImAxis idx, double* min_lnk, double* max_lnk) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.LinkedMin = min_lnk;\n    axis.LinkedMax = max_lnk;\n    axis.PullLinks();\n}\n\nvoid SetupAxisFormat(ImAxis idx, ImPlotFormatter formatter, void* data) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.Formatter = formatter;\n    axis.FormatterData = data;\n}\n\nvoid SetupAxisTicks(ImAxis idx, const double* values, int n_ticks, const char* const labels[], bool show_default) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                        \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.ShowDefaultTicks = show_default;\n    AddTicksCustom(values,\n                  labels,\n                  n_ticks,\n                  axis.Ticker,\n                  axis.Formatter ? axis.Formatter : Formatter_Default,\n                  (axis.Formatter && axis.FormatterData) ? axis.FormatterData : axis.HasFormatSpec ? axis.FormatSpec : (void*)IMPLOT_LABEL_FORMAT);\n}\n\nvoid SetupAxisTicks(ImAxis idx, double v_min, double v_max, int n_ticks, const char* const labels[], bool show_default) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    n_ticks = n_ticks < 2 ? 2 : n_ticks;\n    FillRange(gp.TempDouble1, n_ticks, v_min, v_max);\n    SetupAxisTicks(idx, gp.TempDouble1.Data, n_ticks, labels, show_default);\n}\n\nvoid SetupAxisScale(ImAxis idx, ImPlotScale scale) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                        \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.Scale = scale;\n    switch (scale)\n    {\n    case ImPlotScale_Time:\n        axis.TransformForward = nullptr;\n        axis.TransformInverse = nullptr;\n        axis.TransformData    = nullptr;\n        axis.Locator          = Locator_Time;\n        axis.ConstraintRange  = ImPlotRange(IMPLOT_MIN_TIME, IMPLOT_MAX_TIME);\n        axis.Ticker.Levels    = 2;\n        break;\n    case ImPlotScale_Log10:\n        axis.TransformForward = TransformForward_Log10;\n        axis.TransformInverse = TransformInverse_Log10;\n        axis.TransformData    = nullptr;\n        axis.Locator          = Locator_Log10;\n        axis.ConstraintRange  = ImPlotRange(DBL_MIN, INFINITY);\n        break;\n    case ImPlotScale_SymLog:\n        axis.TransformForward = TransformForward_SymLog;\n        axis.TransformInverse = TransformInverse_SymLog;\n        axis.TransformData    = nullptr;\n        axis.Locator          = Locator_SymLog;\n        axis.ConstraintRange  = ImPlotRange(-INFINITY, INFINITY);\n        break;\n    default:\n        axis.TransformForward = nullptr;\n        axis.TransformInverse = nullptr;\n        axis.TransformData    = nullptr;\n        axis.Locator          = nullptr;\n        axis.ConstraintRange  = ImPlotRange(-INFINITY, INFINITY);\n        break;\n    }\n}\n\nvoid SetupAxisScale(ImAxis idx, ImPlotTransform fwd, ImPlotTransform inv, void* data) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                        \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.Scale = IMPLOT_AUTO;\n    axis.TransformForward = fwd;\n    axis.TransformInverse = inv;\n    axis.TransformData = data;\n}\n\nvoid SetupAxisLimitsConstraints(ImAxis idx, double v_min, double v_max) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                        \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.ConstraintRange.Min = v_min;\n    axis.ConstraintRange.Max = v_max;\n}\n\nvoid SetupAxisZoomConstraints(ImAxis idx, double z_min, double z_max) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                        \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& axis = plot.Axes[idx];\n    IM_ASSERT_USER_ERROR(axis.Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    axis.ConstraintZoom.Min = z_min;\n    axis.ConstraintZoom.Max = z_max;\n}\n\nvoid SetupAxes(const char* x_label, const char* y_label, ImPlotAxisFlags x_flags, ImPlotAxisFlags y_flags) {\n    SetupAxis(ImAxis_X1, x_label, x_flags);\n    SetupAxis(ImAxis_Y1, y_label, y_flags);\n}\n\nvoid SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond) {\n    SetupAxisLimits(ImAxis_X1, x_min, x_max, cond);\n    SetupAxisLimits(ImAxis_Y1, y_min, y_max, cond);\n}\n\nvoid SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr,\n                         \"SetupLegend() needs to be called within an itemized context!\");\n    ImPlotLegend& legend = gp.CurrentItems->Legend;\n    // check and set location\n    if (location != legend.PreviousLocation)\n        legend.Location = location;\n    legend.PreviousLocation = location;\n    // check and set flags\n    if (flags != legend.PreviousFlags)\n        legend.Flags = flags;\n    legend.PreviousFlags = flags;\n}\n\nvoid SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,\n                         \"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!\");\n    gp.CurrentPlot->MouseTextLocation = location;\n    gp.CurrentPlot->MouseTextFlags = flags;\n}\n\n//-----------------------------------------------------------------------------\n// SetNext\n//-----------------------------------------------------------------------------\n\nvoid SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot == nullptr, \"SetNextAxisLimits() needs to be called before BeginPlot()!\");\n    IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.\n    gp.NextPlotData.HasRange[axis]  = true;\n    gp.NextPlotData.RangeCond[axis] = cond;\n    gp.NextPlotData.Range[axis].Min = v_min;\n    gp.NextPlotData.Range[axis].Max = v_max;\n}\n\nvoid SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot == nullptr, \"SetNextAxisLinks() needs to be called before BeginPlot()!\");\n    gp.NextPlotData.LinkedMin[axis] = link_min;\n    gp.NextPlotData.LinkedMax[axis] = link_max;\n}\n\nvoid SetNextAxisToFit(ImAxis axis) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot == nullptr, \"SetNextAxisToFit() needs to be called before BeginPlot()!\");\n    gp.NextPlotData.Fit[axis] = true;\n}\n\nvoid SetNextAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond) {\n    SetNextAxisLimits(ImAxis_X1, x_min, x_max, cond);\n    SetNextAxisLimits(ImAxis_Y1, y_min, y_max, cond);\n}\n\nvoid SetNextAxesToFit() {\n    for (int i = 0; i < ImAxis_COUNT; ++i)\n        SetNextAxisToFit(i);\n}\n\n//-----------------------------------------------------------------------------\n// BeginPlot\n//-----------------------------------------------------------------------------\n\nbool BeginPlot(const char* title_id, const ImVec2& size, ImPlotFlags flags) {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot == nullptr, \"Mismatched BeginPlot()/EndPlot()!\");\n\n    // FRONT MATTER -----------------------------------------------------------\n\n    if (gp.CurrentSubplot != nullptr)\n        ImGui::PushID(gp.CurrentSubplot->CurrentIdx);\n\n    // get globals\n    ImGuiContext &G          = *GImGui;\n    ImGuiWindow* Window      = G.CurrentWindow;\n\n    // skip if needed\n    if (Window->SkipItems && !gp.CurrentSubplot) {\n        ResetCtxForNextPlot(GImPlot);\n        return false;\n    }\n\n    // ID and age (TODO: keep track of plot age in frames)\n    const ImGuiID ID         = Window->GetID(title_id);\n    const bool just_created  = gp.Plots.GetByKey(ID) == nullptr;\n    gp.CurrentPlot           = gp.Plots.GetOrAddByKey(ID);\n\n    ImPlotPlot &plot         = *gp.CurrentPlot;\n    plot.ID                  = ID;\n    plot.Items.ID            = ID - 1;\n    plot.JustCreated         = just_created;\n    plot.SetupLocked         = false;\n\n    // check flags\n    if (plot.JustCreated)\n        plot.Flags = flags;\n    else if (flags != plot.PreviousFlags)\n        plot.Flags = flags;\n    plot.PreviousFlags = flags;\n\n    // setup default axes\n    if (plot.JustCreated) {\n        SetupAxis(ImAxis_X1);\n        SetupAxis(ImAxis_Y1);\n    }\n\n    // reset axes\n    for (int i = 0; i < ImAxis_COUNT; ++i) {\n        plot.Axes[i].Reset();\n        UpdateAxisColors(plot.Axes[i]);\n    }\n    // ensure first axes enabled\n    plot.Axes[ImAxis_X1].Enabled = true;\n    plot.Axes[ImAxis_Y1].Enabled = true;\n    // set initial axes\n    plot.CurrentX = ImAxis_X1;\n    plot.CurrentY = ImAxis_Y1;\n\n    // process next plot data (legacy)\n    for (int i = 0; i < ImAxis_COUNT; ++i)\n        ApplyNextPlotData(i);\n\n    // capture scroll with a child region\n    if (!ImHasFlag(plot.Flags, ImPlotFlags_NoChild)) {\n        ImVec2 child_size;\n        if (gp.CurrentSubplot != nullptr)\n            child_size = gp.CurrentSubplot->CellSize;\n        else\n            child_size = ImVec2(size.x == 0 ? gp.Style.PlotDefaultSize.x : size.x, size.y == 0 ? gp.Style.PlotDefaultSize.y : size.y);\n        ImGui::BeginChild(title_id, child_size, false, ImGuiWindowFlags_NoScrollbar);\n        Window = ImGui::GetCurrentWindow();\n        Window->ScrollMax.y = 1.0f;\n        gp.ChildWindowMade = true;\n    }\n    else {\n        gp.ChildWindowMade = false;\n    }\n\n    // clear text buffers\n    plot.ClearTextBuffer();\n    plot.SetTitle(title_id);\n\n    // set frame size\n    ImVec2 frame_size;\n    if (gp.CurrentSubplot != nullptr)\n        frame_size = gp.CurrentSubplot->CellSize;\n    else\n        frame_size = ImGui::CalcItemSize(size, gp.Style.PlotDefaultSize.x, gp.Style.PlotDefaultSize.y);\n\n    if (frame_size.x < gp.Style.PlotMinSize.x && (size.x < 0.0f || gp.CurrentSubplot != nullptr))\n        frame_size.x = gp.Style.PlotMinSize.x;\n    if (frame_size.y < gp.Style.PlotMinSize.y && (size.y < 0.0f || gp.CurrentSubplot != nullptr))\n        frame_size.y = gp.Style.PlotMinSize.y;\n\n    plot.FrameRect = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);\n    ImGui::ItemSize(plot.FrameRect);\n    if (!ImGui::ItemAdd(plot.FrameRect, plot.ID, &plot.FrameRect) && !gp.CurrentSubplot) {\n        ResetCtxForNextPlot(GImPlot);\n        return false;\n    }\n\n    // setup items (or dont)\n    if (gp.CurrentItems == nullptr)\n        gp.CurrentItems = &plot.Items;\n\n    return true;\n}\n\n//-----------------------------------------------------------------------------\n// SetupFinish\n//-----------------------------------------------------------------------------\n\nvoid SetupFinish() {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"SetupFinish needs to be called after BeginPlot!\");\n\n    ImGuiContext& G         = *GImGui;\n    ImDrawList& DrawList    = *G.CurrentWindow->DrawList;\n    const ImGuiStyle& Style = G.Style;\n\n    ImPlotPlot &plot  = *gp.CurrentPlot;\n\n    // lock setup\n    plot.SetupLocked = true;\n\n    // finalize axes and set default formatter/locator\n    for (int i = 0; i < ImAxis_COUNT; ++i) {\n        ImPlotAxis& axis = plot.Axes[i];\n        if (axis.Enabled) {\n            axis.Constrain();\n            if (!plot.Initialized && axis.CanInitFit())\n                plot.FitThisFrame = axis.FitThisFrame = true;\n        }\n        if (axis.Formatter == nullptr) {\n            axis.Formatter = Formatter_Default;\n            if (axis.HasFormatSpec)\n                axis.FormatterData = axis.FormatSpec;\n            else\n                axis.FormatterData = (void*)IMPLOT_LABEL_FORMAT;\n        }\n        if (axis.Locator == nullptr) {\n            axis.Locator = Locator_Default;\n        }\n    }\n\n    // setup nullptr orthogonal axes\n    const bool axis_equal = ImHasFlag(plot.Flags, ImPlotFlags_Equal);\n    for (int ix = ImAxis_X1, iy = ImAxis_Y1; ix < ImAxis_Y1 || iy < ImAxis_COUNT; ++ix, ++iy) {\n        ImPlotAxis& x_axis = plot.Axes[ix];\n        ImPlotAxis& y_axis = plot.Axes[iy];\n        if (x_axis.Enabled && y_axis.Enabled) {\n            if (x_axis.OrthoAxis == nullptr)\n                x_axis.OrthoAxis = &y_axis;\n            if (y_axis.OrthoAxis == nullptr)\n                y_axis.OrthoAxis = &x_axis;\n        }\n        else if (x_axis.Enabled)\n        {\n            if (x_axis.OrthoAxis == nullptr && !axis_equal)\n                x_axis.OrthoAxis = &plot.Axes[ImAxis_Y1];\n        }\n        else if (y_axis.Enabled) {\n            if (y_axis.OrthoAxis == nullptr && !axis_equal)\n                y_axis.OrthoAxis = &plot.Axes[ImAxis_X1];\n        }\n    }\n\n    // canvas/axes bb\n    plot.CanvasRect = ImRect(plot.FrameRect.Min + gp.Style.PlotPadding, plot.FrameRect.Max - gp.Style.PlotPadding);\n    plot.AxesRect   = plot.FrameRect;\n\n    // outside legend adjustments\n    if (!ImHasFlag(plot.Flags, ImPlotFlags_NoLegend) && plot.Items.GetLegendCount() > 0 && ImHasFlag(plot.Items.Legend.Flags, ImPlotLegendFlags_Outside)) {\n        ImPlotLegend& legend = plot.Items.Legend;\n        const bool horz = ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal);\n        const ImVec2 legend_size = CalcLegendSize(plot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !horz);\n        const bool west = ImHasFlag(legend.Location, ImPlotLocation_West) && !ImHasFlag(legend.Location, ImPlotLocation_East);\n        const bool east = ImHasFlag(legend.Location, ImPlotLocation_East) && !ImHasFlag(legend.Location, ImPlotLocation_West);\n        const bool north = ImHasFlag(legend.Location, ImPlotLocation_North) && !ImHasFlag(legend.Location, ImPlotLocation_South);\n        const bool south = ImHasFlag(legend.Location, ImPlotLocation_South) && !ImHasFlag(legend.Location, ImPlotLocation_North);\n        if ((west && !horz) || (west && horz && !north && !south)) {\n            plot.CanvasRect.Min.x += (legend_size.x + gp.Style.LegendPadding.x);\n            plot.AxesRect.Min.x   += (legend_size.x + gp.Style.PlotPadding.x);\n        }\n        if ((east && !horz) || (east && horz && !north && !south)) {\n            plot.CanvasRect.Max.x -= (legend_size.x + gp.Style.LegendPadding.x);\n            plot.AxesRect.Max.x   -= (legend_size.x + gp.Style.PlotPadding.x);\n        }\n        if ((north && horz) || (north && !horz && !west && !east)) {\n            plot.CanvasRect.Min.y += (legend_size.y + gp.Style.LegendPadding.y);\n            plot.AxesRect.Min.y   += (legend_size.y + gp.Style.PlotPadding.y);\n        }\n        if ((south && horz) || (south && !horz && !west && !east)) {\n            plot.CanvasRect.Max.y -= (legend_size.y + gp.Style.LegendPadding.y);\n            plot.AxesRect.Max.y   -= (legend_size.y + gp.Style.PlotPadding.y);\n        }\n    }\n\n    // plot bb\n    float pad_top = 0, pad_bot = 0, pad_left = 0, pad_right = 0;\n\n    // (0) calc top padding form title\n    ImVec2 title_size(0.0f, 0.0f);\n    if (plot.HasTitle())\n         title_size = ImGui::CalcTextSize(plot.GetTitle(), nullptr, true);\n    if (title_size.x > 0) {\n        pad_top += title_size.y + gp.Style.LabelPadding.y;\n        plot.AxesRect.Min.y += gp.Style.PlotPadding.y + pad_top;\n    }\n\n    // (1) calc addition top padding and bot padding\n    PadAndDatumAxesX(plot,pad_top,pad_bot,gp.CurrentAlignmentH);\n\n    const float plot_height = plot.CanvasRect.GetHeight() - pad_top - pad_bot;\n\n    // (2) get y tick labels (needed for left/right pad)\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n        ImPlotAxis& axis = plot.YAxis(i);\n        if (axis.WillRender() && axis.ShowDefaultTicks) {\n            axis.Locator(axis.Ticker, axis.Range, plot_height, true, axis.Formatter, axis.FormatterData);\n        }\n    }\n\n    // (3) calc left/right pad\n    PadAndDatumAxesY(plot,pad_left,pad_right,gp.CurrentAlignmentV);\n\n    const float plot_width = plot.CanvasRect.GetWidth() - pad_left - pad_right;\n\n    // (4) get x ticks\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n        ImPlotAxis& axis = plot.XAxis(i);\n        if (axis.WillRender() && axis.ShowDefaultTicks) {\n            axis.Locator(axis.Ticker, axis.Range, plot_width, false, axis.Formatter, axis.FormatterData);\n        }\n    }\n\n    // (5) calc plot bb\n    plot.PlotRect = ImRect(plot.CanvasRect.Min + ImVec2(pad_left, pad_top), plot.CanvasRect.Max - ImVec2(pad_right, pad_bot));\n\n    // HOVER------------------------------------------------------------\n\n    // axes hover rect, pixel ranges\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n        ImPlotAxis& xax = plot.XAxis(i);\n        xax.HoverRect   = ImRect(ImVec2(plot.PlotRect.Min.x, ImMin(xax.Datum1,xax.Datum2)),\n                                 ImVec2(plot.PlotRect.Max.x, ImMax(xax.Datum1,xax.Datum2)));\n        xax.PixelMin    = xax.IsInverted() ? plot.PlotRect.Max.x : plot.PlotRect.Min.x;\n        xax.PixelMax    = xax.IsInverted() ? plot.PlotRect.Min.x : plot.PlotRect.Max.x;\n        xax.UpdateTransformCache();\n    }\n\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {\n        ImPlotAxis& yax = plot.YAxis(i);\n        yax.HoverRect   = ImRect(ImVec2(ImMin(yax.Datum1,yax.Datum2),plot.PlotRect.Min.y),\n                                 ImVec2(ImMax(yax.Datum1,yax.Datum2),plot.PlotRect.Max.y));\n        yax.PixelMin    = yax.IsInverted() ? plot.PlotRect.Min.y : plot.PlotRect.Max.y;\n        yax.PixelMax    = yax.IsInverted() ? plot.PlotRect.Max.y : plot.PlotRect.Min.y;\n        yax.UpdateTransformCache();\n    }\n    // Equal axis constraint. Must happen after we set Pixels\n    // constrain equal axes for primary x and y if not approximately equal\n    // constrains x to y since x pixel size depends on y labels width, and causes feedback loops in opposite case\n    if (axis_equal) {\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n            ImPlotAxis& x_axis = plot.XAxis(i);\n            if (x_axis.OrthoAxis == nullptr)\n                continue;\n            double xar = x_axis.GetAspect();\n            double yar = x_axis.OrthoAxis->GetAspect();\n            // edge case: user has set x range this frame, so fit y to x so that we honor their request for x range\n            // NB: because of feedback across several frames, the user's x request may not be perfectly honored\n            if (x_axis.HasRange)\n                x_axis.OrthoAxis->SetAspect(xar);\n            else if (!ImAlmostEqual(xar,yar) && !x_axis.OrthoAxis->IsInputLocked())\n                 x_axis.SetAspect(yar);\n        }\n    }\n\n    // INPUT ------------------------------------------------------------------\n    if (!ImHasFlag(plot.Flags, ImPlotFlags_NoInputs))\n        UpdateInput(plot);\n\n    // fit from FitNextPlotAxes or auto fit\n    for (int i = 0; i < ImAxis_COUNT; ++i) {\n        if (gp.NextPlotData.Fit[i] || plot.Axes[i].IsAutoFitting()) {\n            plot.FitThisFrame = true;\n            plot.Axes[i].FitThisFrame = true;\n        }\n    }\n\n    // RENDER -----------------------------------------------------------------\n\n    const float txt_height = ImGui::GetTextLineHeight();\n\n    // render frame\n    if (!ImHasFlag(plot.Flags, ImPlotFlags_NoFrame))\n        ImGui::RenderFrame(plot.FrameRect.Min, plot.FrameRect.Max, GetStyleColorU32(ImPlotCol_FrameBg), true, Style.FrameRounding);\n\n    // grid bg\n    DrawList.AddRectFilled(plot.PlotRect.Min, plot.PlotRect.Max, GetStyleColorU32(ImPlotCol_PlotBg));\n\n    // transform ticks\n    for (int i = 0; i < ImAxis_COUNT; i++) {\n        ImPlotAxis& axis = plot.Axes[i];\n        if (axis.WillRender()) {\n            for (int t = 0; t < axis.Ticker.TickCount(); t++) {\n                ImPlotTick& tk = axis.Ticker.Ticks[t];\n                tk.PixelPos = IM_ROUND(axis.PlotToPixels(tk.PlotPos));\n            }\n        }\n    }\n\n    // render grid (background)\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n        ImPlotAxis& x_axis = plot.XAxis(i);\n        if (x_axis.Enabled && x_axis.HasGridLines() && !x_axis.IsForeground())\n            RenderGridLinesX(DrawList, x_axis.Ticker, plot.PlotRect, x_axis.ColorMaj, x_axis.ColorMin, gp.Style.MajorGridSize.x, gp.Style.MinorGridSize.x);\n    }\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n        ImPlotAxis& y_axis = plot.YAxis(i);\n        if (y_axis.Enabled && y_axis.HasGridLines() && !y_axis.IsForeground())\n            RenderGridLinesY(DrawList, y_axis.Ticker, plot.PlotRect,  y_axis.ColorMaj, y_axis.ColorMin, gp.Style.MajorGridSize.y, gp.Style.MinorGridSize.y);\n    }\n\n    // render x axis button, label, tick labels\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n        ImPlotAxis& ax = plot.XAxis(i);\n        if (!ax.Enabled)\n            continue;\n        if ((ax.Hovered || ax.Held) && !plot.Held && !ImHasFlag(ax.Flags, ImPlotAxisFlags_NoHighlight))\n            DrawList.AddRectFilled(ax.HoverRect.Min, ax.HoverRect.Max, ax.Held ? ax.ColorAct : ax.ColorHov);\n        else if (ax.ColorHiLi != IM_COL32_BLACK_TRANS) {\n            DrawList.AddRectFilled(ax.HoverRect.Min, ax.HoverRect.Max, ax.ColorHiLi);\n            ax.ColorHiLi = IM_COL32_BLACK_TRANS;\n        }\n        else if (ax.ColorBg != IM_COL32_BLACK_TRANS) {\n            DrawList.AddRectFilled(ax.HoverRect.Min, ax.HoverRect.Max, ax.ColorBg);\n        }\n        const ImPlotTicker& tkr = ax.Ticker;\n        const bool opp = ax.IsOpposite();\n        if (ax.HasLabel()) {\n            const char* label        = plot.GetAxisLabel(ax);\n            const ImVec2 label_size  = ImGui::CalcTextSize(label);\n            const float label_offset = (ax.HasTickLabels() ? tkr.MaxSize.y + gp.Style.LabelPadding.y : 0.0f)\n                                     + (tkr.Levels - 1) * (txt_height + gp.Style.LabelPadding.y)\n                                     + gp.Style.LabelPadding.y;\n            const ImVec2 label_pos(plot.PlotRect.GetCenter().x - label_size.x * 0.5f,\n                                   opp ? ax.Datum1 - label_offset - label_size.y : ax.Datum1 + label_offset);\n            DrawList.AddText(label_pos, ax.ColorTxt, label);\n        }\n        if (ax.HasTickLabels()) {\n            for (int j = 0; j < tkr.TickCount(); ++j) {\n                const ImPlotTick& tk = tkr.Ticks[j];\n                const float datum = ax.Datum1 + (opp ? (-gp.Style.LabelPadding.y -txt_height -tk.Level * (txt_height + gp.Style.LabelPadding.y))\n                                                     : gp.Style.LabelPadding.y + tk.Level * (txt_height + gp.Style.LabelPadding.y));\n                if (tk.ShowLabel && tk.PixelPos >= plot.PlotRect.Min.x - 1 && tk.PixelPos <= plot.PlotRect.Max.x + 1) {\n                    ImVec2 start(tk.PixelPos - 0.5f * tk.LabelSize.x, datum);\n                    DrawList.AddText(start, ax.ColorTxt, tkr.GetText(j));\n                }\n            }\n        }\n    }\n\n    // render y axis button, label, tick labels\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n        ImPlotAxis& ax = plot.YAxis(i);\n        if (!ax.Enabled)\n            continue;\n        if ((ax.Hovered || ax.Held) && !plot.Held && !ImHasFlag(ax.Flags, ImPlotAxisFlags_NoHighlight))\n            DrawList.AddRectFilled(ax.HoverRect.Min, ax.HoverRect.Max, ax.Held ? ax.ColorAct : ax.ColorHov);\n        else if (ax.ColorHiLi != IM_COL32_BLACK_TRANS) {\n            DrawList.AddRectFilled(ax.HoverRect.Min, ax.HoverRect.Max, ax.ColorHiLi);\n            ax.ColorHiLi = IM_COL32_BLACK_TRANS;\n        }\n        else if (ax.ColorBg != IM_COL32_BLACK_TRANS) {\n            DrawList.AddRectFilled(ax.HoverRect.Min, ax.HoverRect.Max, ax.ColorBg);\n        }\n        const ImPlotTicker& tkr = ax.Ticker;\n        const bool opp = ax.IsOpposite();\n        if (ax.HasLabel()) {\n            const char* label        = plot.GetAxisLabel(ax);\n            const ImVec2 label_size  = CalcTextSizeVertical(label);\n            const float label_offset = (ax.HasTickLabels() ? tkr.MaxSize.x + gp.Style.LabelPadding.x : 0.0f)\n                                     + gp.Style.LabelPadding.x;\n            const ImVec2 label_pos(opp ? ax.Datum1 + label_offset : ax.Datum1 - label_offset - label_size.x,\n                                   plot.PlotRect.GetCenter().y + label_size.y * 0.5f);\n            AddTextVertical(&DrawList, label_pos, ax.ColorTxt, label);\n        }\n        if (ax.HasTickLabels()) {\n            for (int j = 0; j < tkr.TickCount(); ++j) {\n                const ImPlotTick& tk = tkr.Ticks[j];\n                const float datum = ax.Datum1 + (opp ? gp.Style.LabelPadding.x : (-gp.Style.LabelPadding.x - tk.LabelSize.x));\n                if (tk.ShowLabel && tk.PixelPos >= plot.PlotRect.Min.y - 1 && tk.PixelPos <= plot.PlotRect.Max.y + 1) {\n                    ImVec2 start(datum, tk.PixelPos - 0.5f * tk.LabelSize.y);\n                    DrawList.AddText(start, ax.ColorTxt, tkr.GetText(j));\n                }\n            }\n        }\n    }\n\n\n    // clear legend (TODO: put elsewhere)\n    plot.Items.Legend.Reset();\n    // push ID to set item hashes (NB: !!!THIS PROBABLY NEEDS TO BE IN BEGIN PLOT!!!!)\n    ImGui::PushOverrideID(gp.CurrentItems->ID);\n}\n\n//-----------------------------------------------------------------------------\n// EndPlot()\n//-----------------------------------------------------------------------------\n\nvoid EndPlot() {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"Mismatched BeginPlot()/EndPlot()!\");\n\n    SetupLock();\n\n    ImGuiContext &G       = *GImGui;\n    ImPlotPlot &plot      = *gp.CurrentPlot;\n    ImGuiWindow * Window  = G.CurrentWindow;\n    ImDrawList & DrawList = *Window->DrawList;\n    const ImGuiIO &   IO  = ImGui::GetIO();\n\n    // FINAL RENDER -----------------------------------------------------------\n\n    const bool render_border  = gp.Style.PlotBorderSize > 0 && gp.Style.Colors[ImPlotCol_PlotBorder].w > 0;\n    const bool any_x_held = plot.Held    || AnyAxesHeld(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);\n    const bool any_y_held = plot.Held    || AnyAxesHeld(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);\n\n    ImGui::PushClipRect(plot.FrameRect.Min, plot.FrameRect.Max, true);\n\n    // render grid (foreground)\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n        ImPlotAxis& x_axis = plot.XAxis(i);\n        if (x_axis.Enabled && x_axis.HasGridLines() && x_axis.IsForeground())\n            RenderGridLinesX(DrawList, x_axis.Ticker, plot.PlotRect, x_axis.ColorMaj, x_axis.ColorMin, gp.Style.MajorGridSize.x, gp.Style.MinorGridSize.x);\n    }\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n        ImPlotAxis& y_axis = plot.YAxis(i);\n        if (y_axis.Enabled && y_axis.HasGridLines() && y_axis.IsForeground())\n            RenderGridLinesY(DrawList, y_axis.Ticker, plot.PlotRect,  y_axis.ColorMaj, y_axis.ColorMin, gp.Style.MajorGridSize.y, gp.Style.MinorGridSize.y);\n    }\n\n\n    // render title\n    if (plot.HasTitle()) {\n        ImU32 col = GetStyleColorU32(ImPlotCol_TitleText);\n        AddTextCentered(&DrawList,ImVec2(plot.PlotRect.GetCenter().x, plot.CanvasRect.Min.y),col,plot.GetTitle());\n    }\n\n    // render x ticks\n    int count_B = 0, count_T = 0;\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n        const ImPlotAxis& ax = plot.XAxis(i);\n        if (!ax.Enabled)\n            continue;\n        const ImPlotTicker& tkr = ax.Ticker;\n        const bool opp = ax.IsOpposite();\n        const bool aux = ((opp && count_T > 0)||(!opp && count_B > 0));\n        if (ax.HasTickMarks()) {\n            const float direction = opp ? 1.0f : -1.0f;\n            for (int j = 0; j < tkr.TickCount(); ++j) {\n                const ImPlotTick& tk = tkr.Ticks[j];\n                if (tk.Level != 0 || tk.PixelPos < plot.PlotRect.Min.x || tk.PixelPos > plot.PlotRect.Max.x)\n                    continue;\n                const ImVec2 start(tk.PixelPos, ax.Datum1);\n                const float len = (!aux && tk.Major) ? gp.Style.MajorTickLen.x  : gp.Style.MinorTickLen.x;\n                const float thk = (!aux && tk.Major) ? gp.Style.MajorTickSize.x : gp.Style.MinorTickSize.x;\n                DrawList.AddLine(start, start + ImVec2(0,direction*len), ax.ColorTick, thk);\n            }\n            if (aux || !render_border)\n                DrawList.AddLine(ImVec2(plot.PlotRect.Min.x,ax.Datum1), ImVec2(plot.PlotRect.Max.x,ax.Datum1), ax.ColorTick, gp.Style.MinorTickSize.x);\n        }\n        count_B += !opp;\n        count_T +=  opp;\n    }\n\n    // render y ticks\n    int count_L = 0, count_R = 0;\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n        const ImPlotAxis& ax = plot.YAxis(i);\n        if (!ax.Enabled)\n            continue;\n        const ImPlotTicker& tkr = ax.Ticker;\n        const bool opp = ax.IsOpposite();\n        const bool aux = ((opp && count_R > 0)||(!opp && count_L > 0));\n        if (ax.HasTickMarks()) {\n            const float direction = opp ? -1.0f : 1.0f;\n            for (int j = 0; j < tkr.TickCount(); ++j) {\n                const ImPlotTick& tk = tkr.Ticks[j];\n                if (tk.Level != 0 || tk.PixelPos < plot.PlotRect.Min.y || tk.PixelPos > plot.PlotRect.Max.y)\n                    continue;\n                const ImVec2 start(ax.Datum1, tk.PixelPos);\n                const float len = (!aux && tk.Major) ? gp.Style.MajorTickLen.y  : gp.Style.MinorTickLen.y;\n                const float thk = (!aux && tk.Major) ? gp.Style.MajorTickSize.y : gp.Style.MinorTickSize.y;\n                DrawList.AddLine(start, start + ImVec2(direction*len,0), ax.ColorTick, thk);\n            }\n            if (aux || !render_border)\n                DrawList.AddLine(ImVec2(ax.Datum1, plot.PlotRect.Min.y), ImVec2(ax.Datum1, plot.PlotRect.Max.y), ax.ColorTick, gp.Style.MinorTickSize.y);\n        }\n        count_L += !opp;\n        count_R +=  opp;\n    }\n    ImGui::PopClipRect();\n\n    // render annotations\n    PushPlotClipRect();\n    for (int i = 0; i < gp.Annotations.Size; ++i) {\n        const char* txt       = gp.Annotations.GetText(i);\n        ImPlotAnnotation& an  = gp.Annotations.Annotations[i];\n        const ImVec2 txt_size = ImGui::CalcTextSize(txt);\n        const ImVec2 size     = txt_size + gp.Style.AnnotationPadding * 2;\n        ImVec2 pos            = an.Pos;\n        if (an.Offset.x == 0)\n            pos.x -= size.x / 2;\n        else if (an.Offset.x > 0)\n            pos.x += an.Offset.x;\n        else\n            pos.x -= size.x - an.Offset.x;\n        if (an.Offset.y == 0)\n            pos.y -= size.y / 2;\n        else if (an.Offset.y > 0)\n            pos.y += an.Offset.y;\n        else\n            pos.y -= size.y - an.Offset.y;\n        if (an.Clamp)\n            pos = ClampLabelPos(pos, size, plot.PlotRect.Min, plot.PlotRect.Max);\n        ImRect rect(pos,pos+size);\n        if (an.Offset.x != 0 || an.Offset.y != 0) {\n            ImVec2 corners[4] = {rect.GetTL(), rect.GetTR(), rect.GetBR(), rect.GetBL()};\n            int min_corner = 0;\n            float min_len = FLT_MAX;\n            for (int c = 0; c < 4; ++c) {\n                float len = ImLengthSqr(an.Pos - corners[c]);\n                if (len < min_len) {\n                    min_corner = c;\n                    min_len = len;\n                }\n            }\n            DrawList.AddLine(an.Pos, corners[min_corner], an.ColorBg);\n        }\n        DrawList.AddRectFilled(rect.Min, rect.Max, an.ColorBg);\n        DrawList.AddText(pos + gp.Style.AnnotationPadding, an.ColorFg, txt);\n    }\n\n    // render selection\n    if (plot.Selected)\n        RenderSelectionRect(DrawList, plot.SelectRect.Min + plot.PlotRect.Min, plot.SelectRect.Max + plot.PlotRect.Min, GetStyleColorVec4(ImPlotCol_Selection));\n\n    // render crosshairs\n    if (ImHasFlag(plot.Flags, ImPlotFlags_Crosshairs) && plot.Hovered && !(any_x_held || any_y_held) && !plot.Selecting && !plot.Items.Legend.Hovered) {\n        ImGui::SetMouseCursor(ImGuiMouseCursor_None);\n        ImVec2 xy = IO.MousePos;\n        ImVec2 h1(plot.PlotRect.Min.x, xy.y);\n        ImVec2 h2(xy.x - 5, xy.y);\n        ImVec2 h3(xy.x + 5, xy.y);\n        ImVec2 h4(plot.PlotRect.Max.x, xy.y);\n        ImVec2 v1(xy.x, plot.PlotRect.Min.y);\n        ImVec2 v2(xy.x, xy.y - 5);\n        ImVec2 v3(xy.x, xy.y + 5);\n        ImVec2 v4(xy.x, plot.PlotRect.Max.y);\n        ImU32 col = GetStyleColorU32(ImPlotCol_Crosshairs);\n        DrawList.AddLine(h1, h2, col);\n        DrawList.AddLine(h3, h4, col);\n        DrawList.AddLine(v1, v2, col);\n        DrawList.AddLine(v3, v4, col);\n    }\n\n    // render mouse pos\n    if (!ImHasFlag(plot.Flags, ImPlotFlags_NoMouseText) && (plot.Hovered || ImHasFlag(plot.MouseTextFlags, ImPlotMouseTextFlags_ShowAlways))) {\n\n        const bool no_aux = ImHasFlag(plot.MouseTextFlags, ImPlotMouseTextFlags_NoAuxAxes);\n        const bool no_fmt = ImHasFlag(plot.MouseTextFlags, ImPlotMouseTextFlags_NoFormat);\n\n        ImGuiTextBuffer& builder = gp.MousePosStringBuilder;\n        builder.Buf.shrink(0);\n        char buff[IMPLOT_LABEL_MAX_SIZE];\n\n        const int num_x = no_aux ? 1 : IMPLOT_NUM_X_AXES;\n        for (int i = 0; i < num_x; ++i) {\n            ImPlotAxis& x_axis = plot.XAxis(i);\n            if (!x_axis.Enabled)\n                continue;\n            if (i > 0)\n                builder.append(\", (\");\n            double v = x_axis.PixelsToPlot(IO.MousePos.x);\n            if (no_fmt)\n                Formatter_Default(v,buff,IMPLOT_LABEL_MAX_SIZE,(void*)IMPLOT_LABEL_FORMAT);\n            else\n                LabelAxisValue(x_axis,v,buff,IMPLOT_LABEL_MAX_SIZE,true);\n            builder.append(buff);\n            if (i > 0)\n                builder.append(\")\");\n        }\n        builder.append(\", \");\n        const int num_y = no_aux ? 1 : IMPLOT_NUM_Y_AXES;\n        for (int i = 0; i < num_y; ++i) {\n            ImPlotAxis& y_axis = plot.YAxis(i);\n            if (!y_axis.Enabled)\n                continue;\n            if (i > 0)\n                builder.append(\", (\");\n            double v = y_axis.PixelsToPlot(IO.MousePos.y);\n            if (no_fmt)\n                Formatter_Default(v,buff,IMPLOT_LABEL_MAX_SIZE,(void*)IMPLOT_LABEL_FORMAT);\n            else\n                LabelAxisValue(y_axis,v,buff,IMPLOT_LABEL_MAX_SIZE,true);\n            builder.append(buff);\n            if (i > 0)\n                builder.append(\")\");\n        }\n\n        if (!builder.empty()) {\n            const ImVec2 size = ImGui::CalcTextSize(builder.c_str());\n            const ImVec2 pos = GetLocationPos(plot.PlotRect, size, plot.MouseTextLocation, gp.Style.MousePosPadding);\n            DrawList.AddText(pos, GetStyleColorU32(ImPlotCol_InlayText), builder.c_str());\n        }\n    }\n    PopPlotClipRect();\n\n    // axis side switch\n    if (!plot.Held) {\n        ImVec2 mouse_pos = ImGui::GetIO().MousePos;\n        ImRect trigger_rect = plot.PlotRect;\n        trigger_rect.Expand(-10);\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n            ImPlotAxis& x_axis = plot.XAxis(i);\n            if (ImHasFlag(x_axis.Flags, ImPlotAxisFlags_NoSideSwitch))\n                continue;\n            if (x_axis.Held && plot.PlotRect.Contains(mouse_pos)) {\n                const bool opp = ImHasFlag(x_axis.Flags, ImPlotAxisFlags_Opposite);\n                if (!opp) {\n                    ImRect rect(plot.PlotRect.Min.x - 5, plot.PlotRect.Min.y - 5,\n                                plot.PlotRect.Max.x + 5, plot.PlotRect.Min.y + 5);\n                    if (mouse_pos.y < plot.PlotRect.Max.y - 10)\n                        DrawList.AddRectFilled(rect.Min, rect.Max, x_axis.ColorHov);\n                    if (rect.Contains(mouse_pos))\n                        x_axis.Flags |= ImPlotAxisFlags_Opposite;\n                }\n                else {\n                    ImRect rect(plot.PlotRect.Min.x - 5, plot.PlotRect.Max.y - 5,\n                                plot.PlotRect.Max.x + 5, plot.PlotRect.Max.y + 5);\n                    if (mouse_pos.y > plot.PlotRect.Min.y + 10)\n                        DrawList.AddRectFilled(rect.Min, rect.Max, x_axis.ColorHov);\n                    if (rect.Contains(mouse_pos))\n                        x_axis.Flags &= ~ImPlotAxisFlags_Opposite;\n                }\n            }\n        }\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {\n            ImPlotAxis& y_axis = plot.YAxis(i);\n            if (ImHasFlag(y_axis.Flags, ImPlotAxisFlags_NoSideSwitch))\n                continue;\n            if (y_axis.Held && plot.PlotRect.Contains(mouse_pos)) {\n                const bool opp = ImHasFlag(y_axis.Flags, ImPlotAxisFlags_Opposite);\n                if (!opp) {\n                    ImRect rect(plot.PlotRect.Max.x - 5, plot.PlotRect.Min.y - 5,\n                                plot.PlotRect.Max.x + 5, plot.PlotRect.Max.y + 5);\n                    if (mouse_pos.x > plot.PlotRect.Min.x + 10)\n                        DrawList.AddRectFilled(rect.Min, rect.Max, y_axis.ColorHov);\n                    if (rect.Contains(mouse_pos))\n                        y_axis.Flags |= ImPlotAxisFlags_Opposite;\n                }\n                else {\n                    ImRect rect(plot.PlotRect.Min.x - 5, plot.PlotRect.Min.y - 5,\n                                plot.PlotRect.Min.x + 5, plot.PlotRect.Max.y + 5);\n                    if (mouse_pos.x < plot.PlotRect.Max.x - 10)\n                        DrawList.AddRectFilled(rect.Min, rect.Max, y_axis.ColorHov);\n                    if (rect.Contains(mouse_pos))\n                        y_axis.Flags &= ~ImPlotAxisFlags_Opposite;\n                }\n            }\n        }\n    }\n\n    // reset legend hovers\n    plot.Items.Legend.Hovered = false;\n    for (int i = 0; i < plot.Items.GetItemCount(); ++i)\n        plot.Items.GetItemByIndex(i)->LegendHovered = false;\n    // render legend\n    if (!ImHasFlag(plot.Flags, ImPlotFlags_NoLegend) && plot.Items.GetLegendCount() > 0) {\n        ImPlotLegend& legend = plot.Items.Legend;\n        const bool   legend_out  = ImHasFlag(legend.Flags, ImPlotLegendFlags_Outside);\n        const bool   legend_horz = ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal);\n        const ImVec2 legend_size = CalcLegendSize(plot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz);\n        const ImVec2 legend_pos  = GetLocationPos(legend_out ? plot.FrameRect : plot.PlotRect,\n                                                  legend_size,\n                                                  legend.Location,\n                                                  legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding);\n        legend.Rect = ImRect(legend_pos, legend_pos + legend_size);\n        // test hover\n        legend.Hovered = ImGui::IsWindowHovered() && legend.Rect.Contains(IO.MousePos);\n\n        if (legend_out)\n            ImGui::PushClipRect(plot.FrameRect.Min, plot.FrameRect.Max, true);\n        else\n            PushPlotClipRect();\n        ImU32  col_bg      = GetStyleColorU32(ImPlotCol_LegendBg);\n        ImU32  col_bd      = GetStyleColorU32(ImPlotCol_LegendBorder);\n        DrawList.AddRectFilled(legend.Rect.Min, legend.Rect.Max, col_bg);\n        DrawList.AddRect(legend.Rect.Min, legend.Rect.Max, col_bd);\n        bool legend_contextable = ShowLegendEntries(plot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)\n                                && !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);\n\n        // main ctx menu\n        if (gp.OpenContextThisFrame && legend_contextable && !ImHasFlag(plot.Flags, ImPlotFlags_NoMenus))\n            ImGui::OpenPopup(\"##LegendContext\");\n        ImGui::PopClipRect();\n        if (ImGui::BeginPopup(\"##LegendContext\")) {\n            ImGui::Text(\"Legend\"); ImGui::Separator();\n            if (ShowLegendContextMenu(legend, !ImHasFlag(plot.Flags, ImPlotFlags_NoLegend)))\n                ImFlipFlag(plot.Flags, ImPlotFlags_NoLegend);\n            ImGui::EndPopup();\n        }\n    }\n    else {\n        plot.Items.Legend.Rect = ImRect();\n    }\n\n    // render border\n    if (render_border)\n        DrawList.AddRect(plot.PlotRect.Min, plot.PlotRect.Max, GetStyleColorU32(ImPlotCol_PlotBorder), 0, ImDrawFlags_RoundCornersAll, gp.Style.PlotBorderSize);\n\n    // render tags\n    for (int i = 0; i < gp.Tags.Size; ++i) {\n        ImPlotTag& tag  = gp.Tags.Tags[i];\n        ImPlotAxis& axis = plot.Axes[tag.Axis];\n        if (!axis.Enabled || !axis.Range.Contains(tag.Value))\n            continue;\n        const char* txt = gp.Tags.GetText(i);\n        ImVec2 text_size = ImGui::CalcTextSize(txt);\n        ImVec2 size = text_size + gp.Style.AnnotationPadding * 2;\n        ImVec2 pos;\n        axis.Ticker.OverrideSizeLate(size);\n        float pix = IM_ROUND(axis.PlotToPixels(tag.Value));\n        if (axis.Vertical) {\n            if (axis.IsOpposite()) {\n                pos = ImVec2(axis.Datum1 + gp.Style.LabelPadding.x, pix - size.y * 0.5f);\n                DrawList.AddTriangleFilled(ImVec2(axis.Datum1,pix), pos, pos + ImVec2(0,size.y), tag.ColorBg);\n            }\n            else {\n                pos = ImVec2(axis.Datum1 - size.x - gp.Style.LabelPadding.x, pix - size.y * 0.5f);\n                DrawList.AddTriangleFilled(pos + ImVec2(size.x,0), ImVec2(axis.Datum1,pix), pos+size, tag.ColorBg);\n            }\n        }\n        else {\n            if (axis.IsOpposite()) {\n                pos = ImVec2(pix - size.x * 0.5f, axis.Datum1 - size.y - gp.Style.LabelPadding.y );\n                DrawList.AddTriangleFilled(pos + ImVec2(0,size.y), pos + size, ImVec2(pix,axis.Datum1), tag.ColorBg);\n            }\n            else {\n                pos = ImVec2(pix - size.x * 0.5f, axis.Datum1 + gp.Style.LabelPadding.y);\n                DrawList.AddTriangleFilled(pos, ImVec2(pix,axis.Datum1), pos + ImVec2(size.x, 0), tag.ColorBg);\n            }\n        }\n        DrawList.AddRectFilled(pos,pos+size,tag.ColorBg);\n        DrawList.AddText(pos+gp.Style.AnnotationPadding,tag.ColorFg,txt);\n    }\n\n    // FIT DATA --------------------------------------------------------------\n    const bool axis_equal = ImHasFlag(plot.Flags, ImPlotFlags_Equal);\n    if (plot.FitThisFrame) {\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {\n            ImPlotAxis& x_axis = plot.XAxis(i);\n            if (x_axis.FitThisFrame) {\n                x_axis.ApplyFit(gp.Style.FitPadding.x);\n                if (axis_equal && x_axis.OrthoAxis != nullptr) {\n                    double aspect = x_axis.GetAspect();\n                    ImPlotAxis& y_axis = *x_axis.OrthoAxis;\n                    if (y_axis.FitThisFrame) {\n                        y_axis.ApplyFit(gp.Style.FitPadding.y);\n                        y_axis.FitThisFrame = false;\n                        aspect = ImMax(aspect, y_axis.GetAspect());\n                    }\n                    x_axis.SetAspect(aspect);\n                    y_axis.SetAspect(aspect);\n                }\n            }\n        }\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {\n            ImPlotAxis& y_axis = plot.YAxis(i);\n            if (y_axis.FitThisFrame) {\n                y_axis.ApplyFit(gp.Style.FitPadding.y);\n                if (axis_equal && y_axis.OrthoAxis != nullptr) {\n                    double aspect = y_axis.GetAspect();\n                    ImPlotAxis& x_axis = *y_axis.OrthoAxis;\n                    if (x_axis.FitThisFrame) {\n                        x_axis.ApplyFit(gp.Style.FitPadding.x);\n                        x_axis.FitThisFrame = false;\n                        aspect = ImMax(x_axis.GetAspect(), aspect);\n                    }\n                    x_axis.SetAspect(aspect);\n                    y_axis.SetAspect(aspect);\n                }\n            }\n        }\n        plot.FitThisFrame = false;\n    }\n\n    // CONTEXT MENUS -----------------------------------------------------------\n\n    ImGui::PushOverrideID(plot.ID);\n\n    const bool can_ctx = gp.OpenContextThisFrame &&\n                         !ImHasFlag(plot.Flags, ImPlotFlags_NoMenus) &&\n                         !plot.Items.Legend.Hovered;\n\n\n\n    // main ctx menu\n    if (can_ctx && plot.Hovered)\n        ImGui::OpenPopup(\"##PlotContext\");\n    if (ImGui::BeginPopup(\"##PlotContext\")) {\n        ShowPlotContextMenu(plot);\n        ImGui::EndPopup();\n    }\n\n    // axes ctx menus\n    for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n        ImGui::PushID(i);\n        ImPlotAxis& x_axis = plot.XAxis(i);\n        if (can_ctx && x_axis.Hovered && x_axis.HasMenus())\n            ImGui::OpenPopup(\"##XContext\");\n        if (ImGui::BeginPopup(\"##XContext\")) {\n            ImGui::Text(x_axis.HasLabel() ? plot.GetAxisLabel(x_axis) :  i == 0 ? \"X-Axis\" : \"X-Axis %d\", i + 1);\n            ImGui::Separator();\n            ShowAxisContextMenu(x_axis, axis_equal ? x_axis.OrthoAxis : nullptr, true);\n            ImGui::EndPopup();\n        }\n        ImGui::PopID();\n    }\n    for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {\n        ImGui::PushID(i);\n        ImPlotAxis& y_axis = plot.YAxis(i);\n        if (can_ctx && y_axis.Hovered && y_axis.HasMenus())\n            ImGui::OpenPopup(\"##YContext\");\n        if (ImGui::BeginPopup(\"##YContext\")) {\n            ImGui::Text(y_axis.HasLabel() ? plot.GetAxisLabel(y_axis) : i == 0 ? \"Y-Axis\" : \"Y-Axis %d\", i + 1);\n            ImGui::Separator();\n            ShowAxisContextMenu(y_axis, axis_equal ? y_axis.OrthoAxis : nullptr, false);\n            ImGui::EndPopup();\n        }\n        ImGui::PopID();\n    }\n    ImGui::PopID();\n\n    // LINKED AXES ------------------------------------------------------------\n\n    for (int i = 0; i < ImAxis_COUNT; ++i)\n        plot.Axes[i].PushLinks();\n\n\n    // CLEANUP ----------------------------------------------------------------\n\n    // remove items\n    if (gp.CurrentItems == &plot.Items)\n        gp.CurrentItems = nullptr;\n    // reset the plot items for the next frame\n    for (int i = 0; i < plot.Items.GetItemCount(); ++i) {\n        plot.Items.GetItemByIndex(i)->SeenThisFrame = false;\n    }\n\n    // mark the plot as initialized, i.e. having made it through one frame completely\n    plot.Initialized = true;\n    // Pop ImGui::PushID at the end of BeginPlot\n    ImGui::PopID();\n    // Reset context for next plot\n    ResetCtxForNextPlot(GImPlot);\n\n    // setup next subplot\n    if (gp.CurrentSubplot != nullptr) {\n        ImGui::PopID();\n        SubplotNextCell();\n    }\n}\n\n//-----------------------------------------------------------------------------\n// BEGIN/END SUBPLOT\n//-----------------------------------------------------------------------------\n\nstatic const float SUBPLOT_BORDER_SIZE             = 1.0f;\nstatic const float SUBPLOT_SPLITTER_HALF_THICKNESS = 4.0f;\nstatic const float SUBPLOT_SPLITTER_FEEDBACK_TIMER = 0.06f;\n\nvoid SubplotSetCell(int row, int col) {\n    ImPlotContext& gp      = *GImPlot;\n    ImPlotSubplot& subplot = *gp.CurrentSubplot;\n    if (row >= subplot.Rows || col >= subplot.Cols)\n        return;\n    float xoff = 0;\n    float yoff = 0;\n    for (int c = 0; c < col; ++c)\n        xoff += subplot.ColRatios[c];\n    for (int r = 0; r < row; ++r)\n        yoff += subplot.RowRatios[r];\n    const ImVec2 grid_size = subplot.GridRect.GetSize();\n    ImVec2 cpos            = subplot.GridRect.Min + ImVec2(xoff*grid_size.x,yoff*grid_size.y);\n    cpos.x = IM_ROUND(cpos.x);\n    cpos.y = IM_ROUND(cpos.y);\n    ImGui::GetCurrentWindow()->DC.CursorPos =  cpos;\n    // set cell size\n    subplot.CellSize.x = IM_ROUND(subplot.GridRect.GetWidth()  * subplot.ColRatios[col]);\n    subplot.CellSize.y = IM_ROUND(subplot.GridRect.GetHeight() * subplot.RowRatios[row]);\n    // setup links\n    const bool lx = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkAllX);\n    const bool ly = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkAllY);\n    const bool lr = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkRows);\n    const bool lc = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_LinkCols);\n\n    SetNextAxisLinks(ImAxis_X1, lx ? &subplot.ColLinkData[0].Min : lc ? &subplot.ColLinkData[col].Min : nullptr,\n                                lx ? &subplot.ColLinkData[0].Max : lc ? &subplot.ColLinkData[col].Max : nullptr);\n    SetNextAxisLinks(ImAxis_Y1, ly ? &subplot.RowLinkData[0].Min : lr ? &subplot.RowLinkData[row].Min : nullptr,\n                                ly ? &subplot.RowLinkData[0].Max : lr ? &subplot.RowLinkData[row].Max : nullptr);\n    // setup alignment\n    if (!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoAlign)) {\n        gp.CurrentAlignmentH = &subplot.RowAlignmentData[row];\n        gp.CurrentAlignmentV = &subplot.ColAlignmentData[col];\n    }\n    // set idx\n    if (ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ColMajor))\n        subplot.CurrentIdx = col * subplot.Rows + row;\n    else\n        subplot.CurrentIdx = row * subplot.Cols + col;\n}\n\nvoid SubplotSetCell(int idx) {\n    ImPlotContext& gp      = *GImPlot;\n    ImPlotSubplot& subplot = *gp.CurrentSubplot;\n    if (idx >= subplot.Rows * subplot.Cols)\n        return;\n    int row = 0, col = 0;\n    if (ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ColMajor)) {\n        row = idx % subplot.Rows;\n        col = idx / subplot.Rows;\n    }\n    else {\n        row = idx / subplot.Cols;\n        col = idx % subplot.Cols;\n    }\n    return SubplotSetCell(row, col);\n}\n\nvoid SubplotNextCell() {\n    ImPlotContext& gp      = *GImPlot;\n    ImPlotSubplot& subplot = *gp.CurrentSubplot;\n    SubplotSetCell(++subplot.CurrentIdx);\n}\n\nbool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, ImPlotSubplotFlags flags, float* row_sizes, float* col_sizes) {\n    IM_ASSERT_USER_ERROR(rows > 0 && cols > 0, \"Invalid sizing arguments!\");\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentSubplot == nullptr, \"Mismatched BeginSubplots()/EndSubplots()!\");\n    ImGuiContext &G = *GImGui;\n    ImGuiWindow * Window = G.CurrentWindow;\n    if (Window->SkipItems)\n        return false;\n    const ImGuiID ID = Window->GetID(title);\n    bool just_created = gp.Subplots.GetByKey(ID) == nullptr;\n    gp.CurrentSubplot = gp.Subplots.GetOrAddByKey(ID);\n    ImPlotSubplot& subplot = *gp.CurrentSubplot;\n    subplot.ID       = ID;\n    subplot.Items.ID = ID - 1;\n    subplot.HasTitle = ImGui::FindRenderedTextEnd(title, nullptr) != title;\n    // push ID\n    ImGui::PushID(ID);\n\n    if (just_created)\n        subplot.Flags = flags;\n    else if (flags != subplot.PreviousFlags)\n        subplot.Flags = flags;\n    subplot.PreviousFlags = flags;\n\n    // check for change in rows and cols\n    if (subplot.Rows != rows || subplot.Cols != cols) {\n        subplot.RowAlignmentData.resize(rows);\n        subplot.RowLinkData.resize(rows);\n        subplot.RowRatios.resize(rows);\n        for (int r = 0; r < rows; ++r) {\n            subplot.RowAlignmentData[r].Reset();\n            subplot.RowLinkData[r] = ImPlotRange(0,1);\n            subplot.RowRatios[r] = 1.0f / rows;\n        }\n        subplot.ColAlignmentData.resize(cols);\n        subplot.ColLinkData.resize(cols);\n        subplot.ColRatios.resize(cols);\n        for (int c = 0; c < cols; ++c) {\n            subplot.ColAlignmentData[c].Reset();\n            subplot.ColLinkData[c] = ImPlotRange(0,1);\n            subplot.ColRatios[c] = 1.0f / cols;\n        }\n    }\n    // check incoming size requests\n    float row_sum = 0, col_sum = 0;\n    if (row_sizes != nullptr) {\n        row_sum = ImSum(row_sizes, rows);\n        for (int r = 0; r < rows; ++r)\n            subplot.RowRatios[r] = row_sizes[r] / row_sum;\n    }\n    if (col_sizes != nullptr) {\n        col_sum = ImSum(col_sizes, cols);\n        for (int c = 0; c < cols; ++c)\n            subplot.ColRatios[c] = col_sizes[c] / col_sum;\n    }\n    subplot.Rows = rows;\n    subplot.Cols = cols;\n\n    // calc plot frame sizes\n    ImVec2 title_size(0.0f, 0.0f);\n    if (!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoTitle))\n         title_size = ImGui::CalcTextSize(title, nullptr, true);\n    const float pad_top = title_size.x > 0.0f ? title_size.y + gp.Style.LabelPadding.y : 0;\n    const ImVec2 half_pad = gp.Style.PlotPadding/2;\n    const ImVec2 frame_size = ImGui::CalcItemSize(size, gp.Style.PlotDefaultSize.x, gp.Style.PlotDefaultSize.y);\n    subplot.FrameRect = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);\n    subplot.GridRect.Min = subplot.FrameRect.Min + half_pad + ImVec2(0,pad_top);\n    subplot.GridRect.Max = subplot.FrameRect.Max - half_pad;\n    subplot.FrameHovered = subplot.FrameRect.Contains(ImGui::GetMousePos()) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows);\n\n    // outside legend adjustments (TODO: make function)\n    const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);\n    if (share_items)\n        gp.CurrentItems = &subplot.Items;\n    if (share_items && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoLegend) && subplot.Items.GetLegendCount() > 0) {\n        ImPlotLegend& legend = subplot.Items.Legend;\n        const bool horz = ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal);\n        const ImVec2 legend_size = CalcLegendSize(subplot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !horz);\n        const bool west = ImHasFlag(legend.Location, ImPlotLocation_West) && !ImHasFlag(legend.Location, ImPlotLocation_East);\n        const bool east = ImHasFlag(legend.Location, ImPlotLocation_East) && !ImHasFlag(legend.Location, ImPlotLocation_West);\n        const bool north = ImHasFlag(legend.Location, ImPlotLocation_North) && !ImHasFlag(legend.Location, ImPlotLocation_South);\n        const bool south = ImHasFlag(legend.Location, ImPlotLocation_South) && !ImHasFlag(legend.Location, ImPlotLocation_North);\n        if ((west && !horz) || (west && horz && !north && !south))\n            subplot.GridRect.Min.x += (legend_size.x + gp.Style.LegendPadding.x);\n        if ((east && !horz) || (east && horz && !north && !south))\n            subplot.GridRect.Max.x -= (legend_size.x + gp.Style.LegendPadding.x);\n        if ((north && horz) || (north && !horz && !west && !east))\n            subplot.GridRect.Min.y += (legend_size.y + gp.Style.LegendPadding.y);\n        if ((south && horz) || (south && !horz && !west && !east))\n            subplot.GridRect.Max.y -= (legend_size.y + gp.Style.LegendPadding.y);\n    }\n\n    // render single background frame\n    ImGui::RenderFrame(subplot.FrameRect.Min, subplot.FrameRect.Max, GetStyleColorU32(ImPlotCol_FrameBg), true, ImGui::GetStyle().FrameRounding);\n    // render title\n    if (title_size.x > 0.0f && !ImHasFlag(subplot.Flags, ImPlotFlags_NoTitle)) {\n        const ImU32 col = GetStyleColorU32(ImPlotCol_TitleText);\n        AddTextCentered(ImGui::GetWindowDrawList(),ImVec2(subplot.GridRect.GetCenter().x, subplot.GridRect.Min.y - pad_top + half_pad.y),col,title);\n    }\n\n    // render splitters\n    if (!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoResize)) {\n        ImDrawList& DrawList = *ImGui::GetWindowDrawList();\n        const ImU32 hov_col = ImGui::ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_SeparatorHovered]);\n        const ImU32 act_col = ImGui::ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_SeparatorActive]);\n        float xpos = subplot.GridRect.Min.x;\n        float ypos = subplot.GridRect.Min.y;\n        int separator = 1;\n        // bool pass = false;\n        for (int r = 0; r < subplot.Rows-1; ++r) {\n            ypos += subplot.RowRatios[r] * subplot.GridRect.GetHeight();\n            const ImGuiID sep_id = subplot.ID + separator;\n            ImGui::KeepAliveID(sep_id);\n            const ImRect sep_bb = ImRect(subplot.GridRect.Min.x, ypos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.x, ypos+SUBPLOT_SPLITTER_HALF_THICKNESS);\n            bool sep_hov = false, sep_hld = false;\n            const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);\n            if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) {\n                if (sep_clk && ImGui::IsMouseDoubleClicked(0)) {\n                    float p = (subplot.RowRatios[r] + subplot.RowRatios[r+1])/2;\n                    subplot.RowRatios[r] = subplot.RowRatios[r+1] = p;\n                }\n                if (sep_clk) {\n                    subplot.TempSizes[0] = subplot.RowRatios[r];\n                    subplot.TempSizes[1] = subplot.RowRatios[r+1];\n                }\n                if (sep_hld) {\n                    float dp = ImGui::GetMouseDragDelta(0).y  / subplot.GridRect.GetHeight();\n                    if (subplot.TempSizes[0] + dp > 0.1f && subplot.TempSizes[1] - dp > 0.1f) {\n                        subplot.RowRatios[r]   = subplot.TempSizes[0] + dp;\n                        subplot.RowRatios[r+1] = subplot.TempSizes[1] - dp;\n                    }\n                }\n                DrawList.AddLine(ImVec2(IM_ROUND(subplot.GridRect.Min.x),IM_ROUND(ypos)),\n                                 ImVec2(IM_ROUND(subplot.GridRect.Max.x),IM_ROUND(ypos)),\n                                 sep_hld ? act_col : hov_col, SUBPLOT_BORDER_SIZE);\n                ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);\n            }\n            separator++;\n        }\n        for (int c = 0; c < subplot.Cols-1; ++c) {\n            xpos += subplot.ColRatios[c] * subplot.GridRect.GetWidth();\n            const ImGuiID sep_id = subplot.ID + separator;\n            ImGui::KeepAliveID(sep_id);\n            const ImRect sep_bb = ImRect(xpos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Min.y, xpos+SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.y);\n            bool sep_hov = false, sep_hld = false;\n            const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);\n            if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) {\n                if (sep_clk && ImGui::IsMouseDoubleClicked(0)) {\n                    float p = (subplot.ColRatios[c] + subplot.ColRatios[c+1])/2;\n                    subplot.ColRatios[c] = subplot.ColRatios[c+1] = p;\n                }\n                if (sep_clk) {\n                    subplot.TempSizes[0] = subplot.ColRatios[c];\n                    subplot.TempSizes[1] = subplot.ColRatios[c+1];\n                }\n                if (sep_hld) {\n                    float dp = ImGui::GetMouseDragDelta(0).x / subplot.GridRect.GetWidth();\n                    if (subplot.TempSizes[0] + dp > 0.1f && subplot.TempSizes[1] - dp > 0.1f) {\n                        subplot.ColRatios[c]   = subplot.TempSizes[0] + dp;\n                        subplot.ColRatios[c+1] = subplot.TempSizes[1] - dp;\n                    }\n                }\n                DrawList.AddLine(ImVec2(IM_ROUND(xpos),IM_ROUND(subplot.GridRect.Min.y)),\n                                 ImVec2(IM_ROUND(xpos),IM_ROUND(subplot.GridRect.Max.y)),\n                                 sep_hld ? act_col : hov_col, SUBPLOT_BORDER_SIZE);\n                ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);\n            }\n            separator++;\n        }\n    }\n\n    // set outgoing sizes\n    if (row_sizes != nullptr) {\n        for (int r = 0; r < rows; ++r)\n            row_sizes[r] = subplot.RowRatios[r] * row_sum;\n    }\n    if (col_sizes != nullptr) {\n        for (int c = 0; c < cols; ++c)\n            col_sizes[c] = subplot.ColRatios[c] * col_sum;\n    }\n\n    // push styling\n    PushStyleColor(ImPlotCol_FrameBg, IM_COL32_BLACK_TRANS);\n    PushStyleVar(ImPlotStyleVar_PlotPadding, half_pad);\n    PushStyleVar(ImPlotStyleVar_PlotMinSize, ImVec2(0,0));\n    ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize,0);\n\n    // set initial cursor pos\n    Window->DC.CursorPos = subplot.GridRect.Min;\n    // begin alignments\n    for (int r = 0; r < subplot.Rows; ++r)\n        subplot.RowAlignmentData[r].Begin();\n    for (int c = 0; c < subplot.Cols; ++c)\n        subplot.ColAlignmentData[c].Begin();\n    // clear legend data\n    subplot.Items.Legend.Reset();\n    // Setup first subplot\n    SubplotSetCell(0,0);\n    return true;\n}\n\nvoid EndSubplots() {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentSubplot != nullptr, \"Mismatched BeginSubplots()/EndSubplots()!\");\n    ImPlotSubplot& subplot = *gp.CurrentSubplot;\n    // set alignments\n    for (int r = 0; r < subplot.Rows; ++r)\n        subplot.RowAlignmentData[r].End();\n    for (int c = 0; c < subplot.Cols; ++c)\n        subplot.ColAlignmentData[c].End();\n    // pop styling\n    PopStyleColor();\n    PopStyleVar();\n    PopStyleVar();\n    ImGui::PopStyleVar();\n    // legend\n    subplot.Items.Legend.Hovered = false;\n    for (int i = 0; i < subplot.Items.GetItemCount(); ++i)\n        subplot.Items.GetItemByIndex(i)->LegendHovered = false;\n    // render legend\n    const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);\n    ImDrawList& DrawList = *ImGui::GetWindowDrawList();\n    if (share_items && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoLegend) && subplot.Items.GetLegendCount() > 0) {\n        const bool   legend_horz = ImHasFlag(subplot.Items.Legend.Flags, ImPlotLegendFlags_Horizontal);\n        const ImVec2 legend_size = CalcLegendSize(subplot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz);\n        const ImVec2 legend_pos  = GetLocationPos(subplot.FrameRect, legend_size, subplot.Items.Legend.Location, gp.Style.PlotPadding);\n        subplot.Items.Legend.Rect = ImRect(legend_pos, legend_pos + legend_size);\n        subplot.Items.Legend.Hovered = subplot.FrameHovered && subplot.Items.Legend.Rect.Contains(ImGui::GetIO().MousePos);\n        ImGui::PushClipRect(subplot.FrameRect.Min, subplot.FrameRect.Max, true);\n        ImU32  col_bg      = GetStyleColorU32(ImPlotCol_LegendBg);\n        ImU32  col_bd      = GetStyleColorU32(ImPlotCol_LegendBorder);\n        DrawList.AddRectFilled(subplot.Items.Legend.Rect.Min, subplot.Items.Legend.Rect.Max, col_bg);\n        DrawList.AddRect(subplot.Items.Legend.Rect.Min, subplot.Items.Legend.Rect.Max, col_bd);\n        bool legend_contextable = ShowLegendEntries(subplot.Items, subplot.Items.Legend.Rect, subplot.Items.Legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)\n                                && !ImHasFlag(subplot.Items.Legend.Flags, ImPlotLegendFlags_NoMenus);\n        if (legend_contextable && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoMenus) && ImGui::GetIO().MouseReleased[gp.InputMap.Menu])\n            ImGui::OpenPopup(\"##LegendContext\");\n        ImGui::PopClipRect();\n        if (ImGui::BeginPopup(\"##LegendContext\")) {\n            ImGui::Text(\"Legend\"); ImGui::Separator();\n            if (ShowLegendContextMenu(subplot.Items.Legend, !ImHasFlag(subplot.Flags, ImPlotFlags_NoLegend)))\n                ImFlipFlag(subplot.Flags, ImPlotFlags_NoLegend);\n            ImGui::EndPopup();\n        }\n    }\n    else {\n        subplot.Items.Legend.Rect = ImRect();\n    }\n    // remove items\n    if (gp.CurrentItems == &subplot.Items)\n        gp.CurrentItems = nullptr;\n    // reset the plot items for the next frame (TODO: put this elswhere)\n    for (int i = 0; i < subplot.Items.GetItemCount(); ++i) {\n        subplot.Items.GetItemByIndex(i)->SeenThisFrame = false;\n    }\n    // pop id\n    ImGui::PopID();\n    // set DC back correctly\n    GImGui->CurrentWindow->DC.CursorPos = subplot.FrameRect.Min;\n    ImGui::Dummy(subplot.FrameRect.GetSize());\n    ResetCtxForNextSubplot(GImPlot);\n\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot Utils\n//-----------------------------------------------------------------------------\n\nvoid SetAxis(ImAxis axis) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"SetAxis() needs to be called between BeginPlot() and EndPlot()!\");\n    IM_ASSERT_USER_ERROR(axis >= ImAxis_X1 && axis < ImAxis_COUNT, \"Axis index out of bounds!\");\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot->Axes[axis].Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    SetupLock();\n    if (axis < ImAxis_Y1)\n        gp.CurrentPlot->CurrentX = axis;\n    else\n        gp.CurrentPlot->CurrentY = axis;\n}\n\nvoid SetAxes(ImAxis x_idx, ImAxis y_idx) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"SetAxes() needs to be called between BeginPlot() and EndPlot()!\");\n    IM_ASSERT_USER_ERROR(x_idx >= ImAxis_X1 && x_idx < ImAxis_Y1, \"X-Axis index out of bounds!\");\n    IM_ASSERT_USER_ERROR(y_idx >= ImAxis_Y1 && y_idx < ImAxis_COUNT, \"Y-Axis index out of bounds!\");\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot->Axes[x_idx].Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot->Axes[y_idx].Enabled, \"Axis is not enabled! Did you forget to call SetupAxis()?\");\n    SetupLock();\n    gp.CurrentPlot->CurrentX = x_idx;\n    gp.CurrentPlot->CurrentY = y_idx;\n}\n\nImPlotPoint PixelsToPlot(float x, float y, ImAxis x_idx, ImAxis y_idx) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"PixelsToPlot() needs to be called between BeginPlot() and EndPlot()!\");\n    IM_ASSERT_USER_ERROR(x_idx == IMPLOT_AUTO || (x_idx >= ImAxis_X1 && x_idx < ImAxis_Y1),    \"X-Axis index out of bounds!\");\n    IM_ASSERT_USER_ERROR(y_idx == IMPLOT_AUTO || (y_idx >= ImAxis_Y1 && y_idx < ImAxis_COUNT), \"Y-Axis index out of bounds!\");\n    SetupLock();\n    ImPlotPlot& plot   = *gp.CurrentPlot;\n    ImPlotAxis& x_axis = x_idx == IMPLOT_AUTO ? plot.Axes[plot.CurrentX] : plot.Axes[x_idx];\n    ImPlotAxis& y_axis = y_idx == IMPLOT_AUTO ? plot.Axes[plot.CurrentY] : plot.Axes[y_idx];\n    return ImPlotPoint( x_axis.PixelsToPlot(x), y_axis.PixelsToPlot(y) );\n}\n\nImPlotPoint PixelsToPlot(const ImVec2& pix, ImAxis x_idx, ImAxis y_idx) {\n    return PixelsToPlot(pix.x, pix.y, x_idx, y_idx);\n}\n\nImVec2 PlotToPixels(double x, double y, ImAxis x_idx, ImAxis y_idx) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"PlotToPixels() needs to be called between BeginPlot() and EndPlot()!\");\n    IM_ASSERT_USER_ERROR(x_idx == IMPLOT_AUTO || (x_idx >= ImAxis_X1 && x_idx < ImAxis_Y1),    \"X-Axis index out of bounds!\");\n    IM_ASSERT_USER_ERROR(y_idx == IMPLOT_AUTO || (y_idx >= ImAxis_Y1 && y_idx < ImAxis_COUNT), \"Y-Axis index out of bounds!\");\n    SetupLock();\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& x_axis = x_idx == IMPLOT_AUTO ? plot.Axes[plot.CurrentX] : plot.Axes[x_idx];\n    ImPlotAxis& y_axis = y_idx == IMPLOT_AUTO ? plot.Axes[plot.CurrentY] : plot.Axes[y_idx];\n    return ImVec2( x_axis.PlotToPixels(x), y_axis.PlotToPixels(y) );\n}\n\nImVec2 PlotToPixels(const ImPlotPoint& plt, ImAxis x_idx, ImAxis y_idx) {\n    return PlotToPixels(plt.x, plt.y, x_idx, y_idx);\n}\n\nImVec2 GetPlotPos() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"GetPlotPos() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    return gp.CurrentPlot->PlotRect.Min;\n}\n\nImVec2 GetPlotSize() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"GetPlotSize() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    return gp.CurrentPlot->PlotRect.GetSize();\n}\n\nImPlotPoint GetPlotMousePos(ImAxis x_idx, ImAxis y_idx) {\n    IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, \"GetPlotMousePos() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    return PixelsToPlot(ImGui::GetMousePos(), x_idx, y_idx);\n}\n\nImPlotRect GetPlotLimits(ImAxis x_idx, ImAxis y_idx) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"GetPlotLimits() needs to be called between BeginPlot() and EndPlot()!\");\n    IM_ASSERT_USER_ERROR(x_idx == IMPLOT_AUTO || (x_idx >= ImAxis_X1 && x_idx < ImAxis_Y1),    \"X-Axis index out of bounds!\");\n    IM_ASSERT_USER_ERROR(y_idx == IMPLOT_AUTO || (y_idx >= ImAxis_Y1 && y_idx < ImAxis_COUNT), \"Y-Axis index out of bounds!\");\n    SetupLock();\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    ImPlotAxis& x_axis = x_idx == IMPLOT_AUTO ? plot.Axes[plot.CurrentX] : plot.Axes[x_idx];\n    ImPlotAxis& y_axis = y_idx == IMPLOT_AUTO ? plot.Axes[plot.CurrentY] : plot.Axes[y_idx];\n    ImPlotRect limits;\n    limits.X = x_axis.Range;\n    limits.Y = y_axis.Range;\n    return limits;\n}\n\nbool IsPlotHovered() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"IsPlotHovered() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    return gp.CurrentPlot->Hovered;\n}\n\nbool IsAxisHovered(ImAxis axis) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"IsPlotXAxisHovered() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    return gp.CurrentPlot->Axes[axis].Hovered;\n}\n\nbool IsSubplotsHovered() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentSubplot != nullptr, \"IsSubplotsHovered() needs to be called between BeginSubplots() and EndSubplots()!\");\n    return gp.CurrentSubplot->FrameHovered;\n}\n\nbool IsPlotSelected() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"IsPlotSelected() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    return gp.CurrentPlot->Selected;\n}\n\nImPlotRect GetPlotSelection(ImAxis x_idx, ImAxis y_idx) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"GetPlotSelection() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    if (!plot.Selected)\n        return ImPlotRect(0,0,0,0);\n    ImPlotPoint p1 = PixelsToPlot(plot.SelectRect.Min + plot.PlotRect.Min, x_idx, y_idx);\n    ImPlotPoint p2 = PixelsToPlot(plot.SelectRect.Max + plot.PlotRect.Min, x_idx, y_idx);\n    ImPlotRect result;\n    result.X.Min = ImMin(p1.x, p2.x);\n    result.X.Max = ImMax(p1.x, p2.x);\n    result.Y.Min = ImMin(p1.y, p2.y);\n    result.Y.Max = ImMax(p1.y, p2.y);\n    return result;\n}\n\nvoid CancelPlotSelection() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"CancelPlotSelection() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    ImPlotPlot& plot = *gp.CurrentPlot;\n    if (plot.Selected)\n        plot.Selected = plot.Selecting = false;\n}\n\nvoid HideNextItem(bool hidden, ImPlotCond cond) {\n    ImPlotContext& gp = *GImPlot;\n    gp.NextItemData.HasHidden  = true;\n    gp.NextItemData.Hidden     = hidden;\n    gp.NextItemData.HiddenCond = cond;\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot Tools\n//-----------------------------------------------------------------------------\n\nvoid Annotation(double x, double y, const ImVec4& col, const ImVec2& offset, bool clamp, bool round) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"Annotation() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    char x_buff[IMPLOT_LABEL_MAX_SIZE];\n    char y_buff[IMPLOT_LABEL_MAX_SIZE];\n    ImPlotAxis& x_axis = gp.CurrentPlot->Axes[gp.CurrentPlot->CurrentX];\n    ImPlotAxis& y_axis = gp.CurrentPlot->Axes[gp.CurrentPlot->CurrentY];\n    LabelAxisValue(x_axis, x, x_buff, sizeof(x_buff), round);\n    LabelAxisValue(y_axis, y, y_buff, sizeof(y_buff), round);\n    Annotation(x,y,col,offset,clamp,\"%s, %s\",x_buff,y_buff);\n}\n\nvoid AnnotationV(double x, double y, const ImVec4& col, const ImVec2& offset, bool clamp, const char* fmt, va_list args) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"Annotation() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    ImVec2 pos = PlotToPixels(x,y,IMPLOT_AUTO,IMPLOT_AUTO);\n    ImU32  bg  = ImGui::GetColorU32(col);\n    ImU32  fg  = col.w == 0 ? GetStyleColorU32(ImPlotCol_InlayText) : CalcTextColor(col);\n    gp.Annotations.AppendV(pos, offset, bg, fg, clamp, fmt, args);\n}\n\nvoid Annotation(double x, double y, const ImVec4& col, const ImVec2& offset, bool clamp, const char* fmt, ...) {\n    va_list args;\n    va_start(args, fmt);\n    AnnotationV(x,y,col,offset,clamp,fmt,args);\n    va_end(args);\n}\n\nvoid TagV(ImAxis axis, double v, const ImVec4& col, const char* fmt, va_list args) {\n    ImPlotContext& gp = *GImPlot;\n    SetupLock();\n    ImU32 bg = ImGui::GetColorU32(col);\n    ImU32 fg = col.w == 0 ? GetStyleColorU32(ImPlotCol_AxisText) : CalcTextColor(col);\n    gp.Tags.AppendV(axis,v,bg,fg,fmt,args);\n}\n\nvoid Tag(ImAxis axis, double v, const ImVec4& col, const char* fmt, ...) {\n    va_list args;\n    va_start(args, fmt);\n    TagV(axis,v,col,fmt,args);\n    va_end(args);\n}\n\nvoid Tag(ImAxis axis, double v, const ImVec4& color, bool round) {\n    ImPlotContext& gp = *GImPlot;\n    SetupLock();\n    char buff[IMPLOT_LABEL_MAX_SIZE];\n    ImPlotAxis& ax = gp.CurrentPlot->Axes[axis];\n    LabelAxisValue(ax, v, buff, sizeof(buff), round);\n    Tag(axis,v,color,\"%s\",buff);\n}\n\nIMPLOT_API void TagX(double x, const ImVec4& color, bool round) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"TagX() needs to be called between BeginPlot() and EndPlot()!\");\n    Tag(gp.CurrentPlot->CurrentX, x, color, round);\n}\n\nIMPLOT_API void TagX(double x, const ImVec4& color, const char* fmt, ...) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"TagX() needs to be called between BeginPlot() and EndPlot()!\");\n    va_list args;\n    va_start(args, fmt);\n    TagV(gp.CurrentPlot->CurrentX,x,color,fmt,args);\n    va_end(args);\n}\n\nIMPLOT_API void TagXV(double x, const ImVec4& color, const char* fmt, va_list args) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"TagX() needs to be called between BeginPlot() and EndPlot()!\");\n    TagV(gp.CurrentPlot->CurrentX, x, color, fmt, args);\n}\n\nIMPLOT_API void TagY(double y, const ImVec4& color, bool round) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"TagY() needs to be called between BeginPlot() and EndPlot()!\");\n    Tag(gp.CurrentPlot->CurrentY, y, color, round);\n}\n\nIMPLOT_API void TagY(double y, const ImVec4& color, const char* fmt, ...) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"TagY() needs to be called between BeginPlot() and EndPlot()!\");\n    va_list args;\n    va_start(args, fmt);\n    TagV(gp.CurrentPlot->CurrentY,y,color,fmt,args);\n    va_end(args);\n}\n\nIMPLOT_API void TagYV(double y, const ImVec4& color, const char* fmt, va_list args) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"TagY() needs to be called between BeginPlot() and EndPlot()!\");\n    TagV(gp.CurrentPlot->CurrentY, y, color, fmt, args);\n}\n\nstatic const float DRAG_GRAB_HALF_SIZE = 4.0f;\n\nbool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius, ImPlotDragToolFlags flags) {\n    ImGui::PushID(\"#IMPLOT_DRAG_POINT\");\n    IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, \"DragPoint() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n\n    if (!ImHasFlag(flags,ImPlotDragToolFlags_NoFit) && FitThisFrame()) {\n        FitPoint(ImPlotPoint(*x,*y));\n    }\n\n    const bool input = !ImHasFlag(flags, ImPlotDragToolFlags_NoInputs);\n    const bool show_curs = !ImHasFlag(flags, ImPlotDragToolFlags_NoCursors);\n    const bool no_delay = !ImHasFlag(flags, ImPlotDragToolFlags_Delayed);\n    const float grab_half_size = ImMax(DRAG_GRAB_HALF_SIZE, radius);\n    const ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;\n    const ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);\n\n    ImVec2 pos = PlotToPixels(*x,*y,IMPLOT_AUTO,IMPLOT_AUTO);\n    const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id);\n    ImRect rect(pos.x-grab_half_size,pos.y-grab_half_size,pos.x+grab_half_size,pos.y+grab_half_size);\n    bool hovered = false, held = false;\n\n    ImGui::KeepAliveID(id);\n    if (input)\n        ImGui::ButtonBehavior(rect,id,&hovered,&held);\n\n    bool dragging = false;\n    if (held && ImGui::IsMouseDragging(0)) {\n        *x = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;\n        *y = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;\n        dragging = true;\n    }\n\n    PushPlotClipRect();\n    ImDrawList& DrawList = *GetPlotDrawList();\n    if ((hovered || held) && show_curs)\n        ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);\n    if (dragging && no_delay)\n        pos = PlotToPixels(*x,*y,IMPLOT_AUTO,IMPLOT_AUTO);\n    DrawList.AddCircleFilled(pos, radius, col32);\n    PopPlotClipRect();\n\n    ImGui::PopID();\n    return dragging;\n}\n\nbool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags) {\n    // ImGui::PushID(\"#IMPLOT_DRAG_LINE_X\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"DragLineX() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n\n    if (!ImHasFlag(flags,ImPlotDragToolFlags_NoFit) && FitThisFrame()) {\n        FitPointX(*value);\n    }\n\n    const bool input = !ImHasFlag(flags, ImPlotDragToolFlags_NoInputs);\n    const bool show_curs = !ImHasFlag(flags, ImPlotDragToolFlags_NoCursors);\n    const bool no_delay = !ImHasFlag(flags, ImPlotDragToolFlags_Delayed);\n    const float grab_half_size = ImMax(DRAG_GRAB_HALF_SIZE, thickness/2);\n    float yt = gp.CurrentPlot->PlotRect.Min.y;\n    float yb = gp.CurrentPlot->PlotRect.Max.y;\n    float x  = IM_ROUND(PlotToPixels(*value,0,IMPLOT_AUTO,IMPLOT_AUTO).x);\n    const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id);\n    ImRect rect(x-grab_half_size,yt,x+grab_half_size,yb);\n    bool hovered = false, held = false;\n\n    ImGui::KeepAliveID(id);\n    if (input)\n        ImGui::ButtonBehavior(rect,id,&hovered,&held);\n\n    if ((hovered || held) && show_curs)\n        ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);\n\n    float len = gp.Style.MajorTickLen.x;\n    ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;\n    ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);\n\n    bool dragging = false;\n    if (held && ImGui::IsMouseDragging(0)) {\n        *value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;\n        dragging = true;\n    }\n\n    PushPlotClipRect();\n    ImDrawList& DrawList = *GetPlotDrawList();\n    if (dragging && no_delay)\n        x  = IM_ROUND(PlotToPixels(*value,0,IMPLOT_AUTO,IMPLOT_AUTO).x);\n    DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yb),     col32,   thickness);\n    DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yt+len), col32, 3*thickness);\n    DrawList.AddLine(ImVec2(x,yb), ImVec2(x,yb-len), col32, 3*thickness);\n    PopPlotClipRect();\n\n    // ImGui::PopID();\n    return dragging;\n}\n\nbool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags) {\n    ImGui::PushID(\"#IMPLOT_DRAG_LINE_Y\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"DragLineY() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n\n    if (!ImHasFlag(flags,ImPlotDragToolFlags_NoFit) && FitThisFrame()) {\n        FitPointY(*value);\n    }\n\n    const bool input = !ImHasFlag(flags, ImPlotDragToolFlags_NoInputs);\n    const bool show_curs = !ImHasFlag(flags, ImPlotDragToolFlags_NoCursors);\n    const bool no_delay = !ImHasFlag(flags, ImPlotDragToolFlags_Delayed);\n    const float grab_half_size = ImMax(DRAG_GRAB_HALF_SIZE, thickness/2);\n    float xl = gp.CurrentPlot->PlotRect.Min.x;\n    float xr = gp.CurrentPlot->PlotRect.Max.x;\n    float y  = IM_ROUND(PlotToPixels(0, *value,IMPLOT_AUTO,IMPLOT_AUTO).y);\n\n    const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id);\n    ImRect rect(xl,y-grab_half_size,xr,y+grab_half_size);\n    bool hovered = false, held = false;\n\n    ImGui::KeepAliveID(id);\n    if (input)\n        ImGui::ButtonBehavior(rect,id,&hovered,&held);\n\n    if ((hovered || held) && show_curs)\n        ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);\n\n    float len = gp.Style.MajorTickLen.y;\n    ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;\n    ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);\n\n    bool dragging = false;\n    if (held && ImGui::IsMouseDragging(0)) {\n        *value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;\n        dragging = true;\n    }\n\n    PushPlotClipRect();\n    ImDrawList& DrawList = *GetPlotDrawList();\n    if (dragging && no_delay)\n        y  = IM_ROUND(PlotToPixels(0, *value,IMPLOT_AUTO,IMPLOT_AUTO).y);\n    DrawList.AddLine(ImVec2(xl,y), ImVec2(xr,y),     col32,   thickness);\n    DrawList.AddLine(ImVec2(xl,y), ImVec2(xl+len,y), col32, 3*thickness);\n    DrawList.AddLine(ImVec2(xr,y), ImVec2(xr-len,y), col32, 3*thickness);\n    PopPlotClipRect();\n\n    ImGui::PopID();\n    return dragging;\n}\n\nbool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_max, const ImVec4& col, ImPlotDragToolFlags flags) {\n    ImGui::PushID(\"#IMPLOT_DRAG_RECT\");\n    IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, \"DragRect() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n\n    if (!ImHasFlag(flags,ImPlotDragToolFlags_NoFit) && FitThisFrame()) {\n        FitPoint(ImPlotPoint(*x_min,*y_min));\n        FitPoint(ImPlotPoint(*x_max,*y_max));\n    }\n\n    const bool input = !ImHasFlag(flags, ImPlotDragToolFlags_NoInputs);\n    const bool show_curs = !ImHasFlag(flags, ImPlotDragToolFlags_NoCursors);\n    const bool no_delay = !ImHasFlag(flags, ImPlotDragToolFlags_Delayed);\n    bool    h[] = {true,false,true,false};\n    double* x[] = {x_min,x_max,x_max,x_min};\n    double* y[] = {y_min,y_min,y_max,y_max};\n    ImVec2 p[4];\n    for (int i = 0; i < 4; ++i)\n        p[i] = PlotToPixels(*x[i],*y[i],IMPLOT_AUTO,IMPLOT_AUTO);\n    ImVec2 pc = PlotToPixels((*x_min+*x_max)/2,(*y_min+*y_max)/2,IMPLOT_AUTO,IMPLOT_AUTO);\n    ImRect rect(ImMin(p[0],p[2]),ImMax(p[0],p[2]));\n    ImRect rect_grab = rect; rect_grab.Expand(DRAG_GRAB_HALF_SIZE);\n\n    ImGuiMouseCursor cur[4];\n    if (show_curs) {\n        cur[0] = (rect.Min.x == p[0].x && rect.Min.y == p[0].y) || (rect.Max.x == p[0].x && rect.Max.y == p[0].y) ? ImGuiMouseCursor_ResizeNWSE : ImGuiMouseCursor_ResizeNESW;\n        cur[1] = cur[0] == ImGuiMouseCursor_ResizeNWSE ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;\n        cur[2] = cur[1] == ImGuiMouseCursor_ResizeNWSE ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;\n        cur[3] = cur[2] == ImGuiMouseCursor_ResizeNWSE ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;\n    }\n\n    ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;\n    ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);\n    color.w *= 0.25f;\n    ImU32 col32_a = ImGui::ColorConvertFloat4ToU32(color);\n    const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id);\n\n    bool dragging = false;\n    bool hovered = false, held = false;\n    ImRect b_rect(pc.x-DRAG_GRAB_HALF_SIZE,pc.y-DRAG_GRAB_HALF_SIZE,pc.x+DRAG_GRAB_HALF_SIZE,pc.y+DRAG_GRAB_HALF_SIZE);\n\n    ImGui::KeepAliveID(id);\n    if (input)\n        ImGui::ButtonBehavior(b_rect,id,&hovered,&held);\n\n    if ((hovered || held) && show_curs)\n        ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);\n    if (held && ImGui::IsMouseDragging(0)) {\n        for (int i = 0; i < 4; ++i) {\n            ImPlotPoint pp = PixelsToPlot(p[i] + ImGui::GetIO().MouseDelta,IMPLOT_AUTO,IMPLOT_AUTO);\n            *y[i] = pp.y;\n            *x[i] = pp.x;\n        }\n        dragging = true;\n    }\n\n    for (int i = 0; i < 4; ++i) {\n        // points\n        b_rect = ImRect(p[i].x-DRAG_GRAB_HALF_SIZE,p[i].y-DRAG_GRAB_HALF_SIZE,p[i].x+DRAG_GRAB_HALF_SIZE,p[i].y+DRAG_GRAB_HALF_SIZE);\n        ImGuiID p_id = id + i + 1;\n        ImGui::KeepAliveID(p_id);\n        if (input)\n            ImGui::ButtonBehavior(b_rect,p_id,&hovered,&held);\n        if ((hovered || held) && show_curs)\n            ImGui::SetMouseCursor(cur[i]);\n\n        if (held && ImGui::IsMouseDragging(0)) {\n            *x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;\n            *y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;\n            dragging = true;\n        }\n\n        // edges\n        ImVec2 e_min = ImMin(p[i],p[(i+1)%4]);\n        ImVec2 e_max = ImMax(p[i],p[(i+1)%4]);\n        b_rect = h[i] ? ImRect(e_min.x + DRAG_GRAB_HALF_SIZE, e_min.y - DRAG_GRAB_HALF_SIZE, e_max.x - DRAG_GRAB_HALF_SIZE, e_max.y + DRAG_GRAB_HALF_SIZE)\n                    : ImRect(e_min.x - DRAG_GRAB_HALF_SIZE, e_min.y + DRAG_GRAB_HALF_SIZE, e_max.x + DRAG_GRAB_HALF_SIZE, e_max.y - DRAG_GRAB_HALF_SIZE);\n        ImGuiID e_id = id + i + 5;\n        ImGui::KeepAliveID(e_id);\n        if (input)\n            ImGui::ButtonBehavior(b_rect,e_id,&hovered,&held);\n        if ((hovered || held) && show_curs)\n            h[i] ? ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS) : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);\n        if (held && ImGui::IsMouseDragging(0)) {\n            if (h[i])\n                *y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;\n            else\n                *x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;\n            dragging = true;\n        }\n        if (hovered && ImGui::IsMouseDoubleClicked(0))\n        {\n            ImPlotRect b = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO);\n            if (h[i])\n                *y[i] = ((y[i] == y_min && *y_min < *y_max) || (y[i] == y_max && *y_max < *y_min)) ? b.Y.Min : b.Y.Max;\n            else\n                *x[i] = ((x[i] == x_min && *x_min < *x_max) || (x[i] == x_max && *x_max < *x_min)) ? b.X.Min : b.X.Max;\n            dragging = true;\n        }\n    }\n\n\n    PushPlotClipRect();\n    ImDrawList& DrawList = *GetPlotDrawList();\n    if (dragging && no_delay) {\n        for (int i = 0; i < 4; ++i)\n            p[i] = PlotToPixels(*x[i],*y[i],IMPLOT_AUTO,IMPLOT_AUTO);\n        pc = PlotToPixels((*x_min+*x_max)/2,(*y_min+*y_max)/2,IMPLOT_AUTO,IMPLOT_AUTO);\n        rect = ImRect(ImMin(p[0],p[2]),ImMax(p[0],p[2]));\n    }\n    DrawList.AddRectFilled(rect.Min, rect.Max, col32_a);\n    DrawList.AddRect(rect.Min, rect.Max, col32);\n    if (input && (dragging || rect_grab.Contains(ImGui::GetMousePos()))) {\n        DrawList.AddCircleFilled(pc,DRAG_GRAB_HALF_SIZE,col32);\n        for (int i = 0; i < 4; ++i)\n            DrawList.AddCircleFilled(p[i],DRAG_GRAB_HALF_SIZE,col32);\n    }\n    PopPlotClipRect();\n    ImGui::PopID();\n    return dragging;\n}\n\nbool DragRect(int id, ImPlotRect* bounds, const ImVec4& col, ImPlotDragToolFlags flags) {\n    return DragRect(id, &bounds->X.Min, &bounds->Y.Min,&bounds->X.Max, &bounds->Y.Max, col, flags);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Legend Utils and Tools\n//-----------------------------------------------------------------------------\n\nbool IsLegendEntryHovered(const char* label_id) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr, \"IsPlotItemHighlight() needs to be called within an itemized context!\");\n    SetupLock();\n    ImGuiID id = ImGui::GetIDWithSeed(label_id, nullptr, gp.CurrentItems->ID);\n    ImPlotItem* item = gp.CurrentItems->GetItem(id);\n    return item && item->LegendHovered;\n}\n\nbool BeginLegendPopup(const char* label_id, ImGuiMouseButton mouse_button) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr, \"BeginLegendPopup() needs to be called within an itemized context!\");\n    SetupLock();\n    ImGuiWindow* window = GImGui->CurrentWindow;\n    if (window->SkipItems)\n        return false;\n    ImGuiID id = ImGui::GetIDWithSeed(label_id, nullptr, gp.CurrentItems->ID);\n    if (ImGui::IsMouseReleased(mouse_button)) {\n        ImPlotItem* item = gp.CurrentItems->GetItem(id);\n        if (item && item->LegendHovered)\n            ImGui::OpenPopupEx(id);\n    }\n    return ImGui::BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);\n}\n\nvoid EndLegendPopup() {\n    SetupLock();\n    ImGui::EndPopup();\n}\n\nvoid ShowAltLegend(const char* title_id, bool vertical, const ImVec2 size, bool interactable) {\n    ImPlotContext& gp    = *GImPlot;\n    ImGuiContext &G      = *GImGui;\n    ImGuiWindow * Window = G.CurrentWindow;\n    if (Window->SkipItems)\n        return;\n    ImDrawList &DrawList = *Window->DrawList;\n    ImPlotPlot* plot = GetPlot(title_id);\n    ImVec2 legend_size;\n    ImVec2 default_size = gp.Style.LegendPadding * 2;\n    if (plot != nullptr) {\n        legend_size  = CalcLegendSize(plot->Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, vertical);\n        default_size = legend_size + gp.Style.LegendPadding * 2;\n    }\n    ImVec2 frame_size = ImGui::CalcItemSize(size, default_size.x, default_size.y);\n    ImRect bb_frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);\n    ImGui::ItemSize(bb_frame);\n    if (!ImGui::ItemAdd(bb_frame, 0, &bb_frame))\n        return;\n    ImGui::RenderFrame(bb_frame.Min, bb_frame.Max, GetStyleColorU32(ImPlotCol_FrameBg), true, G.Style.FrameRounding);\n    DrawList.PushClipRect(bb_frame.Min, bb_frame.Max, true);\n    if (plot != nullptr) {\n        const ImVec2 legend_pos  = GetLocationPos(bb_frame, legend_size, 0, gp.Style.LegendPadding);\n        const ImRect legend_bb(legend_pos, legend_pos + legend_size);\n        interactable = interactable && bb_frame.Contains(ImGui::GetIO().MousePos);\n        // render legend box\n        ImU32  col_bg      = GetStyleColorU32(ImPlotCol_LegendBg);\n        ImU32  col_bd      = GetStyleColorU32(ImPlotCol_LegendBorder);\n        DrawList.AddRectFilled(legend_bb.Min, legend_bb.Max, col_bg);\n        DrawList.AddRect(legend_bb.Min, legend_bb.Max, col_bd);\n        // render entries\n        ShowLegendEntries(plot->Items, legend_bb, interactable, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, vertical, DrawList);\n    }\n    DrawList.PopClipRect();\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Drag and Drop Utils\n//-----------------------------------------------------------------------------\n\nbool BeginDragDropTargetPlot() {\n    SetupLock();\n    ImPlotContext& gp = *GImPlot;\n    ImRect rect = gp.CurrentPlot->PlotRect;\n    return ImGui::BeginDragDropTargetCustom(rect, gp.CurrentPlot->ID);\n}\n\nbool BeginDragDropTargetAxis(ImAxis axis) {\n    SetupLock();\n    ImPlotPlot& plot = *GImPlot->CurrentPlot;\n    ImPlotAxis& ax = plot.Axes[axis];\n    ImRect rect = ax.HoverRect;\n    rect.Expand(-3.5f);\n    return ImGui::BeginDragDropTargetCustom(rect, ax.ID);\n}\n\nbool BeginDragDropTargetLegend() {\n    SetupLock();\n    ImPlotItemGroup& items = *GImPlot->CurrentItems;\n    ImRect rect = items.Legend.Rect;\n    return ImGui::BeginDragDropTargetCustom(rect, items.ID);\n}\n\nvoid EndDragDropTarget() {\n    SetupLock();\n\tImGui::EndDragDropTarget();\n}\n\nbool BeginDragDropSourcePlot(ImGuiDragDropFlags flags) {\n    SetupLock();\n    ImPlotContext& gp = *GImPlot;\n    ImPlotPlot* plot = gp.CurrentPlot;\n    if (GImGui->IO.KeyMods == gp.InputMap.OverrideMod || GImGui->DragDropPayload.SourceId == plot->ID)\n        return ImGui::ItemAdd(plot->PlotRect, plot->ID) && ImGui::BeginDragDropSource(flags);\n    return false;\n}\n\nbool BeginDragDropSourceAxis(ImAxis idx, ImGuiDragDropFlags flags) {\n    SetupLock();\n    ImPlotContext& gp = *GImPlot;\n    ImPlotAxis& axis = gp.CurrentPlot->Axes[idx];\n    if (GImGui->IO.KeyMods == gp.InputMap.OverrideMod || GImGui->DragDropPayload.SourceId == axis.ID)\n        return ImGui::ItemAdd(axis.HoverRect, axis.ID) && ImGui::BeginDragDropSource(flags);\n    return false;\n}\n\nbool BeginDragDropSourceItem(const char* label_id, ImGuiDragDropFlags flags) {\n    SetupLock();\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr, \"BeginDragDropSourceItem() needs to be called within an itemized context!\");\n    ImGuiID item_id = ImGui::GetIDWithSeed(label_id, nullptr, gp.CurrentItems->ID);\n    ImPlotItem* item = gp.CurrentItems->GetItem(item_id);\n    if (item != nullptr) {\n        return ImGui::ItemAdd(item->LegendHoverRect, item->ID) && ImGui::BeginDragDropSource(flags);\n    }\n    return false;\n}\n\nvoid EndDragDropSource() {\n    SetupLock();\n    ImGui::EndDragDropSource();\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Aligned Plots\n//-----------------------------------------------------------------------------\n\nbool BeginAlignedPlots(const char* group_id, bool vertical) {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentAlignmentH == nullptr && gp.CurrentAlignmentV == nullptr, \"Mismatched BeginAlignedPlots()/EndAlignedPlots()!\");\n    ImGuiContext &G = *GImGui;\n    ImGuiWindow * Window = G.CurrentWindow;\n    if (Window->SkipItems)\n        return false;\n    const ImGuiID ID = Window->GetID(group_id);\n    ImPlotAlignmentData* alignment = gp.AlignmentData.GetOrAddByKey(ID);\n    if (vertical)\n        gp.CurrentAlignmentV = alignment;\n    else\n        gp.CurrentAlignmentH = alignment;\n    if (alignment->Vertical != vertical)\n        alignment->Reset();\n    alignment->Vertical = vertical;\n    alignment->Begin();\n    return true;\n}\n\nvoid EndAlignedPlots() {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentAlignmentH != nullptr || gp.CurrentAlignmentV != nullptr, \"Mismatched BeginAlignedPlots()/EndAlignedPlots()!\");\n    ImPlotAlignmentData* alignment = gp.CurrentAlignmentH != nullptr ? gp.CurrentAlignmentH : (gp.CurrentAlignmentV != nullptr ? gp.CurrentAlignmentV : nullptr);\n    if (alignment)\n        alignment->End();\n    ResetCtxForNextAlignedPlots(GImPlot);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot and Item Styling\n//-----------------------------------------------------------------------------\n\nImPlotStyle& GetStyle() {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    return gp.Style;\n}\n\nvoid PushStyleColor(ImPlotCol idx, ImU32 col) {\n    ImPlotContext& gp = *GImPlot;\n    ImGuiColorMod backup;\n    backup.Col = (ImGuiCol)idx;\n    backup.BackupValue = gp.Style.Colors[idx];\n    gp.ColorModifiers.push_back(backup);\n    gp.Style.Colors[idx] = ImGui::ColorConvertU32ToFloat4(col);\n}\n\nvoid PushStyleColor(ImPlotCol idx, const ImVec4& col) {\n    ImPlotContext& gp = *GImPlot;\n    ImGuiColorMod backup;\n    backup.Col = (ImGuiCol)idx;\n    backup.BackupValue = gp.Style.Colors[idx];\n    gp.ColorModifiers.push_back(backup);\n    gp.Style.Colors[idx] = col;\n}\n\nvoid PopStyleColor(int count) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(count <= gp.ColorModifiers.Size, \"You can't pop more modifiers than have been pushed!\");\n    while (count > 0)\n    {\n        ImGuiColorMod& backup = gp.ColorModifiers.back();\n        gp.Style.Colors[backup.Col] = backup.BackupValue;\n        gp.ColorModifiers.pop_back();\n        count--;\n    }\n}\n\nvoid PushStyleVar(ImPlotStyleVar idx, float val) {\n    ImPlotContext& gp = *GImPlot;\n    const ImPlotStyleVarInfo* var_info = GetPlotStyleVarInfo(idx);\n    if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) {\n        float* pvar = (float*)var_info->GetVarPtr(&gp.Style);\n        gp.StyleModifiers.push_back(ImGuiStyleMod((ImGuiStyleVar)idx, *pvar));\n        *pvar = val;\n        return;\n    }\n    IM_ASSERT(0 && \"Called PushStyleVar() float variant but variable is not a float!\");\n}\n\nvoid PushStyleVar(ImPlotStyleVar idx, int val) {\n    ImPlotContext& gp = *GImPlot;\n    const ImPlotStyleVarInfo* var_info = GetPlotStyleVarInfo(idx);\n    if (var_info->Type == ImGuiDataType_S32 && var_info->Count == 1) {\n        int* pvar = (int*)var_info->GetVarPtr(&gp.Style);\n        gp.StyleModifiers.push_back(ImGuiStyleMod((ImGuiStyleVar)idx, *pvar));\n        *pvar = val;\n        return;\n    }\n    else if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) {\n        float* pvar = (float*)var_info->GetVarPtr(&gp.Style);\n        gp.StyleModifiers.push_back(ImGuiStyleMod((ImGuiStyleVar)idx, *pvar));\n        *pvar = (float)val;\n        return;\n    }\n    IM_ASSERT(0 && \"Called PushStyleVar() int variant but variable is not a int!\");\n}\n\nvoid PushStyleVar(ImPlotStyleVar idx, const ImVec2& val)\n{\n    ImPlotContext& gp = *GImPlot;\n    const ImPlotStyleVarInfo* var_info = GetPlotStyleVarInfo(idx);\n    if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)\n    {\n        ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&gp.Style);\n        gp.StyleModifiers.push_back(ImGuiStyleMod((ImGuiStyleVar)idx, *pvar));\n        *pvar = val;\n        return;\n    }\n    IM_ASSERT(0 && \"Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!\");\n}\n\nvoid PopStyleVar(int count) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(count <= gp.StyleModifiers.Size, \"You can't pop more modifiers than have been pushed!\");\n    while (count > 0) {\n        ImGuiStyleMod& backup = gp.StyleModifiers.back();\n        const ImPlotStyleVarInfo* info = GetPlotStyleVarInfo(backup.VarIdx);\n        void* data = info->GetVarPtr(&gp.Style);\n        if (info->Type == ImGuiDataType_Float && info->Count == 1) {\n            ((float*)data)[0] = backup.BackupFloat[0];\n        }\n        else if (info->Type == ImGuiDataType_Float && info->Count == 2) {\n             ((float*)data)[0] = backup.BackupFloat[0];\n             ((float*)data)[1] = backup.BackupFloat[1];\n        }\n        else if (info->Type == ImGuiDataType_S32 && info->Count == 1) {\n            ((int*)data)[0] = backup.BackupInt[0];\n        }\n        gp.StyleModifiers.pop_back();\n        count--;\n    }\n}\n\n//------------------------------------------------------------------------------\n// [Section] Colormaps\n//------------------------------------------------------------------------------\n\nImPlotColormap AddColormap(const char* name, const ImVec4* colormap, int size, bool qual) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(size > 1, \"The colormap size must be greater than 1!\");\n    IM_ASSERT_USER_ERROR(gp.ColormapData.GetIndex(name) == -1, \"The colormap name has already been used!\");\n    ImVector<ImU32> buffer;\n    buffer.resize(size);\n    for (int i = 0; i < size; ++i)\n        buffer[i] = ImGui::ColorConvertFloat4ToU32(colormap[i]);\n    return gp.ColormapData.Append(name, buffer.Data, size, qual);\n}\n\nImPlotColormap AddColormap(const char* name, const ImU32*  colormap, int size, bool qual) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(size > 1, \"The colormap size must be greater than 1!\");\n    IM_ASSERT_USER_ERROR(gp.ColormapData.GetIndex(name) == -1, \"The colormap name has already be used!\");\n    return gp.ColormapData.Append(name, colormap, size, qual);\n}\n\nint GetColormapCount() {\n    ImPlotContext& gp = *GImPlot;\n    return gp.ColormapData.Count;\n}\n\nconst char* GetColormapName(ImPlotColormap colormap) {\n    ImPlotContext& gp = *GImPlot;\n    return gp.ColormapData.GetName(colormap);\n}\n\nImPlotColormap GetColormapIndex(const char* name) {\n    ImPlotContext& gp = *GImPlot;\n    return gp.ColormapData.GetIndex(name);\n}\n\nvoid PushColormap(ImPlotColormap colormap) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(colormap >= 0 && colormap < gp.ColormapData.Count, \"The colormap index is invalid!\");\n    gp.ColormapModifiers.push_back(gp.Style.Colormap);\n    gp.Style.Colormap = colormap;\n}\n\nvoid PushColormap(const char* name) {\n    ImPlotContext& gp = *GImPlot;\n    ImPlotColormap idx = gp.ColormapData.GetIndex(name);\n    IM_ASSERT_USER_ERROR(idx != -1, \"The colormap name is invalid!\");\n    PushColormap(idx);\n}\n\nvoid PopColormap(int count) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(count <= gp.ColormapModifiers.Size, \"You can't pop more modifiers than have been pushed!\");\n    while (count > 0) {\n        const ImPlotColormap& backup = gp.ColormapModifiers.back();\n        gp.Style.Colormap     = backup;\n        gp.ColormapModifiers.pop_back();\n        count--;\n    }\n}\n\nImU32 NextColormapColorU32() {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr, \"NextColormapColor() needs to be called between BeginPlot() and EndPlot()!\");\n    int idx = gp.CurrentItems->ColormapIdx % gp.ColormapData.GetKeyCount(gp.Style.Colormap);\n    ImU32 col  = gp.ColormapData.GetKeyColor(gp.Style.Colormap, idx);\n    gp.CurrentItems->ColormapIdx++;\n    return col;\n}\n\nImVec4 NextColormapColor() {\n    return ImGui::ColorConvertU32ToFloat4(NextColormapColorU32());\n}\n\nint GetColormapSize(ImPlotColormap cmap) {\n    ImPlotContext& gp = *GImPlot;\n    cmap = cmap == IMPLOT_AUTO ? gp.Style.Colormap : cmap;\n    IM_ASSERT_USER_ERROR(cmap >= 0 && cmap < gp.ColormapData.Count, \"Invalid colormap index!\");\n    return gp.ColormapData.GetKeyCount(cmap);\n}\n\nImU32 GetColormapColorU32(int idx, ImPlotColormap cmap) {\n    ImPlotContext& gp = *GImPlot;\n    cmap = cmap == IMPLOT_AUTO ? gp.Style.Colormap : cmap;\n    IM_ASSERT_USER_ERROR(cmap >= 0 && cmap < gp.ColormapData.Count, \"Invalid colormap index!\");\n    idx = idx % gp.ColormapData.GetKeyCount(cmap);\n    return gp.ColormapData.GetKeyColor(cmap, idx);\n}\n\nImVec4 GetColormapColor(int idx, ImPlotColormap cmap) {\n    return ImGui::ColorConvertU32ToFloat4(GetColormapColorU32(idx,cmap));\n}\n\nImU32  SampleColormapU32(float t, ImPlotColormap cmap) {\n    ImPlotContext& gp = *GImPlot;\n    cmap = cmap == IMPLOT_AUTO ? gp.Style.Colormap : cmap;\n    IM_ASSERT_USER_ERROR(cmap >= 0 && cmap < gp.ColormapData.Count, \"Invalid colormap index!\");\n    return gp.ColormapData.LerpTable(cmap, t);\n}\n\nImVec4 SampleColormap(float t, ImPlotColormap cmap) {\n    return ImGui::ColorConvertU32ToFloat4(SampleColormapU32(t,cmap));\n}\n\nvoid RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous) {\n    const int n = continuous ? size - 1 : size;\n    ImU32 col1, col2;\n    if (vert) {\n        const float step = bounds.GetHeight() / n;\n        ImRect rect(bounds.Min.x, bounds.Min.y, bounds.Max.x, bounds.Min.y + step);\n        for (int i = 0; i < n; ++i) {\n            if (reversed) {\n                col1 = colors[size-i-1];\n                col2 = continuous ? colors[size-i-2] : col1;\n            }\n            else {\n                col1 = colors[i];\n                col2 = continuous ? colors[i+1] : col1;\n            }\n            DrawList.AddRectFilledMultiColor(rect.Min, rect.Max, col1, col1, col2, col2);\n            rect.TranslateY(step);\n        }\n    }\n    else {\n        const float step = bounds.GetWidth() / n;\n        ImRect rect(bounds.Min.x, bounds.Min.y, bounds.Min.x + step, bounds.Max.y);\n        for (int i = 0; i < n; ++i) {\n            if (reversed) {\n                col1 = colors[size-i-1];\n                col2 = continuous ? colors[size-i-2] : col1;\n            }\n            else {\n                col1 = colors[i];\n                col2 = continuous ? colors[i+1] : col1;\n            }\n            DrawList.AddRectFilledMultiColor(rect.Min, rect.Max, col1, col2, col2, col1);\n            rect.TranslateX(step);\n        }\n    }\n}\n\nvoid ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size, const char* format, ImPlotColormapScaleFlags flags, ImPlotColormap cmap) {\n    ImGuiContext &G      = *GImGui;\n    ImGuiWindow * Window = G.CurrentWindow;\n    if (Window->SkipItems)\n        return;\n\n    const ImGuiID ID = Window->GetID(label);\n    ImVec2 label_size(0,0);\n    if (!ImHasFlag(flags, ImPlotColormapScaleFlags_NoLabel)) {\n        label_size = ImGui::CalcTextSize(label,nullptr,true);\n    }\n\n    ImPlotContext& gp = *GImPlot;\n    cmap = cmap == IMPLOT_AUTO ? gp.Style.Colormap : cmap;\n    IM_ASSERT_USER_ERROR(cmap >= 0 && cmap < gp.ColormapData.Count, \"Invalid colormap index!\");\n\n    ImVec2 frame_size  = ImGui::CalcItemSize(size, 0, gp.Style.PlotDefaultSize.y);\n    if (frame_size.y < gp.Style.PlotMinSize.y && size.y < 0.0f)\n        frame_size.y = gp.Style.PlotMinSize.y;\n\n    ImPlotRange range(ImMin(scale_min,scale_max), ImMax(scale_min,scale_max));\n    gp.CTicker.Reset();\n    Locator_Default(gp.CTicker, range, frame_size.y, true, Formatter_Default, (void*)format);\n\n    const bool rend_label = label_size.x > 0;\n    const float txt_off   = gp.Style.LabelPadding.x;\n    const float pad       = txt_off + gp.CTicker.MaxSize.x + (rend_label ? txt_off + label_size.y : 0);\n    float bar_w           = 20;\n    if (frame_size.x == 0)\n        frame_size.x = bar_w + pad + 2 * gp.Style.PlotPadding.x;\n    else {\n        bar_w = frame_size.x - (pad + 2 * gp.Style.PlotPadding.x);\n        if (bar_w < gp.Style.MajorTickLen.y)\n            bar_w = gp.Style.MajorTickLen.y;\n    }\n\n    ImDrawList &DrawList = *Window->DrawList;\n    ImRect bb_frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);\n    ImGui::ItemSize(bb_frame);\n    if (!ImGui::ItemAdd(bb_frame, ID, &bb_frame))\n        return;\n\n    ImGui::RenderFrame(bb_frame.Min, bb_frame.Max, GetStyleColorU32(ImPlotCol_FrameBg), true, G.Style.FrameRounding);\n\n    const bool opposite = ImHasFlag(flags, ImPlotColormapScaleFlags_Opposite);\n    const bool inverted = ImHasFlag(flags, ImPlotColormapScaleFlags_Invert);\n    const bool reversed = scale_min > scale_max;\n\n    float bb_grad_shift = opposite ? pad : 0;\n    ImRect bb_grad(bb_frame.Min + gp.Style.PlotPadding + ImVec2(bb_grad_shift, 0),\n                   bb_frame.Min + ImVec2(bar_w + gp.Style.PlotPadding.x + bb_grad_shift,\n                                         frame_size.y - gp.Style.PlotPadding.y));\n\n    ImGui::PushClipRect(bb_frame.Min, bb_frame.Max, true);\n    const ImU32 col_text = ImGui::GetColorU32(ImGuiCol_Text);\n\n    const bool invert_scale = inverted ? (reversed ? false : true) : (reversed ? true : false);\n    const float y_min = invert_scale ? bb_grad.Max.y : bb_grad.Min.y;\n    const float y_max = invert_scale ? bb_grad.Min.y : bb_grad.Max.y;\n\n    RenderColorBar(gp.ColormapData.GetKeys(cmap), gp.ColormapData.GetKeyCount(cmap), DrawList, bb_grad, true, !inverted, !gp.ColormapData.IsQual(cmap));\n    for (int i = 0; i < gp.CTicker.TickCount(); ++i) {\n        const double y_pos_plt = gp.CTicker.Ticks[i].PlotPos;\n        const float y_pos = ImRemap((float)y_pos_plt, (float)range.Max, (float)range.Min, y_min, y_max);\n        const float tick_width = gp.CTicker.Ticks[i].Major ? gp.Style.MajorTickLen.y : gp.Style.MinorTickLen.y;\n        const float tick_thick = gp.CTicker.Ticks[i].Major ? gp.Style.MajorTickSize.y : gp.Style.MinorTickSize.y;\n        const float tick_t     = (float)((y_pos_plt - scale_min) / (scale_max - scale_min));\n        const ImU32 tick_col = CalcTextColor(gp.ColormapData.LerpTable(cmap,tick_t));\n        if (y_pos < bb_grad.Max.y - 2 && y_pos > bb_grad.Min.y + 2) {\n            DrawList.AddLine(opposite ? ImVec2(bb_grad.Min.x+1, y_pos) : ImVec2(bb_grad.Max.x-1, y_pos),\n                             opposite ? ImVec2(bb_grad.Min.x + tick_width, y_pos) : ImVec2(bb_grad.Max.x - tick_width, y_pos),\n                             tick_col,\n                             tick_thick);\n        }\n        const float txt_x = opposite ? bb_grad.Min.x - txt_off - gp.CTicker.Ticks[i].LabelSize.x : bb_grad.Max.x + txt_off;\n        const float txt_y = y_pos - gp.CTicker.Ticks[i].LabelSize.y * 0.5f;\n        DrawList.AddText(ImVec2(txt_x, txt_y), col_text, gp.CTicker.GetText(i));\n    }\n\n    if (rend_label) {\n        const float pos_x = opposite ? bb_frame.Min.x + gp.Style.PlotPadding.x : bb_grad.Max.x + 2 * txt_off + gp.CTicker.MaxSize.x;\n        const float pos_y = bb_grad.GetCenter().y + label_size.x * 0.5f;\n        const char* label_end = ImGui::FindRenderedTextEnd(label);\n        AddTextVertical(&DrawList,ImVec2(pos_x,pos_y),col_text,label,label_end);\n    }\n    DrawList.AddRect(bb_grad.Min, bb_grad.Max, GetStyleColorU32(ImPlotCol_PlotBorder));\n    ImGui::PopClipRect();\n}\n\nbool ColormapSlider(const char* label, float* t, ImVec4* out, const char* format, ImPlotColormap cmap) {\n    *t = ImClamp(*t,0.0f,1.0f);\n    ImGuiContext &G      = *GImGui;\n    ImGuiWindow * Window = G.CurrentWindow;\n    if (Window->SkipItems)\n        return false;\n    ImPlotContext& gp = *GImPlot;\n    cmap = cmap == IMPLOT_AUTO ? gp.Style.Colormap : cmap;\n    IM_ASSERT_USER_ERROR(cmap >= 0 && cmap < gp.ColormapData.Count, \"Invalid colormap index!\");\n    const ImU32* keys  = gp.ColormapData.GetKeys(cmap);\n    const int    count = gp.ColormapData.GetKeyCount(cmap);\n    const bool   qual  = gp.ColormapData.IsQual(cmap);\n    const ImVec2 pos  = ImGui::GetCurrentWindow()->DC.CursorPos;\n    const float w     = ImGui::CalcItemWidth();\n    const float h     = ImGui::GetFrameHeight();\n    const ImRect rect = ImRect(pos.x,pos.y,pos.x+w,pos.y+h);\n    RenderColorBar(keys,count,*ImGui::GetWindowDrawList(),rect,false,false,!qual);\n    const ImU32 grab = CalcTextColor(gp.ColormapData.LerpTable(cmap,*t));\n    // const ImU32 text = CalcTextColor(gp.ColormapData.LerpTable(cmap,0.5f));\n    ImGui::PushStyleColor(ImGuiCol_FrameBg,IM_COL32_BLACK_TRANS);\n    ImGui::PushStyleColor(ImGuiCol_FrameBgActive,IM_COL32_BLACK_TRANS);\n    ImGui::PushStyleColor(ImGuiCol_FrameBgHovered,ImVec4(1,1,1,0.1f));\n    ImGui::PushStyleColor(ImGuiCol_SliderGrab,grab);\n    ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, grab);\n    ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize,2);\n    ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding,0);\n    const bool changed = ImGui::SliderFloat(label,t,0,1,format);\n    ImGui::PopStyleColor(5);\n    ImGui::PopStyleVar(2);\n    if (out != nullptr)\n        *out = ImGui::ColorConvertU32ToFloat4(gp.ColormapData.LerpTable(cmap,*t));\n    return changed;\n}\n\nbool ColormapButton(const char* label, const ImVec2& size_arg, ImPlotColormap cmap) {\n    ImGuiContext &G      = *GImGui;\n    const ImGuiStyle& style = G.Style;\n    ImGuiWindow * Window = G.CurrentWindow;\n    if (Window->SkipItems)\n        return false;\n    ImPlotContext& gp = *GImPlot;\n    cmap = cmap == IMPLOT_AUTO ? gp.Style.Colormap : cmap;\n    IM_ASSERT_USER_ERROR(cmap >= 0 && cmap < gp.ColormapData.Count, \"Invalid colormap index!\");\n    const ImU32* keys  = gp.ColormapData.GetKeys(cmap);\n    const int    count = gp.ColormapData.GetKeyCount(cmap);\n    const bool   qual  = gp.ColormapData.IsQual(cmap);\n    const ImVec2 pos  = ImGui::GetCurrentWindow()->DC.CursorPos;\n    const ImVec2 label_size = ImGui::CalcTextSize(label, nullptr, true);\n    ImVec2 size = ImGui::CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);\n    const ImRect rect = ImRect(pos.x,pos.y,pos.x+size.x,pos.y+size.y);\n    RenderColorBar(keys,count,*ImGui::GetWindowDrawList(),rect,false,false,!qual);\n    const ImU32 text = CalcTextColor(gp.ColormapData.LerpTable(cmap,G.Style.ButtonTextAlign.x));\n    ImGui::PushStyleColor(ImGuiCol_Button,IM_COL32_BLACK_TRANS);\n    ImGui::PushStyleColor(ImGuiCol_ButtonHovered,ImVec4(1,1,1,0.1f));\n    ImGui::PushStyleColor(ImGuiCol_ButtonActive,ImVec4(1,1,1,0.2f));\n    ImGui::PushStyleColor(ImGuiCol_Text,text);\n    ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding,0);\n    const bool pressed = ImGui::Button(label,size);\n    ImGui::PopStyleColor(4);\n    ImGui::PopStyleVar(1);\n    return pressed;\n}\n\n//-----------------------------------------------------------------------------\n// [Section] Miscellaneous\n//-----------------------------------------------------------------------------\n\nImPlotInputMap& GetInputMap() {\n    IM_ASSERT_USER_ERROR(GImPlot != nullptr, \"No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?\");\n    ImPlotContext& gp = *GImPlot;\n    return gp.InputMap;\n}\n\nvoid MapInputDefault(ImPlotInputMap* dst) {\n    ImPlotInputMap& map = dst ? *dst : GetInputMap();\n    map.Pan             = ImGuiMouseButton_Left;\n    map.PanMod          = ImGuiMod_None;\n    map.Fit             = ImGuiMouseButton_Left;\n    map.Menu            = ImGuiMouseButton_Right;\n    map.Select          = ImGuiMouseButton_Right;\n    map.SelectMod       = ImGuiMod_None;\n    map.SelectCancel    = ImGuiMouseButton_Left;\n    map.SelectHorzMod   = ImGuiMod_Alt;\n    map.SelectVertMod   = ImGuiMod_Shift;\n    map.OverrideMod     = ImGuiMod_Ctrl;\n    map.ZoomMod         = ImGuiMod_None;\n    map.ZoomRate        = 0.1f;\n}\n\nvoid MapInputReverse(ImPlotInputMap* dst) {\n    ImPlotInputMap& map = dst ? *dst : GetInputMap();\n    map.Pan             = ImGuiMouseButton_Right;\n    map.PanMod          = ImGuiMod_None;\n    map.Fit             = ImGuiMouseButton_Left;\n    map.Menu            = ImGuiMouseButton_Right;\n    map.Select          = ImGuiMouseButton_Left;\n    map.SelectMod       = ImGuiMod_None;\n    map.SelectCancel    = ImGuiMouseButton_Right;\n    map.SelectHorzMod   = ImGuiMod_Alt;\n    map.SelectVertMod   = ImGuiMod_Shift;\n    map.OverrideMod     = ImGuiMod_Ctrl;\n    map.ZoomMod         = ImGuiMod_None;\n    map.ZoomRate        = 0.1f;\n}\n\n//-----------------------------------------------------------------------------\n// [Section] Miscellaneous\n//-----------------------------------------------------------------------------\n\nvoid ItemIcon(const ImVec4& col) {\n    ItemIcon(ImGui::ColorConvertFloat4ToU32(col));\n}\n\nvoid ItemIcon(ImU32 col) {\n    const float txt_size = ImGui::GetTextLineHeight();\n    ImVec2 size(txt_size-4,txt_size);\n    ImGuiWindow* window = ImGui::GetCurrentWindow();\n    ImVec2 pos = window->DC.CursorPos;\n    ImGui::GetWindowDrawList()->AddRectFilled(pos + ImVec2(0,2), pos + size - ImVec2(0,2), col);\n    ImGui::Dummy(size);\n}\n\nvoid ColormapIcon(ImPlotColormap cmap) {\n    ImPlotContext& gp = *GImPlot;\n    const float txt_size = ImGui::GetTextLineHeight();\n    ImVec2 size(txt_size-4,txt_size);\n    ImGuiWindow* window = ImGui::GetCurrentWindow();\n    ImVec2 pos = window->DC.CursorPos;\n    ImRect rect(pos+ImVec2(0,2),pos+size-ImVec2(0,2));\n    ImDrawList& DrawList = *ImGui::GetWindowDrawList();\n    RenderColorBar(gp.ColormapData.GetKeys(cmap),gp.ColormapData.GetKeyCount(cmap),DrawList,rect,false,false,!gp.ColormapData.IsQual(cmap));\n    ImGui::Dummy(size);\n}\n\nImDrawList* GetPlotDrawList() {\n    return ImGui::GetWindowDrawList();\n}\n\nvoid PushPlotClipRect(float expand) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"PushPlotClipRect() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    ImRect rect = gp.CurrentPlot->PlotRect;\n    rect.Expand(expand);\n    ImGui::PushClipRect(rect.Min, rect.Max, true);\n}\n\nvoid PopPlotClipRect() {\n    SetupLock();\n    ImGui::PopClipRect();\n}\n\nstatic void HelpMarker(const char* desc) {\n    ImGui::TextDisabled(\"(?)\");\n    if (ImGui::IsItemHovered()) {\n        ImGui::BeginTooltip();\n        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);\n        ImGui::TextUnformatted(desc);\n        ImGui::PopTextWrapPos();\n        ImGui::EndTooltip();\n    }\n}\n\nbool ShowStyleSelector(const char* label)\n{\n    static int style_idx = -1;\n    if (ImGui::Combo(label, &style_idx, \"Auto\\0Classic\\0Dark\\0Light\\0\"))\n    {\n        switch (style_idx)\n        {\n        case 0: StyleColorsAuto(); break;\n        case 1: StyleColorsClassic(); break;\n        case 2: StyleColorsDark(); break;\n        case 3: StyleColorsLight(); break;\n        }\n        return true;\n    }\n    return false;\n}\n\nbool ShowColormapSelector(const char* label) {\n    ImPlotContext& gp = *GImPlot;\n    bool set = false;\n    if (ImGui::BeginCombo(label, gp.ColormapData.GetName(gp.Style.Colormap))) {\n        for (int i = 0; i < gp.ColormapData.Count; ++i) {\n            const char* name = gp.ColormapData.GetName(i);\n            if (ImGui::Selectable(name, gp.Style.Colormap == i)) {\n                gp.Style.Colormap = i;\n                ImPlot::BustItemCache();\n                set = true;\n            }\n        }\n        ImGui::EndCombo();\n    }\n    return set;\n}\n\nbool ShowInputMapSelector(const char* label) {\n    static int map_idx = -1;\n    if (ImGui::Combo(label, &map_idx, \"Default\\0Reversed\\0\"))\n    {\n        switch (map_idx)\n        {\n        case 0: MapInputDefault(); break;\n        case 1: MapInputReverse(); break;\n        }\n        return true;\n    }\n    return false;\n}\n\n\nvoid ShowStyleEditor(ImPlotStyle* ref) {\n    ImPlotContext& gp = *GImPlot;\n    ImPlotStyle& style = GetStyle();\n    static ImPlotStyle ref_saved_style;\n    // Default to using internal storage as reference\n    static bool init = true;\n    if (init && ref == nullptr)\n        ref_saved_style = style;\n    init = false;\n    if (ref == nullptr)\n        ref = &ref_saved_style;\n\n    if (ImPlot::ShowStyleSelector(\"Colors##Selector\"))\n        ref_saved_style = style;\n\n    // Save/Revert button\n    if (ImGui::Button(\"Save Ref\"))\n        *ref = ref_saved_style = style;\n    ImGui::SameLine();\n    if (ImGui::Button(\"Revert Ref\"))\n        style = *ref;\n    ImGui::SameLine();\n    HelpMarker(\"Save/Revert in local non-persistent storage. Default Colors definition are not affected. \"\n               \"Use \\\"Export\\\" below to save them somewhere.\");\n    if (ImGui::BeginTabBar(\"##StyleEditor\")) {\n        if (ImGui::BeginTabItem(\"Variables\")) {\n            ImGui::Text(\"Item Styling\");\n            ImGui::SliderFloat(\"LineWeight\", &style.LineWeight, 0.0f, 5.0f, \"%.1f\");\n            ImGui::SliderFloat(\"MarkerSize\", &style.MarkerSize, 2.0f, 10.0f, \"%.1f\");\n            ImGui::SliderFloat(\"MarkerWeight\", &style.MarkerWeight, 0.0f, 5.0f, \"%.1f\");\n            ImGui::SliderFloat(\"FillAlpha\", &style.FillAlpha, 0.0f, 1.0f, \"%.2f\");\n            ImGui::SliderFloat(\"ErrorBarSize\", &style.ErrorBarSize, 0.0f, 10.0f, \"%.1f\");\n            ImGui::SliderFloat(\"ErrorBarWeight\", &style.ErrorBarWeight, 0.0f, 5.0f, \"%.1f\");\n            ImGui::SliderFloat(\"DigitalBitHeight\", &style.DigitalBitHeight, 0.0f, 20.0f, \"%.1f\");\n            ImGui::SliderFloat(\"DigitalBitGap\", &style.DigitalBitGap, 0.0f, 20.0f, \"%.1f\");\n            ImGui::Text(\"Plot Styling\");\n            ImGui::SliderFloat(\"PlotBorderSize\", &style.PlotBorderSize, 0.0f, 2.0f, \"%.0f\");\n            ImGui::SliderFloat(\"MinorAlpha\", &style.MinorAlpha, 0.0f, 1.0f, \"%.2f\");\n            ImGui::SliderFloat2(\"MajorTickLen\", (float*)&style.MajorTickLen, 0.0f, 20.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"MinorTickLen\", (float*)&style.MinorTickLen, 0.0f, 20.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"MajorTickSize\",  (float*)&style.MajorTickSize, 0.0f, 2.0f, \"%.1f\");\n            ImGui::SliderFloat2(\"MinorTickSize\", (float*)&style.MinorTickSize, 0.0f, 2.0f, \"%.1f\");\n            ImGui::SliderFloat2(\"MajorGridSize\", (float*)&style.MajorGridSize, 0.0f, 2.0f, \"%.1f\");\n            ImGui::SliderFloat2(\"MinorGridSize\", (float*)&style.MinorGridSize, 0.0f, 2.0f, \"%.1f\");\n            ImGui::SliderFloat2(\"PlotDefaultSize\", (float*)&style.PlotDefaultSize, 0.0f, 1000, \"%.0f\");\n            ImGui::SliderFloat2(\"PlotMinSize\", (float*)&style.PlotMinSize, 0.0f, 300, \"%.0f\");\n            ImGui::Text(\"Plot Padding\");\n            ImGui::SliderFloat2(\"PlotPadding\", (float*)&style.PlotPadding, 0.0f, 20.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"LabelPadding\", (float*)&style.LabelPadding, 0.0f, 20.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"LegendPadding\", (float*)&style.LegendPadding, 0.0f, 20.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"LegendInnerPadding\", (float*)&style.LegendInnerPadding, 0.0f, 10.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"LegendSpacing\", (float*)&style.LegendSpacing, 0.0f, 5.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"MousePosPadding\", (float*)&style.MousePosPadding, 0.0f, 20.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"AnnotationPadding\", (float*)&style.AnnotationPadding, 0.0f, 5.0f, \"%.0f\");\n            ImGui::SliderFloat2(\"FitPadding\", (float*)&style.FitPadding, 0, 0.2f, \"%.2f\");\n\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Colors\")) {\n            static int output_dest = 0;\n            static bool output_only_modified = false;\n\n            if (ImGui::Button(\"Export\", ImVec2(75,0))) {\n                if (output_dest == 0)\n                    ImGui::LogToClipboard();\n                else\n                    ImGui::LogToTTY();\n                ImGui::LogText(\"ImVec4* colors = ImPlot::GetStyle().Colors;\\n\");\n                for (int i = 0; i < ImPlotCol_COUNT; i++) {\n                    const ImVec4& col = style.Colors[i];\n                    const char* name = ImPlot::GetStyleColorName(i);\n                    if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0) {\n                        if (IsColorAuto(i))\n                            ImGui::LogText(\"colors[ImPlotCol_%s]%*s= IMPLOT_AUTO_COL;\\n\",name,14 - (int)strlen(name), \"\");\n                        else\n                            ImGui::LogText(\"colors[ImPlotCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);\\n\",\n                                        name, 14 - (int)strlen(name), \"\", col.x, col.y, col.z, col.w);\n                    }\n                }\n                ImGui::LogFinish();\n            }\n            ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo(\"##output_type\", &output_dest, \"To Clipboard\\0To TTY\\0\");\n            ImGui::SameLine(); ImGui::Checkbox(\"Only Modified Colors\", &output_only_modified);\n\n            static ImGuiTextFilter filter;\n            filter.Draw(\"Filter colors\", ImGui::GetFontSize() * 16);\n\n            static ImGuiColorEditFlags alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;\n            if (ImGui::RadioButton(\"Opaque\", alpha_flags == ImGuiColorEditFlags_None))             { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();\n            if (ImGui::RadioButton(\"Alpha\",  alpha_flags == ImGuiColorEditFlags_AlphaPreview))     { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();\n            if (ImGui::RadioButton(\"Both\",   alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();\n            HelpMarker(\n                \"In the color list:\\n\"\n                \"Left-click on colored square to open color picker,\\n\"\n                \"Right-click to open edit options menu.\");\n            ImGui::Separator();\n            ImGui::PushItemWidth(-160);\n            for (int i = 0; i < ImPlotCol_COUNT; i++) {\n                const char* name = ImPlot::GetStyleColorName(i);\n                if (!filter.PassFilter(name))\n                    continue;\n                ImGui::PushID(i);\n                ImVec4 temp = GetStyleColorVec4(i);\n                const bool is_auto = IsColorAuto(i);\n                if (!is_auto)\n                    ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.25f);\n                if (ImGui::Button(\"Auto\")) {\n                    if (is_auto)\n                        style.Colors[i] = temp;\n                    else\n                        style.Colors[i] = IMPLOT_AUTO_COL;\n                    BustItemCache();\n                }\n                if (!is_auto)\n                    ImGui::PopStyleVar();\n                ImGui::SameLine();\n                if (ImGui::ColorEdit4(name, &temp.x, ImGuiColorEditFlags_NoInputs | alpha_flags)) {\n                    style.Colors[i] = temp;\n                    BustItemCache();\n                }\n                if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) {\n                    ImGui::SameLine(175); if (ImGui::Button(\"Save\")) { ref->Colors[i] = style.Colors[i]; }\n                    ImGui::SameLine(); if (ImGui::Button(\"Revert\")) {\n                        style.Colors[i] = ref->Colors[i];\n                        BustItemCache();\n                    }\n                }\n                ImGui::PopID();\n            }\n            ImGui::PopItemWidth();\n            ImGui::Separator();\n            ImGui::Text(\"Colors that are set to Auto (i.e. IMPLOT_AUTO_COL) will\\n\"\n                        \"be automatically deduced from your ImGui style or the\\n\"\n                        \"current ImPlot Colormap. If you want to style individual\\n\"\n                        \"plot items, use Push/PopStyleColor around its function.\");\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Colormaps\")) {\n            static int output_dest = 0;\n            if (ImGui::Button(\"Export\", ImVec2(75,0))) {\n                if (output_dest == 0)\n                    ImGui::LogToClipboard();\n                else\n                    ImGui::LogToTTY();\n                int size = GetColormapSize();\n                const char* name = GetColormapName(gp.Style.Colormap);\n                ImGui::LogText(\"static const ImU32 %s_Data[%d] = {\\n\", name, size);\n                for (int i = 0; i < size; ++i) {\n                    ImU32 col = GetColormapColorU32(i,gp.Style.Colormap);\n                    ImGui::LogText(\"    %u%s\\n\", col, i == size - 1 ? \"\" : \",\");\n                }\n                ImGui::LogText(\"};\\nImPlotColormap %s = ImPlot::AddColormap(\\\"%s\\\", %s_Data, %d);\", name, name, name, size);\n                ImGui::LogFinish();\n            }\n            ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo(\"##output_type\", &output_dest, \"To Clipboard\\0To TTY\\0\");\n            ImGui::SameLine();\n            static bool edit = false;\n            ImGui::Checkbox(\"Edit Mode\",&edit);\n\n            // built-in/added\n            ImGui::Separator();\n            for (int i = 0; i < gp.ColormapData.Count; ++i) {\n                ImGui::PushID(i);\n                int size = gp.ColormapData.GetKeyCount(i);\n                bool selected = i == gp.Style.Colormap;\n\n                const char* name = GetColormapName(i);\n                if (!selected)\n                    ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.25f);\n                if (ImGui::Button(name, ImVec2(100,0))) {\n                    gp.Style.Colormap = i;\n                    BustItemCache();\n                }\n                if (!selected)\n                    ImGui::PopStyleVar();\n                ImGui::SameLine();\n                ImGui::BeginGroup();\n                if (edit) {\n                    for (int c = 0; c < size; ++c) {\n                        ImGui::PushID(c);\n                        ImVec4 col4 = ImGui::ColorConvertU32ToFloat4(gp.ColormapData.GetKeyColor(i,c));\n                        if (ImGui::ColorEdit4(\"\",&col4.x,ImGuiColorEditFlags_NoInputs)) {\n                            ImU32 col32 = ImGui::ColorConvertFloat4ToU32(col4);\n                            gp.ColormapData.SetKeyColor(i,c,col32);\n                            BustItemCache();\n                        }\n                        if ((c + 1) % 12 != 0 && c != size -1)\n                            ImGui::SameLine();\n                        ImGui::PopID();\n                    }\n                }\n                else {\n                    if (ImPlot::ColormapButton(\"##\",ImVec2(-1,0),i))\n                        edit = true;\n                }\n                ImGui::EndGroup();\n                ImGui::PopID();\n            }\n\n\n            static ImVector<ImVec4> custom;\n            if (custom.Size == 0) {\n                custom.push_back(ImVec4(1,0,0,1));\n                custom.push_back(ImVec4(0,1,0,1));\n                custom.push_back(ImVec4(0,0,1,1));\n            }\n            ImGui::Separator();\n            ImGui::BeginGroup();\n            static char name[16] = \"MyColormap\";\n\n\n            if (ImGui::Button(\"+\", ImVec2((100 - ImGui::GetStyle().ItemSpacing.x)/2,0)))\n                custom.push_back(ImVec4(0,0,0,1));\n            ImGui::SameLine();\n            if (ImGui::Button(\"-\", ImVec2((100 - ImGui::GetStyle().ItemSpacing.x)/2,0)) && custom.Size > 2)\n                custom.pop_back();\n            ImGui::SetNextItemWidth(100);\n            ImGui::InputText(\"##Name\",name,16,ImGuiInputTextFlags_CharsNoBlank);\n            static bool qual = true;\n            ImGui::Checkbox(\"Qualitative\",&qual);\n            if (ImGui::Button(\"Add\", ImVec2(100, 0)) && gp.ColormapData.GetIndex(name)==-1)\n                AddColormap(name,custom.Data,custom.Size,qual);\n\n            ImGui::EndGroup();\n            ImGui::SameLine();\n            ImGui::BeginGroup();\n            for (int c = 0; c < custom.Size; ++c) {\n                ImGui::PushID(c);\n                if (ImGui::ColorEdit4(\"##Col1\", &custom[c].x, ImGuiColorEditFlags_NoInputs)) {\n\n                }\n                if ((c + 1) % 12 != 0)\n                    ImGui::SameLine();\n                ImGui::PopID();\n            }\n            ImGui::EndGroup();\n\n\n            ImGui::EndTabItem();\n        }\n        ImGui::EndTabBar();\n    }\n}\n\nvoid ShowUserGuide() {\n        ImGui::BulletText(\"Left-click drag within the plot area to pan X and Y axes.\");\n    ImGui::Indent();\n        ImGui::BulletText(\"Left-click drag on axis labels to pan an individual axis.\");\n    ImGui::Unindent();\n    ImGui::BulletText(\"Scroll in the plot area to zoom both X any Y axes.\");\n    ImGui::Indent();\n        ImGui::BulletText(\"Scroll on axis labels to zoom an individual axis.\");\n    ImGui::Unindent();\n    ImGui::BulletText(\"Right-click drag to box select data.\");\n    ImGui::Indent();\n        ImGui::BulletText(\"Hold Alt to expand box selection horizontally.\");\n        ImGui::BulletText(\"Hold Shift to expand box selection vertically.\");\n        ImGui::BulletText(\"Left-click while box selecting to cancel the selection.\");\n    ImGui::Unindent();\n    ImGui::BulletText(\"Double left-click to fit all visible data.\");\n    ImGui::Indent();\n        ImGui::BulletText(\"Double left-click axis labels to fit the individual axis.\");\n    ImGui::Unindent();\n    ImGui::BulletText(\"Right-click open the full plot context menu.\");\n    ImGui::Indent();\n        ImGui::BulletText(\"Right-click axis labels to open an individual axis context menu.\");\n    ImGui::Unindent();\n    ImGui::BulletText(\"Click legend label icons to show/hide plot items.\");\n}\n\nvoid ShowTicksMetrics(const ImPlotTicker& ticker) {\n    ImGui::BulletText(\"Size: %d\", ticker.TickCount());\n    ImGui::BulletText(\"MaxSize: [%f,%f]\", ticker.MaxSize.x, ticker.MaxSize.y);\n}\n\nvoid ShowAxisMetrics(const ImPlotPlot& plot, const ImPlotAxis& axis) {\n    ImGui::BulletText(\"Label: %s\", axis.LabelOffset == -1 ? \"[none]\" : plot.GetAxisLabel(axis));\n    ImGui::BulletText(\"Flags: 0x%08X\", axis.Flags);\n    ImGui::BulletText(\"Range: [%f,%f]\",axis.Range.Min, axis.Range.Max);\n    ImGui::BulletText(\"Pixels: %f\", axis.PixelSize());\n    ImGui::BulletText(\"Aspect: %f\", axis.GetAspect());\n    ImGui::BulletText(axis.OrthoAxis == nullptr ? \"OrtherAxis: NULL\" : \"OrthoAxis: 0x%08X\", axis.OrthoAxis->ID);\n    ImGui::BulletText(\"LinkedMin: %p\", (void*)axis.LinkedMin);\n    ImGui::BulletText(\"LinkedMax: %p\", (void*)axis.LinkedMax);\n    ImGui::BulletText(\"HasRange: %s\", axis.HasRange ? \"true\" : \"false\");\n    ImGui::BulletText(\"Hovered: %s\", axis.Hovered ? \"true\" : \"false\");\n    ImGui::BulletText(\"Held: %s\", axis.Held ? \"true\" : \"false\");\n\n    if (ImGui::TreeNode(\"Transform\")) {\n        ImGui::BulletText(\"PixelMin: %f\", axis.PixelMin);\n        ImGui::BulletText(\"PixelMax: %f\", axis.PixelMax);\n        ImGui::BulletText(\"ScaleToPixel: %f\", axis.ScaleToPixel);\n        ImGui::BulletText(\"ScaleMax: %f\", axis.ScaleMax);\n        ImGui::TreePop();\n    }\n\n    if (ImGui::TreeNode(\"Ticks\")) {\n        ShowTicksMetrics(axis.Ticker);\n        ImGui::TreePop();\n    }\n}\n\nvoid ShowMetricsWindow(bool* p_popen) {\n\n    static bool show_plot_rects = false;\n    static bool show_axes_rects = false;\n    static bool show_axis_rects = false;\n    static bool show_canvas_rects = false;\n    static bool show_frame_rects = false;\n    static bool show_subplot_frame_rects = false;\n    static bool show_subplot_grid_rects = false;\n\n    ImDrawList& fg = *ImGui::GetForegroundDrawList();\n\n    ImPlotContext& gp = *GImPlot;\n    // ImGuiContext& g = *GImGui;\n    ImGuiIO& io = ImGui::GetIO();\n    ImGui::Begin(\"ImPlot Metrics\", p_popen);\n    ImGui::Text(\"ImPlot \" IMPLOT_VERSION);\n    ImGui::Text(\"Application average %.3f ms/frame (%.1f FPS)\", 1000.0f / io.Framerate, io.Framerate);\n    ImGui::Text(\"Mouse Position: [%.0f,%.0f]\", io.MousePos.x, io.MousePos.y);\n    ImGui::Separator();\n    if (ImGui::TreeNode(\"Tools\")) {\n        if (ImGui::Button(\"Bust Plot Cache\"))\n            BustPlotCache();\n        ImGui::SameLine();\n        if (ImGui::Button(\"Bust Item Cache\"))\n            BustItemCache();\n        ImGui::Checkbox(\"Show Frame Rects\", &show_frame_rects);\n        ImGui::Checkbox(\"Show Canvas Rects\",&show_canvas_rects);\n        ImGui::Checkbox(\"Show Plot Rects\",  &show_plot_rects);\n        ImGui::Checkbox(\"Show Axes Rects\",  &show_axes_rects);\n        ImGui::Checkbox(\"Show Axis Rects\",  &show_axis_rects);\n        ImGui::Checkbox(\"Show Subplot Frame Rects\",  &show_subplot_frame_rects);\n        ImGui::Checkbox(\"Show Subplot Grid Rects\",  &show_subplot_grid_rects);\n        ImGui::TreePop();\n    }\n    const int n_plots = gp.Plots.GetBufSize();\n    const int n_subplots = gp.Subplots.GetBufSize();\n    // render rects\n    for (int p = 0; p < n_plots; ++p) {\n        ImPlotPlot* plot = gp.Plots.GetByIndex(p);\n        if (show_frame_rects)\n            fg.AddRect(plot->FrameRect.Min, plot->FrameRect.Max, IM_COL32(255,0,255,255));\n        if (show_canvas_rects)\n            fg.AddRect(plot->CanvasRect.Min, plot->CanvasRect.Max, IM_COL32(0,255,255,255));\n        if (show_plot_rects)\n            fg.AddRect(plot->PlotRect.Min, plot->PlotRect.Max, IM_COL32(255,255,0,255));\n        if (show_axes_rects)\n            fg.AddRect(plot->AxesRect.Min, plot->AxesRect.Max, IM_COL32(0,255,128,255));\n        if (show_axis_rects) {\n            for (int i = 0; i < ImAxis_COUNT; ++i) {\n                if (plot->Axes[i].Enabled)\n                    fg.AddRect(plot->Axes[i].HoverRect.Min, plot->Axes[i].HoverRect.Max, IM_COL32(0,255,0,255));\n            }\n        }\n    }\n    for (int p = 0; p < n_subplots; ++p) {\n        ImPlotSubplot* subplot = gp.Subplots.GetByIndex(p);\n        if (show_subplot_frame_rects)\n            fg.AddRect(subplot->FrameRect.Min, subplot->FrameRect.Max, IM_COL32(255,0,0,255));\n        if (show_subplot_grid_rects)\n            fg.AddRect(subplot->GridRect.Min, subplot->GridRect.Max, IM_COL32(0,0,255,255));\n    }\n    if (ImGui::TreeNode(\"Plots\",\"Plots (%d)\", n_plots)) {\n        for (int p = 0; p < n_plots; ++p) {\n            // plot\n            ImPlotPlot& plot = *gp.Plots.GetByIndex(p);\n            ImGui::PushID(p);\n            if (ImGui::TreeNode(\"Plot\", \"Plot [0x%08X]\", plot.ID)) {\n                int n_items = plot.Items.GetItemCount();\n                if (ImGui::TreeNode(\"Items\", \"Items (%d)\", n_items)) {\n                    for (int i = 0; i < n_items; ++i) {\n                        ImPlotItem* item = plot.Items.GetItemByIndex(i);\n                        ImGui::PushID(i);\n                        if (ImGui::TreeNode(\"Item\", \"Item [0x%08X]\", item->ID)) {\n                            ImGui::Bullet(); ImGui::Checkbox(\"Show\", &item->Show);\n                            ImGui::Bullet();\n                            ImVec4 temp = ImGui::ColorConvertU32ToFloat4(item->Color);\n                            if (ImGui::ColorEdit4(\"Color\",&temp.x, ImGuiColorEditFlags_NoInputs))\n                                item->Color = ImGui::ColorConvertFloat4ToU32(temp);\n\n                            ImGui::BulletText(\"NameOffset: %d\",item->NameOffset);\n                            ImGui::BulletText(\"Name: %s\", item->NameOffset != -1 ? plot.Items.Legend.Labels.Buf.Data + item->NameOffset : \"N/A\");\n                            ImGui::BulletText(\"Hovered: %s\",item->LegendHovered ? \"true\" : \"false\");\n                            ImGui::TreePop();\n                        }\n                        ImGui::PopID();\n                    }\n                    ImGui::TreePop();\n                }\n                char buff[16];\n                for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n                    ImFormatString(buff,16,\"X-Axis %d\", i+1);\n                    if (plot.XAxis(i).Enabled && ImGui::TreeNode(buff, \"X-Axis %d [0x%08X]\", i+1, plot.XAxis(i).ID)) {\n                        ShowAxisMetrics(plot, plot.XAxis(i));\n                        ImGui::TreePop();\n                    }\n                }\n                for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {\n                    ImFormatString(buff,16,\"Y-Axis %d\", i+1);\n                    if (plot.YAxis(i).Enabled && ImGui::TreeNode(buff, \"Y-Axis %d [0x%08X]\", i+1, plot.YAxis(i).ID)) {\n                        ShowAxisMetrics(plot, plot.YAxis(i));\n                        ImGui::TreePop();\n                    }\n                }\n                ImGui::BulletText(\"Title: %s\", plot.HasTitle() ? plot.GetTitle() : \"none\");\n                ImGui::BulletText(\"Flags: 0x%08X\", plot.Flags);\n                ImGui::BulletText(\"Initialized: %s\", plot.Initialized ? \"true\" : \"false\");\n                ImGui::BulletText(\"Selecting: %s\", plot.Selecting ? \"true\" : \"false\");\n                ImGui::BulletText(\"Selected: %s\", plot.Selected ? \"true\" : \"false\");\n                ImGui::BulletText(\"Hovered: %s\", plot.Hovered ? \"true\" : \"false\");\n                ImGui::BulletText(\"Held: %s\", plot.Held ? \"true\" : \"false\");\n                ImGui::BulletText(\"LegendHovered: %s\", plot.Items.Legend.Hovered ? \"true\" : \"false\");\n                ImGui::BulletText(\"ContextLocked: %s\", plot.ContextLocked ? \"true\" : \"false\");\n                ImGui::TreePop();\n            }\n            ImGui::PopID();\n        }\n        ImGui::TreePop();\n    }\n\n    if (ImGui::TreeNode(\"Subplots\",\"Subplots (%d)\", n_subplots)) {\n        for (int p = 0; p < n_subplots; ++p) {\n            // plot\n            ImPlotSubplot& plot = *gp.Subplots.GetByIndex(p);\n            ImGui::PushID(p);\n            if (ImGui::TreeNode(\"Subplot\", \"Subplot [0x%08X]\", plot.ID)) {\n                int n_items = plot.Items.GetItemCount();\n                if (ImGui::TreeNode(\"Items\", \"Items (%d)\", n_items)) {\n                    for (int i = 0; i < n_items; ++i) {\n                        ImPlotItem* item = plot.Items.GetItemByIndex(i);\n                        ImGui::PushID(i);\n                        if (ImGui::TreeNode(\"Item\", \"Item [0x%08X]\", item->ID)) {\n                            ImGui::Bullet(); ImGui::Checkbox(\"Show\", &item->Show);\n                            ImGui::Bullet();\n                            ImVec4 temp = ImGui::ColorConvertU32ToFloat4(item->Color);\n                            if (ImGui::ColorEdit4(\"Color\",&temp.x, ImGuiColorEditFlags_NoInputs))\n                                item->Color = ImGui::ColorConvertFloat4ToU32(temp);\n\n                            ImGui::BulletText(\"NameOffset: %d\",item->NameOffset);\n                            ImGui::BulletText(\"Name: %s\", item->NameOffset != -1 ? plot.Items.Legend.Labels.Buf.Data + item->NameOffset : \"N/A\");\n                            ImGui::BulletText(\"Hovered: %s\",item->LegendHovered ? \"true\" : \"false\");\n                            ImGui::TreePop();\n                        }\n                        ImGui::PopID();\n                    }\n                    ImGui::TreePop();\n                }\n                ImGui::BulletText(\"Flags: 0x%08X\", plot.Flags);\n                ImGui::BulletText(\"FrameHovered: %s\", plot.FrameHovered ? \"true\" : \"false\");\n                ImGui::BulletText(\"LegendHovered: %s\", plot.Items.Legend.Hovered ? \"true\" : \"false\");\n                ImGui::TreePop();\n            }\n            ImGui::PopID();\n        }\n        ImGui::TreePop();\n    }\n    if (ImGui::TreeNode(\"Colormaps\")) {\n        ImGui::BulletText(\"Colormaps:  %d\", gp.ColormapData.Count);\n        ImGui::BulletText(\"Memory: %d bytes\", gp.ColormapData.Tables.Size * 4);\n        if (ImGui::TreeNode(\"Data\")) {\n            for (int m = 0; m < gp.ColormapData.Count; ++m) {\n                if (ImGui::TreeNode(gp.ColormapData.GetName(m))) {\n                    int count = gp.ColormapData.GetKeyCount(m);\n                    int size = gp.ColormapData.GetTableSize(m);\n                    bool qual = gp.ColormapData.IsQual(m);\n                    ImGui::BulletText(\"Qualitative: %s\", qual ? \"true\" : \"false\");\n                    ImGui::BulletText(\"Key Count: %d\", count);\n                    ImGui::BulletText(\"Table Size: %d\", size);\n                    ImGui::Indent();\n\n                    static float t = 0.5;\n                    ImVec4 samp;\n                    float wid = 32 * 10 - ImGui::GetFrameHeight() - ImGui::GetStyle().ItemSpacing.x;\n                    ImGui::SetNextItemWidth(wid);\n                    ImPlot::ColormapSlider(\"##Sample\",&t,&samp,\"%.3f\",m);\n                    ImGui::SameLine();\n                    ImGui::ColorButton(\"Sampler\",samp);\n                    ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0,0,0,0));\n                    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));\n                    for (int c = 0; c < size; ++c) {\n                        ImVec4 col = ImGui::ColorConvertU32ToFloat4(gp.ColormapData.GetTableColor(m,c));\n                        ImGui::PushID(m*1000+c);\n                        ImGui::ColorButton(\"\",col,0,ImVec2(10,10));\n                        ImGui::PopID();\n                        if ((c + 1) % 32 != 0 && c != size - 1)\n                            ImGui::SameLine();\n                    }\n                    ImGui::PopStyleVar();\n                    ImGui::PopStyleColor();\n                    ImGui::Unindent();\n                    ImGui::TreePop();\n                }\n            }\n            ImGui::TreePop();\n        }\n        ImGui::TreePop();\n    }\n    ImGui::End();\n}\n\nbool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1, const ImPlotTime* t2) {\n\n    ImGui::PushID(id);\n    ImGui::BeginGroup();\n\n    ImGuiStyle& style = ImGui::GetStyle();\n    ImVec4 col_txt    = style.Colors[ImGuiCol_Text];\n    ImVec4 col_dis    = style.Colors[ImGuiCol_TextDisabled];\n    ImVec4 col_btn    = style.Colors[ImGuiCol_Button];\n    ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));\n    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));\n\n    const float ht    = ImGui::GetFrameHeight();\n    ImVec2 cell_size(ht*1.25f,ht);\n    char buff[32];\n    bool clk = false;\n    tm& Tm = GImPlot->Tm;\n\n    const int min_yr = 1970;\n    const int max_yr = 2999;\n\n    // t1 parts\n    int t1_mo = 0; int t1_md = 0; int t1_yr = 0;\n    if (t1 != nullptr) {\n        GetTime(*t1,&Tm);\n        t1_mo = Tm.tm_mon;\n        t1_md = Tm.tm_mday;\n        t1_yr = Tm.tm_year + 1900;\n    }\n\n     // t2 parts\n    int t2_mo = 0; int t2_md = 0; int t2_yr = 0;\n    if (t2 != nullptr) {\n        GetTime(*t2,&Tm);\n        t2_mo = Tm.tm_mon;\n        t2_md = Tm.tm_mday;\n        t2_yr = Tm.tm_year + 1900;\n    }\n\n    // day widget\n    if (*level == 0) {\n        *t = FloorTime(*t, ImPlotTimeUnit_Day);\n        GetTime(*t, &Tm);\n        const int this_year = Tm.tm_year + 1900;\n        const int last_year = this_year - 1;\n        const int next_year = this_year + 1;\n        const int this_mon  = Tm.tm_mon;\n        const int last_mon  = this_mon == 0 ? 11 : this_mon - 1;\n        const int next_mon  = this_mon == 11 ? 0 : this_mon + 1;\n        const int days_this_mo = GetDaysInMonth(this_year, this_mon);\n        const int days_last_mo = GetDaysInMonth(this_mon == 0 ? last_year : this_year, last_mon);\n        ImPlotTime t_first_mo = FloorTime(*t,ImPlotTimeUnit_Mo);\n        GetTime(t_first_mo,&Tm);\n        const int first_wd = Tm.tm_wday;\n        // month year\n        ImFormatString(buff, 32, \"%s %d\", MONTH_NAMES[this_mon], this_year);\n        if (ImGui::Button(buff))\n            *level = 1;\n        ImGui::SameLine(5*cell_size.x);\n        BeginDisabledControls(this_year <= min_yr && this_mon == 0);\n        if (ImGui::ArrowButtonEx(\"##Up\",ImGuiDir_Up,cell_size))\n            *t = AddTime(*t, ImPlotTimeUnit_Mo, -1);\n        EndDisabledControls(this_year <= min_yr && this_mon == 0);\n        ImGui::SameLine();\n        BeginDisabledControls(this_year >= max_yr && this_mon == 11);\n        if (ImGui::ArrowButtonEx(\"##Down\",ImGuiDir_Down,cell_size))\n            *t = AddTime(*t, ImPlotTimeUnit_Mo, 1);\n        EndDisabledControls(this_year >= max_yr && this_mon == 11);\n        // render weekday abbreviations\n        ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);\n        for (int i = 0; i < 7; ++i) {\n            ImGui::Button(WD_ABRVS[i],cell_size);\n            if (i != 6) { ImGui::SameLine(); }\n        }\n        ImGui::PopItemFlag();\n        // 0 = last mo, 1 = this mo, 2 = next mo\n        int mo = first_wd > 0 ? 0 : 1;\n        int day = mo == 1 ? 1 : days_last_mo - first_wd + 1;\n        for (int i = 0; i < 6; ++i) {\n            for (int j = 0; j < 7; ++j) {\n                if (mo == 0 && day > days_last_mo) {\n                    mo = 1;\n                    day = 1;\n                }\n                else if (mo == 1 && day > days_this_mo) {\n                    mo = 2;\n                    day = 1;\n                }\n                const int now_yr = (mo == 0 && this_mon == 0) ? last_year : ((mo == 2 && this_mon == 11) ? next_year : this_year);\n                const int now_mo = mo == 0 ? last_mon : (mo == 1 ? this_mon : next_mon);\n                const int now_md = day;\n\n                const bool off_mo   = mo == 0 || mo == 2;\n                const bool t1_or_t2 = (t1 != nullptr && t1_mo == now_mo && t1_yr == now_yr && t1_md == now_md) ||\n                                      (t2 != nullptr && t2_mo == now_mo && t2_yr == now_yr && t2_md == now_md);\n\n                if (off_mo)\n                    ImGui::PushStyleColor(ImGuiCol_Text, col_dis);\n                if (t1_or_t2) {\n                    ImGui::PushStyleColor(ImGuiCol_Button, col_btn);\n                    ImGui::PushStyleColor(ImGuiCol_Text, col_txt);\n                }\n                ImGui::PushID(i*7+j);\n                ImFormatString(buff,32,\"%d\",day);\n                if (now_yr == min_yr-1 || now_yr == max_yr+1) {\n                    ImGui::Dummy(cell_size);\n                }\n                else if (ImGui::Button(buff,cell_size) && !clk) {\n                    *t = MakeTime(now_yr, now_mo, now_md);\n                    clk = true;\n                }\n                ImGui::PopID();\n                if (t1_or_t2)\n                    ImGui::PopStyleColor(2);\n                if (off_mo)\n                    ImGui::PopStyleColor();\n                if (j != 6)\n                    ImGui::SameLine();\n                day++;\n            }\n        }\n    }\n    // month widget\n    else if (*level == 1) {\n        *t = FloorTime(*t, ImPlotTimeUnit_Mo);\n        GetTime(*t, &Tm);\n        int this_yr  = Tm.tm_year + 1900;\n        ImFormatString(buff, 32, \"%d\", this_yr);\n        if (ImGui::Button(buff))\n            *level = 2;\n        BeginDisabledControls(this_yr <= min_yr);\n        ImGui::SameLine(5*cell_size.x);\n        if (ImGui::ArrowButtonEx(\"##Up\",ImGuiDir_Up,cell_size))\n            *t = AddTime(*t, ImPlotTimeUnit_Yr, -1);\n        EndDisabledControls(this_yr <= min_yr);\n        ImGui::SameLine();\n        BeginDisabledControls(this_yr >= max_yr);\n        if (ImGui::ArrowButtonEx(\"##Down\",ImGuiDir_Down,cell_size))\n            *t = AddTime(*t, ImPlotTimeUnit_Yr, 1);\n        EndDisabledControls(this_yr >= max_yr);\n        // ImGui::Dummy(cell_size);\n        cell_size.x *= 7.0f/4.0f;\n        cell_size.y *= 7.0f/3.0f;\n        int mo = 0;\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 4; ++j) {\n                const bool t1_or_t2 = (t1 != nullptr && t1_yr == this_yr && t1_mo == mo) ||\n                                      (t2 != nullptr && t2_yr == this_yr && t2_mo == mo);\n                if (t1_or_t2)\n                    ImGui::PushStyleColor(ImGuiCol_Button, col_btn);\n                if (ImGui::Button(MONTH_ABRVS[mo],cell_size) && !clk) {\n                    *t = MakeTime(this_yr, mo);\n                    *level = 0;\n                }\n                if (t1_or_t2)\n                    ImGui::PopStyleColor();\n                if (j != 3)\n                    ImGui::SameLine();\n                mo++;\n            }\n        }\n    }\n    else if (*level == 2) {\n        *t = FloorTime(*t, ImPlotTimeUnit_Yr);\n        int this_yr = GetYear(*t);\n        int yr = this_yr  - this_yr % 20;\n        ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);\n        ImFormatString(buff,32,\"%d-%d\",yr,yr+19);\n        ImGui::Button(buff);\n        ImGui::PopItemFlag();\n        ImGui::SameLine(5*cell_size.x);\n        BeginDisabledControls(yr <= min_yr);\n        if (ImGui::ArrowButtonEx(\"##Up\",ImGuiDir_Up,cell_size))\n            *t = MakeTime(yr-20);\n        EndDisabledControls(yr <= min_yr);\n        ImGui::SameLine();\n        BeginDisabledControls(yr + 20 >= max_yr);\n        if (ImGui::ArrowButtonEx(\"##Down\",ImGuiDir_Down,cell_size))\n            *t = MakeTime(yr+20);\n        EndDisabledControls(yr+ 20 >= max_yr);\n        // ImGui::Dummy(cell_size);\n        cell_size.x *= 7.0f/4.0f;\n        cell_size.y *= 7.0f/5.0f;\n        for (int i = 0; i < 5; ++i) {\n            for (int j = 0; j < 4; ++j) {\n                const bool t1_or_t2 = (t1 != nullptr && t1_yr == yr) || (t2 != nullptr && t2_yr == yr);\n                if (t1_or_t2)\n                    ImGui::PushStyleColor(ImGuiCol_Button, col_btn);\n                ImFormatString(buff,32,\"%d\",yr);\n                if (yr<1970||yr>3000) {\n                    ImGui::Dummy(cell_size);\n                }\n                else if (ImGui::Button(buff,cell_size)) {\n                    *t = MakeTime(yr);\n                    *level = 1;\n                }\n                if (t1_or_t2)\n                    ImGui::PopStyleColor();\n                if (j != 3)\n                    ImGui::SameLine();\n                yr++;\n            }\n        }\n    }\n    ImGui::PopStyleVar();\n    ImGui::PopStyleColor();\n    ImGui::EndGroup();\n    ImGui::PopID();\n    return clk;\n}\n\nbool ShowTimePicker(const char* id, ImPlotTime* t) {\n    ImPlotContext& gp = *GImPlot;\n    ImGui::PushID(id);\n    tm& Tm = gp.Tm;\n    GetTime(*t,&Tm);\n\n    static const char* nums[] = { \"00\",\"01\",\"02\",\"03\",\"04\",\"05\",\"06\",\"07\",\"08\",\"09\",\n                                  \"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\",\"19\",\n                                  \"20\",\"21\",\"22\",\"23\",\"24\",\"25\",\"26\",\"27\",\"28\",\"29\",\n                                  \"30\",\"31\",\"32\",\"33\",\"34\",\"35\",\"36\",\"37\",\"38\",\"39\",\n                                  \"40\",\"41\",\"42\",\"43\",\"44\",\"45\",\"46\",\"47\",\"48\",\"49\",\n                                  \"50\",\"51\",\"52\",\"53\",\"54\",\"55\",\"56\",\"57\",\"58\",\"59\"};\n\n    static const char* am_pm[] = {\"am\",\"pm\"};\n\n    bool hour24 = gp.Style.Use24HourClock;\n\n    int hr  = hour24 ? Tm.tm_hour : ((Tm.tm_hour == 0 || Tm.tm_hour == 12) ? 12 : Tm.tm_hour % 12);\n    int min = Tm.tm_min;\n    int sec = Tm.tm_sec;\n    int ap  = Tm.tm_hour < 12 ? 0 : 1;\n\n    bool changed = false;\n\n    ImVec2 spacing = ImGui::GetStyle().ItemSpacing;\n    spacing.x = 0;\n    float width    = ImGui::CalcTextSize(\"888\").x;\n    float height   = ImGui::GetFrameHeight();\n\n    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, spacing);\n    ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize,2.0f);\n    ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0,0,0,0));\n    ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));\n    ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered));\n\n    ImGui::SetNextItemWidth(width);\n    if (ImGui::BeginCombo(\"##hr\",nums[hr],ImGuiComboFlags_NoArrowButton)) {\n        const int ia = hour24 ? 0 : 1;\n        const int ib = hour24 ? 24 : 13;\n        for (int i = ia; i < ib; ++i) {\n            if (ImGui::Selectable(nums[i],i==hr)) {\n                hr = i;\n                changed = true;\n            }\n        }\n        ImGui::EndCombo();\n    }\n    ImGui::SameLine();\n    ImGui::Text(\":\");\n    ImGui::SameLine();\n    ImGui::SetNextItemWidth(width);\n    if (ImGui::BeginCombo(\"##min\",nums[min],ImGuiComboFlags_NoArrowButton)) {\n        for (int i = 0; i < 60; ++i) {\n            if (ImGui::Selectable(nums[i],i==min)) {\n                min = i;\n                changed = true;\n            }\n        }\n        ImGui::EndCombo();\n    }\n    ImGui::SameLine();\n    ImGui::Text(\":\");\n    ImGui::SameLine();\n    ImGui::SetNextItemWidth(width);\n    if (ImGui::BeginCombo(\"##sec\",nums[sec],ImGuiComboFlags_NoArrowButton)) {\n        for (int i = 0; i < 60; ++i) {\n            if (ImGui::Selectable(nums[i],i==sec)) {\n                sec = i;\n                changed = true;\n            }\n        }\n        ImGui::EndCombo();\n    }\n    if (!hour24) {\n        ImGui::SameLine();\n        if (ImGui::Button(am_pm[ap],ImVec2(0,height))) {\n            ap = 1 - ap;\n            changed = true;\n        }\n    }\n\n    ImGui::PopStyleColor(3);\n    ImGui::PopStyleVar(2);\n    ImGui::PopID();\n\n    if (changed) {\n        if (!hour24)\n            hr = hr % 12 + ap * 12;\n        Tm.tm_hour = hr;\n        Tm.tm_min  = min;\n        Tm.tm_sec  = sec;\n        *t = MkTime(&Tm);\n    }\n\n    return changed;\n}\n\nvoid StyleColorsAuto(ImPlotStyle* dst) {\n    ImPlotStyle* style              = dst ? dst : &ImPlot::GetStyle();\n    ImVec4* colors                  = style->Colors;\n\n    style->MinorAlpha               = 0.25f;\n\n    colors[ImPlotCol_Line]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Fill]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerFill]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_ErrorBar]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_FrameBg]       = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_PlotBg]        = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_PlotBorder]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_LegendBg]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_LegendBorder]  = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_LegendText]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_TitleText]     = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_InlayText]     = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_PlotBorder]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_AxisText]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_AxisGrid]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_AxisTick]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_AxisBg]        = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_AxisBgHovered] = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_AxisBgActive]  = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Selection]     = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Crosshairs]    = IMPLOT_AUTO_COL;\n}\n\nvoid StyleColorsClassic(ImPlotStyle* dst) {\n    ImPlotStyle* style              = dst ? dst : &ImPlot::GetStyle();\n    ImVec4* colors                  = style->Colors;\n\n    style->MinorAlpha               = 0.5f;\n\n    colors[ImPlotCol_Line]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Fill]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerFill]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_ErrorBar]      = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);\n    colors[ImPlotCol_FrameBg]       = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);\n    colors[ImPlotCol_PlotBg]        = ImVec4(0.00f, 0.00f, 0.00f, 0.35f);\n    colors[ImPlotCol_PlotBorder]    = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);\n    colors[ImPlotCol_LegendBg]      = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);\n    colors[ImPlotCol_LegendBorder]  = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);\n    colors[ImPlotCol_LegendText]    = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);\n    colors[ImPlotCol_TitleText]     = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);\n    colors[ImPlotCol_InlayText]     = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);\n    colors[ImPlotCol_AxisText]      = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);\n    colors[ImPlotCol_AxisGrid]      = ImVec4(0.90f, 0.90f, 0.90f, 0.25f);\n    colors[ImPlotCol_AxisTick]      = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBg]        = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBgHovered] = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBgActive]  = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_Selection]     = ImVec4(0.97f, 0.97f, 0.39f, 1.00f);\n    colors[ImPlotCol_Crosshairs]    = ImVec4(0.50f, 0.50f, 0.50f, 0.75f);\n}\n\nvoid StyleColorsDark(ImPlotStyle* dst) {\n    ImPlotStyle* style              = dst ? dst : &ImPlot::GetStyle();\n    ImVec4* colors                  = style->Colors;\n\n    style->MinorAlpha               = 0.25f;\n\n    colors[ImPlotCol_Line]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Fill]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerFill]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_ErrorBar]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_FrameBg]       = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);\n    colors[ImPlotCol_PlotBg]        = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);\n    colors[ImPlotCol_PlotBorder]    = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);\n    colors[ImPlotCol_LegendBg]      = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);\n    colors[ImPlotCol_LegendBorder]  = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);\n    colors[ImPlotCol_LegendText]    = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_TitleText]     = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_InlayText]     = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_AxisText]      = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_AxisGrid]      = ImVec4(1.00f, 1.00f, 1.00f, 0.25f);\n    colors[ImPlotCol_AxisTick]      = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBg]        = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBgHovered] = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBgActive]  = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_Selection]     = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);\n    colors[ImPlotCol_Crosshairs]    = ImVec4(1.00f, 1.00f, 1.00f, 0.50f);\n}\n\nvoid StyleColorsLight(ImPlotStyle* dst) {\n    ImPlotStyle* style              = dst ? dst : &ImPlot::GetStyle();\n    ImVec4* colors                  = style->Colors;\n\n    style->MinorAlpha               = 1.0f;\n\n    colors[ImPlotCol_Line]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Fill]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerFill]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_ErrorBar]      = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_FrameBg]       = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_PlotBg]        = ImVec4(0.42f, 0.57f, 1.00f, 0.13f);\n    colors[ImPlotCol_PlotBorder]    = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\n    colors[ImPlotCol_LegendBg]      = ImVec4(1.00f, 1.00f, 1.00f, 0.98f);\n    colors[ImPlotCol_LegendBorder]  = ImVec4(0.82f, 0.82f, 0.82f, 0.80f);\n    colors[ImPlotCol_LegendText]    = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_TitleText]     = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_InlayText]     = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_AxisText]      = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_AxisGrid]      = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_AxisTick]      = ImVec4(0.00f, 0.00f, 0.00f, 0.25f);\n    colors[ImPlotCol_AxisBg]        = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBgHovered] = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_AxisBgActive]  = IMPLOT_AUTO_COL; // TODO\n    colors[ImPlotCol_Selection]     = ImVec4(0.82f, 0.64f, 0.03f, 1.00f);\n    colors[ImPlotCol_Crosshairs]    = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Obsolete Functions/Types\n//-----------------------------------------------------------------------------\n\n#ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS\n\nbool BeginPlot(const char* title, const char* x_label, const char* y1_label, const ImVec2& size,\n               ImPlotFlags flags, ImPlotAxisFlags x_flags, ImPlotAxisFlags y1_flags, ImPlotAxisFlags y2_flags, ImPlotAxisFlags y3_flags,\n               const char* y2_label, const char* y3_label)\n{\n    if (!BeginPlot(title, size, flags))\n        return false;\n    SetupAxis(ImAxis_X1, x_label, x_flags);\n    SetupAxis(ImAxis_Y1, y1_label, y1_flags);\n    if (ImHasFlag(flags, ImPlotFlags_YAxis2))\n        SetupAxis(ImAxis_Y2, y2_label, y2_flags);\n    if (ImHasFlag(flags, ImPlotFlags_YAxis3))\n        SetupAxis(ImAxis_Y3, y3_label, y3_flags);\n    return true;\n}\n\n#endif\n\n}  // namespace ImPlot\n"
  },
  {
    "path": "Source/External/imgui_tools/implot/implot.h",
    "content": "// MIT License\n\n// Copyright (c) 2022 Evan Pezent\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// ImPlot v0.14\n\n// Table of Contents:\n//\n// [SECTION] Macros and Defines\n// [SECTION] Enums and Types\n// [SECTION] Callbacks\n// [SECTION] Contexts\n// [SECTION] Begin/End Plot\n// [SECTION] Begin/End Subplot\n// [SECTION] Setup\n// [SECTION] SetNext\n// [SECTION] Plot Items\n// [SECTION] Plot Tools\n// [SECTION] Plot Utils\n// [SECTION] Legend Utils\n// [SECTION] Drag and Drop\n// [SECTION] Styling\n// [SECTION] Colormaps\n// [SECTION] Input Mapping\n// [SECTION] Miscellaneous\n// [SECTION] Demo\n// [SECTION] Obsolete API\n\n#pragma once\n#include \"imgui.h\"\n\n//-----------------------------------------------------------------------------\n// [SECTION] Macros and Defines\n//-----------------------------------------------------------------------------\n\n// Define attributes of all API symbols declarations (e.g. for DLL under Windows)\n// Using ImPlot via a shared library is not recommended, because we don't guarantee\n// backward nor forward ABI compatibility and also function call overhead. If you\n// do use ImPlot as a DLL, be sure to call SetImGuiContext (see Miscellanous section).\n#ifndef IMPLOT_API\n#define IMPLOT_API\n#endif\n\n// ImPlot version string.\n#define IMPLOT_VERSION \"0.14\"\n// Indicates variable should deduced automatically.\n#define IMPLOT_AUTO -1\n// Special color used to indicate that a color should be deduced automatically.\n#define IMPLOT_AUTO_COL ImVec4(0,0,0,-1)\n// Macro for templated plotting functions; keeps header clean.\n#define IMPLOT_TMP template <typename T> IMPLOT_API\n\n//-----------------------------------------------------------------------------\n// [SECTION] Enums and Types\n//-----------------------------------------------------------------------------\n\n// Forward declarations\nstruct ImPlotContext;             // ImPlot context (opaque struct, see implot_internal.h)\n\n// Enums/Flags\ntypedef int ImAxis;                   // -> enum ImAxis_\ntypedef int ImPlotFlags;              // -> enum ImPlotFlags_\ntypedef int ImPlotAxisFlags;          // -> enum ImPlotAxisFlags_\ntypedef int ImPlotSubplotFlags;       // -> enum ImPlotSubplotFlags_\ntypedef int ImPlotLegendFlags;        // -> enum ImPlotLegendFlags_\ntypedef int ImPlotMouseTextFlags;     // -> enum ImPlotMouseTextFlags_\ntypedef int ImPlotDragToolFlags;      // -> ImPlotDragToolFlags_\ntypedef int ImPlotColormapScaleFlags; // -> ImPlotColormapScaleFlags_\n\ntypedef int ImPlotItemFlags;          // -> ImPlotItemFlags_\ntypedef int ImPlotLineFlags;          // -> ImPlotLineFlags_\ntypedef int ImPlotScatterFlags;       // -> ImPlotScatterFlags\ntypedef int ImPlotStairsFlags;        // -> ImPlotStairsFlags_\ntypedef int ImPlotShadedFlags;        // -> ImPlotShadedFlags_\ntypedef int ImPlotBarsFlags;          // -> ImPlotBarsFlags_\ntypedef int ImPlotBarGroupsFlags;     // -> ImPlotBarGroupsFlags_\ntypedef int ImPlotErrorBarsFlags;     // -> ImPlotErrorBarsFlags_\ntypedef int ImPlotStemsFlags;         // -> ImPlotStemsFlags_\ntypedef int ImPlotInfLinesFlags;      // -> ImPlotInfLinesFlags_\ntypedef int ImPlotPieChartFlags;      // -> ImPlotPieChartFlags_\ntypedef int ImPlotHeatmapFlags;       // -> ImPlotHeatmapFlags_\ntypedef int ImPlotHistogramFlags;     // -> ImPlotHistogramFlags_\ntypedef int ImPlotDigitalFlags;       // -> ImPlotDigitalFlags_\ntypedef int ImPlotImageFlags;         // -> ImPlotImageFlags_\ntypedef int ImPlotTextFlags;          // -> ImPlotTextFlags_\ntypedef int ImPlotDummyFlags;         // -> ImPlotDummyFlags_\n\ntypedef int ImPlotCond;               // -> enum ImPlotCond_\ntypedef int ImPlotCol;                // -> enum ImPlotCol_\ntypedef int ImPlotStyleVar;           // -> enum ImPlotStyleVar_\ntypedef int ImPlotScale;              // -> enum ImPlotScale_\ntypedef int ImPlotMarker;             // -> enum ImPlotMarker_\ntypedef int ImPlotColormap;           // -> enum ImPlotColormap_\ntypedef int ImPlotLocation;           // -> enum ImPlotLocation_\ntypedef int ImPlotBin;                // -> enum ImPlotBin_\n\n// Axis indices. The values assigned may change; NEVER hardcode these.\nenum ImAxis_ {\n    // horizontal axes\n    ImAxis_X1 = 0, // enabled by default\n    ImAxis_X2,     // disabled by default\n    ImAxis_X3,     // disabled by default\n    // vertical axes\n    ImAxis_Y1,     // enabled by default\n    ImAxis_Y2,     // disabled by default\n    ImAxis_Y3,     // disabled by default\n    // bookeeping\n    ImAxis_COUNT\n};\n\n// Options for plots (see BeginPlot).\nenum ImPlotFlags_ {\n    ImPlotFlags_None          = 0,       // default\n    ImPlotFlags_NoTitle       = 1 << 0,  // the plot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. \"##MyPlot\")\n    ImPlotFlags_NoLegend      = 1 << 1,  // the legend will not be displayed\n    ImPlotFlags_NoMouseText   = 1 << 2,  // the mouse position, in plot coordinates, will not be displayed inside of the plot\n    ImPlotFlags_NoInputs      = 1 << 3,  // the user will not be able to interact with the plot\n    ImPlotFlags_NoMenus       = 1 << 4,  // the user will not be able to open context menus\n    ImPlotFlags_NoBoxSelect   = 1 << 5,  // the user will not be able to box-select\n    ImPlotFlags_NoChild       = 1 << 6,  // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications)\n    ImPlotFlags_NoFrame       = 1 << 7,  // the ImGui frame will not be rendered\n    ImPlotFlags_Equal         = 1 << 8,  // x and y axes pairs will be constrained to have the same units/pixel\n    ImPlotFlags_Crosshairs    = 1 << 9,  // the default mouse cursor will be replaced with a crosshair when hovered\n    ImPlotFlags_CanvasOnly    = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText\n};\n\n// Options for plot axes (see SetupAxis).\nenum ImPlotAxisFlags_ {\n    ImPlotAxisFlags_None          = 0,       // default\n    ImPlotAxisFlags_NoLabel       = 1 << 0,  // the axis label will not be displayed (axis labels are also hidden if the supplied string name is nullptr)\n    ImPlotAxisFlags_NoGridLines   = 1 << 1,  // no grid lines will be displayed\n    ImPlotAxisFlags_NoTickMarks   = 1 << 2,  // no tick marks will be displayed\n    ImPlotAxisFlags_NoTickLabels  = 1 << 3,  // no text labels will be displayed\n    ImPlotAxisFlags_NoInitialFit  = 1 << 4,  // axis will not be initially fit to data extents on the first rendered frame\n    ImPlotAxisFlags_NoMenus       = 1 << 5,  // the user will not be able to open context menus with right-click\n    ImPlotAxisFlags_NoSideSwitch  = 1 << 6,  // the user will not be able to switch the axis side by dragging it\n    ImPlotAxisFlags_NoHighlight   = 1 << 7,  // the axis will not have its background highlighted when hovered or held\n    ImPlotAxisFlags_Opposite      = 1 << 8,  // axis ticks and labels will be rendered on the conventionally opposite side (i.e, right or top)\n    ImPlotAxisFlags_Foreground    = 1 << 9,  // grid lines will be displayed in the foreground (i.e. on top of data) instead of the background\n    ImPlotAxisFlags_Invert        = 1 << 10, // the axis will be inverted\n    ImPlotAxisFlags_AutoFit       = 1 << 11, // axis will be auto-fitting to data extents\n    ImPlotAxisFlags_RangeFit      = 1 << 12, // axis will only fit points if the point is in the visible range of the **orthogonal** axis\n    ImPlotAxisFlags_PanStretch    = 1 << 13, // panning in a locked or constrained state will cause the axis to stretch if possible\n    ImPlotAxisFlags_LockMin       = 1 << 14, // the axis minimum value will be locked when panning/zooming\n    ImPlotAxisFlags_LockMax       = 1 << 15, // the axis maximum value will be locked when panning/zooming\n    ImPlotAxisFlags_Lock          = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax,\n    ImPlotAxisFlags_NoDecorations = ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoTickMarks | ImPlotAxisFlags_NoTickLabels,\n    ImPlotAxisFlags_AuxDefault    = ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_Opposite\n};\n\n// Options for subplots (see BeginSubplot)\nenum ImPlotSubplotFlags_ {\n    ImPlotSubplotFlags_None        = 0,       // default\n    ImPlotSubplotFlags_NoTitle     = 1 << 0,  // the subplot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. \"##MySubplot\")\n    ImPlotSubplotFlags_NoLegend    = 1 << 1,  // the legend will not be displayed (only applicable if ImPlotSubplotFlags_ShareItems is enabled)\n    ImPlotSubplotFlags_NoMenus     = 1 << 2,  // the user will not be able to open context menus with right-click\n    ImPlotSubplotFlags_NoResize    = 1 << 3,  // resize splitters between subplot cells will be not be provided\n    ImPlotSubplotFlags_NoAlign     = 1 << 4,  // subplot edges will not be aligned vertically or horizontally\n    ImPlotSubplotFlags_ShareItems  = 1 << 5,  // items across all subplots will be shared and rendered into a single legend entry\n    ImPlotSubplotFlags_LinkRows    = 1 << 6,  // link the y-axis limits of all plots in each row (does not apply to auxiliary axes)\n    ImPlotSubplotFlags_LinkCols    = 1 << 7,  // link the x-axis limits of all plots in each column (does not apply to auxiliary axes)\n    ImPlotSubplotFlags_LinkAllX    = 1 << 8,  // link the x-axis limits in every plot in the subplot (does not apply to auxiliary axes)\n    ImPlotSubplotFlags_LinkAllY    = 1 << 9,  // link the y-axis limits in every plot in the subplot (does not apply to auxiliary axes)\n    ImPlotSubplotFlags_ColMajor    = 1 << 10  // subplots are added in column major order instead of the default row major order\n};\n\n// Options for legends (see SetupLegend)\nenum ImPlotLegendFlags_ {\n    ImPlotLegendFlags_None            = 0,      // default\n    ImPlotLegendFlags_NoButtons       = 1 << 0, // legend icons will not function as hide/show buttons\n    ImPlotLegendFlags_NoHighlightItem = 1 << 1, // plot items will not be highlighted when their legend entry is hovered\n    ImPlotLegendFlags_NoHighlightAxis = 1 << 2, // axes will not be highlighted when legend entries are hovered (only relevant if x/y-axis count > 1)\n    ImPlotLegendFlags_NoMenus         = 1 << 3, // the user will not be able to open context menus with right-click\n    ImPlotLegendFlags_Outside         = 1 << 4, // legend will be rendered outside of the plot area\n    ImPlotLegendFlags_Horizontal      = 1 << 5, // legend entries will be displayed horizontally\n    ImPlotLegendFlags_Sort            = 1 << 6, // legend entries will be displayed in alphabetical order\n};\n\n// Options for mouse hover text (see SetupMouseText)\nenum ImPlotMouseTextFlags_ {\n    ImPlotMouseTextFlags_None        = 0,      // default\n    ImPlotMouseTextFlags_NoAuxAxes   = 1 << 0, // only show the mouse position for primary axes\n    ImPlotMouseTextFlags_NoFormat    = 1 << 1, // axes label formatters won't be used to render text\n    ImPlotMouseTextFlags_ShowAlways  = 1 << 2, // always display mouse position even if plot not hovered\n};\n\n// Options for DragPoint, DragLine, DragRect\nenum ImPlotDragToolFlags_ {\n    ImPlotDragToolFlags_None      = 0,      // default\n    ImPlotDragToolFlags_NoCursors = 1 << 0, // drag tools won't change cursor icons when hovered or held\n    ImPlotDragToolFlags_NoFit     = 1 << 1, // the drag tool won't be considered for plot fits\n    ImPlotDragToolFlags_NoInputs  = 1 << 2, // lock the tool from user inputs\n    ImPlotDragToolFlags_Delayed   = 1 << 3, // tool rendering will be delayed one frame; useful when applying position-constraints\n};\n\n// Flags for ColormapScale\nenum ImPlotColormapScaleFlags_ {\n    ImPlotColormapScaleFlags_None     = 0,      // default\n    ImPlotColormapScaleFlags_NoLabel  = 1 << 0, // the colormap axis label will not be displayed\n    ImPlotColormapScaleFlags_Opposite = 1 << 1, // render the colormap label and tick labels on the opposite side\n    ImPlotColormapScaleFlags_Invert   = 1 << 2, // invert the colormap bar and axis scale (this only affects rendering; if you only want to reverse the scale mapping, make scale_min > scale_max)\n};\n\n// Flags for ANY PlotX function\nenum ImPlotItemFlags_ {\n    ImPlotItemFlags_None     = 0,\n    ImPlotItemFlags_NoLegend = 1 << 0, // the item won't have a legend entry displayed\n    ImPlotItemFlags_NoFit    = 1 << 1, // the item won't be considered for plot fits\n};\n\n// Flags for PlotLine\nenum ImPlotLineFlags_ {\n    ImPlotLineFlags_None        = 0,       // default\n    ImPlotLineFlags_Segments    = 1 << 10, // a line segment will be rendered from every two consecutive points\n    ImPlotLineFlags_Loop        = 1 << 11, // the last and first point will be connected to form a closed loop\n    ImPlotLineFlags_SkipNaN     = 1 << 12, // NaNs values will be skipped instead of rendered as missing data\n    ImPlotLineFlags_NoClip      = 1 << 13, // markers (if displayed) on the edge of a plot will not be clipped\n    ImPlotLineFlags_Shaded      = 1 << 14, // a filled region between the line and horizontal origin will be rendered; use PlotShaded for more advanced cases\n};\n\n// Flags for PlotScatter\nenum ImPlotScatterFlags_ {\n    ImPlotScatterFlags_None   = 0,       // default\n    ImPlotScatterFlags_NoClip = 1 << 10, // markers on the edge of a plot will not be clipped\n};\n\n// Flags for PlotStairs\nenum ImPlotStairsFlags_ {\n    ImPlotStairsFlags_None     = 0,       // default\n    ImPlotStairsFlags_PreStep  = 1 << 10, // the y value is continued constantly to the left from every x position, i.e. the interval (x[i-1], x[i]] has the value y[i]\n    ImPlotStairsFlags_Shaded   = 1 << 11  // a filled region between the stairs and horizontal origin will be rendered; use PlotShaded for more advanced cases\n};\n\n// Flags for PlotShaded (placeholder)\nenum ImPlotShadedFlags_ {\n    ImPlotShadedFlags_None  = 0 // default\n};\n\n// Flags for PlotBars\nenum ImPlotBarsFlags_ {\n    ImPlotBarsFlags_None         = 0,       // default\n    ImPlotBarsFlags_Horizontal   = 1 << 10, // bars will be rendered horizontally on the current y-axis\n};\n\n// Flags for PlotBarGroups\nenum ImPlotBarGroupsFlags_ {\n    ImPlotBarGroupsFlags_None        = 0,       // default\n    ImPlotBarGroupsFlags_Horizontal  = 1 << 10, // bar groups will be rendered horizontally on the current y-axis\n    ImPlotBarGroupsFlags_Stacked     = 1 << 11, // items in a group will be stacked on top of each other\n};\n\n// Flags for PlotErrorBars\nenum ImPlotErrorBarsFlags_ {\n    ImPlotErrorBarsFlags_None       = 0,       // default\n    ImPlotErrorBarsFlags_Horizontal = 1 << 10, // error bars will be rendered horizontally on the current y-axis\n};\n\n// Flags for PlotStems\nenum ImPlotStemsFlags_ {\n    ImPlotStemsFlags_None       = 0,       // default\n    ImPlotStemsFlags_Horizontal = 1 << 10, // stems will be rendered horizontally on the current y-axis\n};\n\n// Flags for PlotInfLines\nenum ImPlotInfLinesFlags_ {\n    ImPlotInfLinesFlags_None       = 0,      // default\n    ImPlotInfLinesFlags_Horizontal = 1 << 10 // lines will be rendered horizontally on the current y-axis\n};\n\n// Flags for PlotPieChart\nenum ImPlotPieChartFlags_ {\n    ImPlotPieChartFlags_None      = 0,      // default\n    ImPlotPieChartFlags_Normalize = 1 << 10 // force normalization of pie chart values (i.e. always make a full circle if sum < 0)\n};\n\n// Flags for PlotHeatmap\nenum ImPlotHeatmapFlags_ {\n    ImPlotHeatmapFlags_None     = 0,       // default\n    ImPlotHeatmapFlags_ColMajor = 1 << 10, // data will be read in column major order\n};\n\n// Flags for PlotHistogram and PlotHistogram2D\nenum ImPlotHistogramFlags_ {\n    ImPlotHistogramFlags_None       = 0,       // default\n    ImPlotHistogramFlags_Horizontal = 1 << 10, // histogram bars will be rendered horizontally (not supported by PlotHistogram2D)\n    ImPlotHistogramFlags_Cumulative = 1 << 11, // each bin will contain its count plus the counts of all previous bins (not supported by PlotHistogram2D)\n    ImPlotHistogramFlags_Density    = 1 << 12, // counts will be normalized, i.e. the PDF will be visualized, or the CDF will be visualized if Cumulative is also set\n    ImPlotHistogramFlags_NoOutliers = 1 << 13, // exclude values outside the specifed histogram range from the count toward normalizing and cumulative counts\n    ImPlotHistogramFlags_ColMajor   = 1 << 14  // data will be read in column major order (not supported by PlotHistogram)\n};\n\n// Flags for PlotDigital (placeholder)\nenum ImPlotDigitalFlags_ {\n    ImPlotDigitalFlags_None = 0 // default\n};\n\n// Flags for PlotImage (placeholder)\nenum ImPlotImageFlags_ {\n    ImPlotImageFlags_None = 0 // default\n};\n\n// Flags for PlotText\nenum ImPlotTextFlags_ {\n    ImPlotTextFlags_None     = 0,       // default\n    ImPlotTextFlags_Vertical = 1 << 10  // text will be rendered vertically\n};\n\n// Flags for PlotDummy (placeholder)\nenum ImPlotDummyFlags_ {\n    ImPlotDummyFlags_None = 0 // default\n};\n\n// Represents a condition for SetupAxisLimits etc. (same as ImGuiCond, but we only support a subset of those enums)\nenum ImPlotCond_\n{\n    ImPlotCond_None   = ImGuiCond_None,    // No condition (always set the variable), same as _Always\n    ImPlotCond_Always = ImGuiCond_Always,  // No condition (always set the variable)\n    ImPlotCond_Once   = ImGuiCond_Once,    // Set the variable once per runtime session (only the first call will succeed)\n};\n\n// Plot styling colors.\nenum ImPlotCol_ {\n    // item styling colors\n    ImPlotCol_Line,          // plot line/outline color (defaults to next unused color in current colormap)\n    ImPlotCol_Fill,          // plot fill color for bars (defaults to the current line color)\n    ImPlotCol_MarkerOutline, // marker outline color (defaults to the current line color)\n    ImPlotCol_MarkerFill,    // marker fill color (defaults to the current line color)\n    ImPlotCol_ErrorBar,      // error bar color (defaults to ImGuiCol_Text)\n    // plot styling colors\n    ImPlotCol_FrameBg,       // plot frame background color (defaults to ImGuiCol_FrameBg)\n    ImPlotCol_PlotBg,        // plot area background color (defaults to ImGuiCol_WindowBg)\n    ImPlotCol_PlotBorder,    // plot area border color (defaults to ImGuiCol_Border)\n    ImPlotCol_LegendBg,      // legend background color (defaults to ImGuiCol_PopupBg)\n    ImPlotCol_LegendBorder,  // legend border color (defaults to ImPlotCol_PlotBorder)\n    ImPlotCol_LegendText,    // legend text color (defaults to ImPlotCol_InlayText)\n    ImPlotCol_TitleText,     // plot title text color (defaults to ImGuiCol_Text)\n    ImPlotCol_InlayText,     // color of text appearing inside of plots (defaults to ImGuiCol_Text)\n    ImPlotCol_AxisText,      // axis label and tick lables color (defaults to ImGuiCol_Text)\n    ImPlotCol_AxisGrid,      // axis grid color (defaults to 25% ImPlotCol_AxisText)\n    ImPlotCol_AxisTick,      // axis tick color (defaults to AxisGrid)\n    ImPlotCol_AxisBg,        // background color of axis hover region (defaults to transparent)\n    ImPlotCol_AxisBgHovered, // axis hover color (defaults to ImGuiCol_ButtonHovered)\n    ImPlotCol_AxisBgActive,  // axis active color (defaults to ImGuiCol_ButtonActive)\n    ImPlotCol_Selection,     // box-selection color (defaults to yellow)\n    ImPlotCol_Crosshairs,    // crosshairs color (defaults to ImPlotCol_PlotBorder)\n    ImPlotCol_COUNT\n};\n\n// Plot styling variables.\nenum ImPlotStyleVar_ {\n    // item styling variables\n    ImPlotStyleVar_LineWeight,         // float,  plot item line weight in pixels\n    ImPlotStyleVar_Marker,             // int,    marker specification\n    ImPlotStyleVar_MarkerSize,         // float,  marker size in pixels (roughly the marker's \"radius\")\n    ImPlotStyleVar_MarkerWeight,       // float,  plot outline weight of markers in pixels\n    ImPlotStyleVar_FillAlpha,          // float,  alpha modifier applied to all plot item fills\n    ImPlotStyleVar_ErrorBarSize,       // float,  error bar whisker width in pixels\n    ImPlotStyleVar_ErrorBarWeight,     // float,  error bar whisker weight in pixels\n    ImPlotStyleVar_DigitalBitHeight,   // float,  digital channels bit height (at 1) in pixels\n    ImPlotStyleVar_DigitalBitGap,      // float,  digital channels bit padding gap in pixels\n    // plot styling variables\n    ImPlotStyleVar_PlotBorderSize,     // float,  thickness of border around plot area\n    ImPlotStyleVar_MinorAlpha,         // float,  alpha multiplier applied to minor axis grid lines\n    ImPlotStyleVar_MajorTickLen,       // ImVec2, major tick lengths for X and Y axes\n    ImPlotStyleVar_MinorTickLen,       // ImVec2, minor tick lengths for X and Y axes\n    ImPlotStyleVar_MajorTickSize,      // ImVec2, line thickness of major ticks\n    ImPlotStyleVar_MinorTickSize,      // ImVec2, line thickness of minor ticks\n    ImPlotStyleVar_MajorGridSize,      // ImVec2, line thickness of major grid lines\n    ImPlotStyleVar_MinorGridSize,      // ImVec2, line thickness of minor grid lines\n    ImPlotStyleVar_PlotPadding,        // ImVec2, padding between widget frame and plot area, labels, or outside legends (i.e. main padding)\n    ImPlotStyleVar_LabelPadding,       // ImVec2, padding between axes labels, tick labels, and plot edge\n    ImPlotStyleVar_LegendPadding,      // ImVec2, legend padding from plot edges\n    ImPlotStyleVar_LegendInnerPadding, // ImVec2, legend inner padding from legend edges\n    ImPlotStyleVar_LegendSpacing,      // ImVec2, spacing between legend entries\n    ImPlotStyleVar_MousePosPadding,    // ImVec2, padding between plot edge and interior info text\n    ImPlotStyleVar_AnnotationPadding,  // ImVec2, text padding around annotation labels\n    ImPlotStyleVar_FitPadding,         // ImVec2, additional fit padding as a percentage of the fit extents (e.g. ImVec2(0.1f,0.1f) adds 10% to the fit extents of X and Y)\n    ImPlotStyleVar_PlotDefaultSize,    // ImVec2, default size used when ImVec2(0,0) is passed to BeginPlot\n    ImPlotStyleVar_PlotMinSize,        // ImVec2, minimum size plot frame can be when shrunk\n    ImPlotStyleVar_COUNT\n};\n\n// Axis scale\nenum ImPlotScale_ {\n    ImPlotScale_Linear = 0, // default linear scale\n    ImPlotScale_Time,       // date/time scale\n    ImPlotScale_Log10,      // base 10 logartithmic scale\n    ImPlotScale_SymLog,     // symmetric log scale\n};\n\n// Marker specifications.\nenum ImPlotMarker_ {\n    ImPlotMarker_None = -1, // no marker\n    ImPlotMarker_Circle,    // a circle marker (default)\n    ImPlotMarker_Square,    // a square maker\n    ImPlotMarker_Diamond,   // a diamond marker\n    ImPlotMarker_Up,        // an upward-pointing triangle marker\n    ImPlotMarker_Down,      // an downward-pointing triangle marker\n    ImPlotMarker_Left,      // an leftward-pointing triangle marker\n    ImPlotMarker_Right,     // an rightward-pointing triangle marker\n    ImPlotMarker_Cross,     // a cross marker (not fillable)\n    ImPlotMarker_Plus,      // a plus marker (not fillable)\n    ImPlotMarker_Asterisk,  // a asterisk marker (not fillable)\n    ImPlotMarker_COUNT\n};\n\n// Built-in colormaps\nenum ImPlotColormap_ {\n    ImPlotColormap_Deep     = 0,   // a.k.a. seaborn deep             (qual=true,  n=10) (default)\n    ImPlotColormap_Dark     = 1,   // a.k.a. matplotlib \"Set1\"        (qual=true,  n=9 )\n    ImPlotColormap_Pastel   = 2,   // a.k.a. matplotlib \"Pastel1\"     (qual=true,  n=9 )\n    ImPlotColormap_Paired   = 3,   // a.k.a. matplotlib \"Paired\"      (qual=true,  n=12)\n    ImPlotColormap_Viridis  = 4,   // a.k.a. matplotlib \"viridis\"     (qual=false, n=11)\n    ImPlotColormap_Plasma   = 5,   // a.k.a. matplotlib \"plasma\"      (qual=false, n=11)\n    ImPlotColormap_Hot      = 6,   // a.k.a. matplotlib/MATLAB \"hot\"  (qual=false, n=11)\n    ImPlotColormap_Cool     = 7,   // a.k.a. matplotlib/MATLAB \"cool\" (qual=false, n=11)\n    ImPlotColormap_Pink     = 8,   // a.k.a. matplotlib/MATLAB \"pink\" (qual=false, n=11)\n    ImPlotColormap_Jet      = 9,   // a.k.a. MATLAB \"jet\"             (qual=false, n=11)\n    ImPlotColormap_Twilight = 10,  // a.k.a. matplotlib \"twilight\"    (qual=false, n=11)\n    ImPlotColormap_RdBu     = 11,  // red/blue, Color Brewer          (qual=false, n=11)\n    ImPlotColormap_BrBG     = 12,  // brown/blue-green, Color Brewer  (qual=false, n=11)\n    ImPlotColormap_PiYG     = 13,  // pink/yellow-green, Color Brewer (qual=false, n=11)\n    ImPlotColormap_Spectral = 14,  // color spectrum, Color Brewer    (qual=false, n=11)\n    ImPlotColormap_Greys    = 15,  // white/black                     (qual=false, n=2 )\n};\n\n// Used to position items on a plot (e.g. legends, labels, etc.)\nenum ImPlotLocation_ {\n    ImPlotLocation_Center    = 0,                                          // center-center\n    ImPlotLocation_North     = 1 << 0,                                     // top-center\n    ImPlotLocation_South     = 1 << 1,                                     // bottom-center\n    ImPlotLocation_West      = 1 << 2,                                     // center-left\n    ImPlotLocation_East      = 1 << 3,                                     // center-right\n    ImPlotLocation_NorthWest = ImPlotLocation_North | ImPlotLocation_West, // top-left\n    ImPlotLocation_NorthEast = ImPlotLocation_North | ImPlotLocation_East, // top-right\n    ImPlotLocation_SouthWest = ImPlotLocation_South | ImPlotLocation_West, // bottom-left\n    ImPlotLocation_SouthEast = ImPlotLocation_South | ImPlotLocation_East  // bottom-right\n};\n\n// Enums for different automatic histogram binning methods (k = bin count or w = bin width)\nenum ImPlotBin_ {\n    ImPlotBin_Sqrt    = -1, // k = sqrt(n)\n    ImPlotBin_Sturges = -2, // k = 1 + log2(n)\n    ImPlotBin_Rice    = -3, // k = 2 * cbrt(n)\n    ImPlotBin_Scott   = -4, // w = 3.49 * sigma / cbrt(n)\n};\n\n// Double precision version of ImVec2 used by ImPlot. Extensible by end users.\nstruct ImPlotPoint {\n    double x, y;\n    ImPlotPoint()                         { x = y = 0.0;      }\n    ImPlotPoint(double _x, double _y)     { x = _x; y = _y;   }\n    ImPlotPoint(const ImVec2& p)          { x = p.x; y = p.y; }\n    double  operator[] (size_t idx) const { return (&x)[idx]; }\n    double& operator[] (size_t idx)       { return (&x)[idx]; }\n#ifdef IMPLOT_POINT_CLASS_EXTRA\n    IMPLOT_POINT_CLASS_EXTRA     // Define additional constructors and implicit cast operators in imconfig.h\n                                 // to convert back and forth between your math types and ImPlotPoint.\n#endif\n};\n\n// Range defined by a min/max value.\nstruct ImPlotRange {\n    double Min, Max;\n    ImPlotRange()                         { Min = 0; Max = 0;                                         }\n    ImPlotRange(double _min, double _max) { Min = _min; Max = _max;                                   }\n    bool Contains(double value) const     { return value >= Min && value <= Max;                      }\n    double Size() const                   { return Max - Min;                                         }\n    double Clamp(double value) const      { return (value < Min) ? Min : (value > Max) ? Max : value; }\n};\n\n// Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max().\nstruct ImPlotRect {\n    ImPlotRange X, Y;\n    ImPlotRect()                                                       {                                                               }\n    ImPlotRect(double x_min, double x_max, double y_min, double y_max) { X.Min = x_min; X.Max = x_max; Y.Min = y_min; Y.Max = y_max;   }\n    bool Contains(const ImPlotPoint& p) const                          { return Contains(p.x, p.y);                                    }\n    bool Contains(double x, double y) const                            { return X.Contains(x) && Y.Contains(y);                        }\n    ImPlotPoint Size() const                                           { return ImPlotPoint(X.Size(), Y.Size());                       }\n    ImPlotPoint Clamp(const ImPlotPoint& p)                            { return Clamp(p.x, p.y);                                       }\n    ImPlotPoint Clamp(double x, double y)                              { return ImPlotPoint(X.Clamp(x),Y.Clamp(y));                    }\n    ImPlotPoint Min() const                                            { return ImPlotPoint(X.Min, Y.Min);                             }\n    ImPlotPoint Max() const                                            { return ImPlotPoint(X.Max, Y.Max);                             }\n};\n\n// Plot style structure\nstruct ImPlotStyle {\n    // item styling variables\n    float   LineWeight;              // = 1,      item line weight in pixels\n    int     Marker;                  // = ImPlotMarker_None, marker specification\n    float   MarkerSize;              // = 4,      marker size in pixels (roughly the marker's \"radius\")\n    float   MarkerWeight;            // = 1,      outline weight of markers in pixels\n    float   FillAlpha;               // = 1,      alpha modifier applied to plot fills\n    float   ErrorBarSize;            // = 5,      error bar whisker width in pixels\n    float   ErrorBarWeight;          // = 1.5,    error bar whisker weight in pixels\n    float   DigitalBitHeight;        // = 8,      digital channels bit height (at y = 1.0f) in pixels\n    float   DigitalBitGap;           // = 4,      digital channels bit padding gap in pixels\n    // plot styling variables\n    float   PlotBorderSize;          // = 1,      line thickness of border around plot area\n    float   MinorAlpha;              // = 0.25    alpha multiplier applied to minor axis grid lines\n    ImVec2  MajorTickLen;            // = 10,10   major tick lengths for X and Y axes\n    ImVec2  MinorTickLen;            // = 5,5     minor tick lengths for X and Y axes\n    ImVec2  MajorTickSize;           // = 1,1     line thickness of major ticks\n    ImVec2  MinorTickSize;           // = 1,1     line thickness of minor ticks\n    ImVec2  MajorGridSize;           // = 1,1     line thickness of major grid lines\n    ImVec2  MinorGridSize;           // = 1,1     line thickness of minor grid lines\n    ImVec2  PlotPadding;             // = 10,10   padding between widget frame and plot area, labels, or outside legends (i.e. main padding)\n    ImVec2  LabelPadding;            // = 5,5     padding between axes labels, tick labels, and plot edge\n    ImVec2  LegendPadding;           // = 10,10   legend padding from plot edges\n    ImVec2  LegendInnerPadding;      // = 5,5     legend inner padding from legend edges\n    ImVec2  LegendSpacing;           // = 5,0     spacing between legend entries\n    ImVec2  MousePosPadding;         // = 10,10   padding between plot edge and interior mouse location text\n    ImVec2  AnnotationPadding;       // = 2,2     text padding around annotation labels\n    ImVec2  FitPadding;              // = 0,0     additional fit padding as a percentage of the fit extents (e.g. ImVec2(0.1f,0.1f) adds 10% to the fit extents of X and Y)\n    ImVec2  PlotDefaultSize;         // = 400,300 default size used when ImVec2(0,0) is passed to BeginPlot\n    ImVec2  PlotMinSize;             // = 200,150 minimum size plot frame can be when shrunk\n    // style colors\n    ImVec4  Colors[ImPlotCol_COUNT]; // Array of styling colors. Indexable with ImPlotCol_ enums.\n    // colormap\n    ImPlotColormap Colormap;         // The current colormap. Set this to either an ImPlotColormap_ enum or an index returned by AddColormap.\n    // settings/flags\n    bool    UseLocalTime;            // = false,  axis labels will be formatted for your timezone when ImPlotAxisFlag_Time is enabled\n    bool    UseISO8601;              // = false,  dates will be formatted according to ISO 8601 where applicable (e.g. YYYY-MM-DD, YYYY-MM, --MM-DD, etc.)\n    bool    Use24HourClock;          // = false,  times will be formatted using a 24 hour clock\n    IMPLOT_API ImPlotStyle();\n};\n\n// Support for legacy versions\n#if (IMGUI_VERSION_NUM < 18716) // Renamed in 1.88\n#define ImGuiMod_None       0\n#define ImGuiMod_Ctrl       ImGuiKeyModFlags_Ctrl\n#define ImGuiMod_Shift      ImGuiKeyModFlags_Shift\n#define ImGuiMod_Alt        ImGuiKeyModFlags_Alt\n#define ImGuiMod_Super      ImGuiKeyModFlags_Super\n#elif (IMGUI_VERSION_NUM < 18823) // Renamed in 1.89, sorry\n#define ImGuiMod_None       0\n#define ImGuiMod_Ctrl       ImGuiModFlags_Ctrl\n#define ImGuiMod_Shift      ImGuiModFlags_Shift\n#define ImGuiMod_Alt        ImGuiModFlags_Alt\n#define ImGuiMod_Super      ImGuiModFlags_Super\n#endif\n\n// Input mapping structure. Default values listed. See also MapInputDefault, MapInputReverse.\nstruct ImPlotInputMap {\n    ImGuiMouseButton Pan;           // LMB    enables panning when held,\n    int              PanMod;        // none   optional modifier that must be held for panning/fitting\n    ImGuiMouseButton Fit;           // LMB    initiates fit when double clicked\n    ImGuiMouseButton Select;        // RMB    begins box selection when pressed and confirms selection when released\n    ImGuiMouseButton SelectCancel;  // LMB    cancels active box selection when pressed; cannot be same as Select\n    int              SelectMod;     // none   optional modifier that must be held for box selection\n    int              SelectHorzMod; // Alt    expands active box selection horizontally to plot edge when held\n    int              SelectVertMod; // Shift  expands active box selection vertically to plot edge when held\n    ImGuiMouseButton Menu;          // RMB    opens context menus (if enabled) when clicked\n    int              OverrideMod;   // Ctrl   when held, all input is ignored; used to enable axis/plots as DND sources\n    int              ZoomMod;       // none   optional modifier that must be held for scroll wheel zooming\n    float            ZoomRate;      // 0.1f   zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click); make negative to invert\n    IMPLOT_API ImPlotInputMap();\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Callbacks\n//-----------------------------------------------------------------------------\n\n// Callback signature for axis tick label formatter.\ntypedef int (*ImPlotFormatter)(double value, char* buff, int size, void* user_data);\n\n// Callback signature for data getter.\ntypedef ImPlotPoint (*ImPlotGetter)(int idx, void* user_data);\n\n// Callback signature for axis transform.\ntypedef double (*ImPlotTransform)(double value, void* user_data);\n\nnamespace ImPlot {\n\n//-----------------------------------------------------------------------------\n// [SECTION] Contexts\n//-----------------------------------------------------------------------------\n\n// Creates a new ImPlot context. Call this after ImGui::CreateContext.\nIMPLOT_API ImPlotContext* CreateContext();\n// Destroys an ImPlot context. Call this before ImGui::DestroyContext. nullptr = destroy current context.\nIMPLOT_API void DestroyContext(ImPlotContext* ctx = nullptr);\n// Returns the current ImPlot context. nullptr if no context has ben set.\nIMPLOT_API ImPlotContext* GetCurrentContext();\n// Sets the current ImPlot context.\nIMPLOT_API void SetCurrentContext(ImPlotContext* ctx);\n\n// Sets the current **ImGui** context. This is ONLY necessary if you are compiling\n// ImPlot as a DLL (not recommended) separate from your ImGui compilation. It\n// sets the global variable GImGui, which is not shared across DLL boundaries.\n// See GImGui documentation in imgui.cpp for more details.\nIMPLOT_API void SetImGuiContext(ImGuiContext* ctx);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Begin/End Plot\n//-----------------------------------------------------------------------------\n\n// Starts a 2D plotting context. If this function returns true, EndPlot() MUST\n// be called! You are encouraged to use the following convention:\n//\n// if (BeginPlot(...)) {\n//     PlotLine(...);\n//     ...\n//     EndPlot();\n// }\n//\n// Important notes:\n//\n// - #title_id must be unique to the current ImGui ID scope. If you need to avoid ID\n//   collisions or don't want to display a title in the plot, use double hashes\n//   (e.g. \"MyPlot##HiddenIdText\" or \"##NoTitle\").\n// - #size is the **frame** size of the plot widget, not the plot area. The default\n//   size of plots (i.e. when ImVec2(0,0)) can be modified in your ImPlotStyle.\nIMPLOT_API bool BeginPlot(const char* title_id, const ImVec2& size=ImVec2(-1,0), ImPlotFlags flags=0);\n\n// Only call EndPlot() if BeginPlot() returns true! Typically called at the end\n// of an if statement conditioned on BeginPlot(). See example above.\nIMPLOT_API void EndPlot();\n\n//-----------------------------------------------------------------------------\n// [SECTION] Begin/End Subplots\n//-----------------------------------------------------------------------------\n\n// Starts a subdivided plotting context. If the function returns true,\n// EndSubplots() MUST be called! Call BeginPlot/EndPlot AT MOST [rows*cols]\n// times in  between the begining and end of the subplot context. Plots are\n// added in row major order.\n//\n// Example:\n//\n// if (BeginSubplots(\"My Subplot\",2,3,ImVec2(800,400)) {\n//     for (int i = 0; i < 6; ++i) {\n//         if (BeginPlot(...)) {\n//             ImPlot::PlotLine(...);\n//             ...\n//             EndPlot();\n//         }\n//     }\n//     EndSubplots();\n// }\n//\n// Produces:\n//\n// [0] | [1] | [2]\n// ----|-----|----\n// [3] | [4] | [5]\n//\n// Important notes:\n//\n// - #title_id must be unique to the current ImGui ID scope. If you need to avoid ID\n//   collisions or don't want to display a title in the plot, use double hashes\n//   (e.g. \"MySubplot##HiddenIdText\" or \"##NoTitle\").\n// - #rows and #cols must be greater than 0.\n// - #size is the size of the entire grid of subplots, not the individual plots\n// - #row_ratios and #col_ratios must have AT LEAST #rows and #cols elements,\n//   respectively. These are the sizes of the rows and columns expressed in ratios.\n//   If the user adjusts the dimensions, the arrays are updated with new ratios.\n//\n// Important notes regarding BeginPlot from inside of BeginSubplots:\n//\n// - The #title_id parameter of _BeginPlot_ (see above) does NOT have to be\n//   unique when called inside of a subplot context. Subplot IDs are hashed\n//   for your convenience so you don't have call PushID or generate unique title\n//   strings. Simply pass an empty string to BeginPlot unless you want to title\n//   each subplot.\n// - The #size parameter of _BeginPlot_ (see above) is ignored when inside of a\n//   subplot context. The actual size of the subplot will be based on the\n//   #size value you pass to _BeginSubplots_ and #row/#col_ratios if provided.\n\nIMPLOT_API bool BeginSubplots(const char* title_id,\n                             int rows,\n                             int cols,\n                             const ImVec2& size,\n                             ImPlotSubplotFlags flags = 0,\n                             float* row_ratios        = nullptr,\n                             float* col_ratios        = nullptr);\n\n// Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end\n// of an if statement conditioned on BeginSublots(). See example above.\nIMPLOT_API void EndSubplots();\n\n//-----------------------------------------------------------------------------\n// [SECTION] Setup\n//-----------------------------------------------------------------------------\n\n// The following API allows you to setup and customize various aspects of the\n// current plot. The functions should be called immediately after BeginPlot\n// and before any other API calls. Typical usage is as follows:\n\n// if (BeginPlot(...)) {                     1) begin a new plot\n//     SetupAxis(ImAxis_X1, \"My X-Axis\");    2) make Setup calls\n//     SetupAxis(ImAxis_Y1, \"My Y-Axis\");\n//     SetupLegend(ImPlotLocation_North);\n//     ...\n//     SetupFinish();                        3) [optional] explicitly finish setup\n//     PlotLine(...);                        4) plot items\n//     ...\n//     EndPlot();                            5) end the plot\n// }\n//\n// Important notes:\n//\n// - Always call Setup code at the top of your BeginPlot conditional statement.\n// - Setup is locked once you start plotting or explicitly call SetupFinish.\n//   Do NOT call Setup code after you begin plotting or after you make\n//   any non-Setup API calls (e.g. utils like PlotToPixels also lock Setup)\n// - Calling SetupFinish is OPTIONAL, but probably good practice. If you do not\n//   call it yourself, then the first subsequent plotting or utility function will\n//   call it for you.\n\n// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label.\nIMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0);\n// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.\nIMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);\n// Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot.\nIMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);\n// Sets the format of numeric axis labels via formater specifier (default=\"%g\"). Formated values will be double (i.e. use %f).\nIMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt);\n// Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data.\nIMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=nullptr);\n// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true.\nIMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);\n// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.\nIMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);\n// Sets an axis' scale using built-in options.\nIMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale);\n// Sets an axis' scale using user supplied forward and inverse transfroms.\nIMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=nullptr);\n// Sets an axis' limits constraints.\nIMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max);\n// Sets an axis' zoom constraints.\nIMPLOT_API void SetupAxisZoomConstraints(ImAxis axis, double z_min, double z_max);\n\n// Sets the label and/or flags for primary X and Y axes (shorthand for two calls to SetupAxis).\nIMPLOT_API void SetupAxes(const char* x_label, const char* y_label, ImPlotAxisFlags x_flags=0, ImPlotAxisFlags y_flags=0);\n// Sets the primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits).\nIMPLOT_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once);\n\n// Sets up the plot legend.\nIMPLOT_API void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags=0);\n// Set the location of the current plot's mouse position text (default = South|East).\nIMPLOT_API void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags=0);\n\n// Explicitly finalize plot setup. Once you call this, you cannot make anymore Setup calls for the current plot!\n// Note that calling this function is OPTIONAL; it will be called by the first subsequent setup-locking API call.\nIMPLOT_API void SetupFinish();\n\n//-----------------------------------------------------------------------------\n// [SECTION] SetNext\n//-----------------------------------------------------------------------------\n\n// Though you should default to the `Setup` API above, there are some scenarios\n// where (re)configuring a plot or axis before `BeginPlot` is needed (e.g. if\n// using a preceding button or slider widget to change the plot limits). In\n// this case, you can use the `SetNext` API below. While this is not as feature\n// rich as the Setup API, most common needs are provided. These functions can be\n// called anwhere except for inside of `Begin/EndPlot`. For example:\n\n// if (ImGui::Button(\"Center Plot\"))\n//     ImPlot::SetNextPlotLimits(-1,1,-1,1);\n// if (ImPlot::BeginPlot(...)) {\n//     ...\n//     ImPlot::EndPlot();\n// }\n//\n// Important notes:\n//\n// - You must still enable non-default axes with SetupAxis for these functions\n//   to work properly.\n\n// Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.\nIMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);\n// Links an upcoming axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot!\nIMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max);\n// Set an upcoming axis to auto fit to its data.\nIMPLOT_API void SetNextAxisToFit(ImAxis axis);\n\n// Sets the upcoming primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits).\nIMPLOT_API void SetNextAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once);\n// Sets all upcoming axes to auto fit to their data.\nIMPLOT_API void SetNextAxesToFit();\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot Items\n//-----------------------------------------------------------------------------\n\n// The main plotting API is provied below. Call these functions between\n// Begin/EndPlot and after any Setup API calls. Each plots data on the current\n// x and y axes, which can be changed with `SetAxis/Axes`.\n//\n// The templated functions are explicitly instantiated in implot_items.cpp.\n// They are not intended to be used generically with custom types. You will get\n// a linker error if you try! All functions support the following scalar types:\n//\n// float, double, ImS8, ImU8, ImS16, ImU16, ImS32, ImU32, ImS64, ImU64\n//\n//\n// If you need to plot custom or non-homogenous data you have a few options:\n//\n// 1. If your data is a simple struct/class (e.g. Vector2f), you can use striding.\n//    This is the most performant option if applicable.\n//\n//    struct Vector2f { float X, Y; };\n//    ...\n//    Vector2f data[42];\n//    ImPlot::PlotLine(\"line\", &data[0].x, &data[0].y, 42, 0, 0, sizeof(Vector2f));\n//\n// 2. Write a custom getter C function or C++ lambda and pass it and optionally your data to\n//    an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a slight performance\n//    cost, but probably not enough to worry about unless your data is very large. Examples:\n//\n//    ImPlotPoint MyDataGetter(void* data, int idx) {\n//        MyData* my_data = (MyData*)data;\n//        ImPlotPoint p;\n//        p.x = my_data->GetTime(idx);\n//        p.y = my_data->GetValue(idx);\n//        return p\n//    }\n//    ...\n//    auto my_lambda = [](int idx, void*) {\n//        double t = idx / 999.0;\n//        return ImPlotPoint(t, 0.5+0.5*std::sin(2*PI*10*t));\n//    };\n//    ...\n//    if (ImPlot::BeginPlot(\"MyPlot\")) {\n//        MyData my_data;\n//        ImPlot::PlotScatterG(\"scatter\", MyDataGetter, &my_data, my_data.Size());\n//        ImPlot::PlotLineG(\"line\", my_lambda, nullptr, 1000);\n//        ImPlot::EndPlot();\n//    }\n//\n// NB: All types are converted to double before plotting. You may lose information\n// if you try plotting extremely large 64-bit integral types. Proceed with caution!\n\n// Plots a standard 2D line plot.\nIMPLOT_TMP void PlotLine(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_API void PlotLineG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotLineFlags flags=0);\n\n// Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle.\nIMPLOT_TMP void PlotScatter(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotScatterFlags flags=0);\n\n// Plots a a stairstep graph. The y value is continued constantly to the right from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i]\nIMPLOT_TMP void PlotStairs(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotStairsFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_API void PlotStairsG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotStairsFlags flags=0);\n\n// Plots a shaded (filled) region between two lines, or a line and a horizontal reference. Set yref to +/-INFINITY for infinite fill extents.\nIMPLOT_TMP void PlotShaded(const char* label_id, const T* values, int count, double yref=0, double xscale=1, double xstart=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double yref=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_API void PlotShadedG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0);\n\n// Plots a bar graph. Vertical by default. #bar_size and #shift are in plot units.\nIMPLOT_TMP void PlotBars(const char* label_id, const T* values, int count, double bar_size=0.67, double shift=0, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_API void PlotBarsG(const char* label_id, ImPlotGetter getter, void* data, int count, double bar_size, ImPlotBarsFlags flags=0);\n\n// Plots a group of bars. #values is a row-major matrix with #item_count rows and #group_count cols. #label_ids should have #item_count elements.\nIMPLOT_TMP void PlotBarGroups(const char* const label_ids[], const T* values, int item_count, int group_count, double group_size=0.67, double shift=0, ImPlotBarGroupsFlags flags=0);\n\n// Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot.\nIMPLOT_TMP void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, ImPlotErrorBarsFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, ImPlotErrorBarsFlags flags=0, int offset=0, int stride=sizeof(T));\n\n// Plots stems. Vertical by default.\nIMPLOT_TMP void PlotStems(const char* label_id, const T* values, int count, double ref=0, double scale=1, double start=0, ImPlotStemsFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double ref=0, ImPlotStemsFlags flags=0, int offset=0, int stride=sizeof(T));\n\n// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).\nIMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));\n\n// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.\nIMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt=\"%.1f\", double angle0=90, ImPlotPieChartFlags flags=0);\n\n// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels.\nIMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt=\"%.1f\", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0);\n\n// Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range.\n// Otherwise, outlier values outside of the range are not binned. The largest bin count or density is returned.\nIMPLOT_TMP double PlotHistogram(const char* label_id, const T* values, int count, int bins=ImPlotBin_Sturges, double bar_scale=1.0, ImPlotRange range=ImPlotRange(), ImPlotHistogramFlags flags=0);\n\n// Plots two dimensional, bivariate histogram as a heatmap. #x_bins and #y_bins can be a positive integer or an ImPlotBin. If #range is left unspecified, the min/max of\n// #xs an #ys will be used as the ranges. Otherwise, outlier values outside of range are not binned. The largest bin count or density is returned.\nIMPLOT_TMP double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins=ImPlotBin_Sturges, int y_bins=ImPlotBin_Sturges, ImPlotRect range=ImPlotRect(), ImPlotHistogramFlags flags=0);\n\n// Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot.\nIMPLOT_TMP void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags=0, int offset=0, int stride=sizeof(T));\nIMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0);\n\n// Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down).\nIMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0);\n\n// Plots a centered text label at point x,y with an optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...).\nIMPLOT_API void PlotText(const char* text, double x, double y, const ImVec2& pix_offset=ImVec2(0,0), ImPlotTextFlags flags=0);\n\n// Plots a dummy item (i.e. adds a legend entry colored by ImPlotCol_Line)\nIMPLOT_API void PlotDummy(const char* label_id, ImPlotDummyFlags flags=0);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot Tools\n//-----------------------------------------------------------------------------\n\n// The following can be used to render interactive elements and/or annotations.\n// Like the item plotting functions above, they apply to the current x and y\n// axes, which can be changed with `SetAxis/SetAxes`.\n\n// Shows a draggable point at x,y. #col defaults to ImGuiCol_Text.\nIMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags=0);\n// Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text.\nIMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags=0);\n// Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text.\nIMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags=0);\n// Shows a draggable and resizeable rectangle.\nIMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags=0);\n\n// Shows an annotation callout at a chosen point. Clamping keeps annotations in the plot area. Annotations are always rendered on top.\nIMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, bool round = false);\nIMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, const char* fmt, ...)           IM_FMTARGS(6);\nIMPLOT_API void AnnotationV(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, const char* fmt, va_list args) IM_FMTLIST(6);\n\n// Shows a x-axis tag at the specified coordinate value.\nIMPLOT_API void TagX(double x, const ImVec4& col, bool round = false);\nIMPLOT_API void TagX(double x, const ImVec4& col, const char* fmt, ...)           IM_FMTARGS(3);\nIMPLOT_API void TagXV(double x, const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(3);\n\n// Shows a y-axis tag at the specified coordinate value.\nIMPLOT_API void TagY(double y, const ImVec4& col, bool round = false);\nIMPLOT_API void TagY(double y, const ImVec4& col, const char* fmt, ...)           IM_FMTARGS(3);\nIMPLOT_API void TagYV(double y, const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(3);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot Utils\n//-----------------------------------------------------------------------------\n\n// Select which axis/axes will be used for subsequent plot elements.\nIMPLOT_API void SetAxis(ImAxis axis);\nIMPLOT_API void SetAxes(ImAxis x_axis, ImAxis y_axis);\n\n// Convert pixels to a position in the current plot's coordinate system. Passing IMPLOT_AUTO uses the current axes.\nIMPLOT_API ImPlotPoint PixelsToPlot(const ImVec2& pix, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\nIMPLOT_API ImPlotPoint PixelsToPlot(float x, float y, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\n\n// Convert a position in the current plot's coordinate system to pixels. Passing IMPLOT_AUTO uses the current axes.\nIMPLOT_API ImVec2 PlotToPixels(const ImPlotPoint& plt, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\nIMPLOT_API ImVec2 PlotToPixels(double x, double y, ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\n\n// Get the current Plot position (top-left) in pixels.\nIMPLOT_API ImVec2 GetPlotPos();\n// Get the curent Plot size in pixels.\nIMPLOT_API ImVec2 GetPlotSize();\n\n// Returns the mouse position in x,y coordinates of the current plot. Passing IMPLOT_AUTO uses the current axes.\nIMPLOT_API ImPlotPoint GetPlotMousePos(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\n// Returns the current plot axis range.\nIMPLOT_API ImPlotRect GetPlotLimits(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\n\n// Returns true if the plot area in the current plot is hovered.\nIMPLOT_API bool IsPlotHovered();\n// Returns true if the axis label area in the current plot is hovered.\nIMPLOT_API bool IsAxisHovered(ImAxis axis);\n// Returns true if the bounding frame of a subplot is hovered.\nIMPLOT_API bool IsSubplotsHovered();\n\n// Returns true if the current plot is being box selected.\nIMPLOT_API bool IsPlotSelected();\n// Returns the current plot box selection bounds. Passing IMPLOT_AUTO uses the current axes.\nIMPLOT_API ImPlotRect GetPlotSelection(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = IMPLOT_AUTO);\n// Cancels a the current plot box selection.\nIMPLOT_API void CancelPlotSelection();\n\n// Hides or shows the next plot item (i.e. as if it were toggled from the legend).\n// Use ImPlotCond_Always if you need to forcefully set this every frame.\nIMPLOT_API void HideNextItem(bool hidden = true, ImPlotCond cond = ImPlotCond_Once);\n\n// Use the following around calls to Begin/EndPlot to align l/r/t/b padding.\n// Consider using Begin/EndSubplots first. They are more feature rich and\n// accomplish the same behaviour by default. The functions below offer lower\n// level control of plot alignment.\n\n// Align axis padding over multiple plots in a single row or column. #group_id must\n// be unique. If this function returns true, EndAlignedPlots() must be called.\nIMPLOT_API bool BeginAlignedPlots(const char* group_id, bool vertical = true);\n// Only call EndAlignedPlots() if BeginAlignedPlots() returns true!\nIMPLOT_API void EndAlignedPlots();\n\n//-----------------------------------------------------------------------------\n// [SECTION] Legend Utils\n//-----------------------------------------------------------------------------\n\n// Begin a popup for a legend entry.\nIMPLOT_API bool BeginLegendPopup(const char* label_id, ImGuiMouseButton mouse_button=1);\n// End a popup for a legend entry.\nIMPLOT_API void EndLegendPopup();\n// Returns true if a plot item legend entry is hovered.\nIMPLOT_API bool IsLegendEntryHovered(const char* label_id);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Drag and Drop\n//-----------------------------------------------------------------------------\n\n// Turns the current plot's plotting area into a drag and drop target. Don't forget to call EndDragDropTarget!\nIMPLOT_API bool BeginDragDropTargetPlot();\n// Turns the current plot's X-axis into a drag and drop target. Don't forget to call EndDragDropTarget!\nIMPLOT_API bool BeginDragDropTargetAxis(ImAxis axis);\n// Turns the current plot's legend into a drag and drop target. Don't forget to call EndDragDropTarget!\nIMPLOT_API bool BeginDragDropTargetLegend();\n// Ends a drag and drop target (currently just an alias for ImGui::EndDragDropTarget).\nIMPLOT_API void EndDragDropTarget();\n\n// NB: By default, plot and axes drag and drop *sources* require holding the Ctrl modifier to initiate the drag.\n// You can change the modifier if desired. If ImGuiMod_None is provided, the axes will be locked from panning.\n\n// Turns the current plot's plotting area into a drag and drop source. You must hold Ctrl. Don't forget to call EndDragDropSource!\nIMPLOT_API bool BeginDragDropSourcePlot(ImGuiDragDropFlags flags=0);\n// Turns the current plot's X-axis into a drag and drop source. You must hold Ctrl. Don't forget to call EndDragDropSource!\nIMPLOT_API bool BeginDragDropSourceAxis(ImAxis axis, ImGuiDragDropFlags flags=0);\n// Turns an item in the current plot's legend into drag and drop source. Don't forget to call EndDragDropSource!\nIMPLOT_API bool BeginDragDropSourceItem(const char* label_id, ImGuiDragDropFlags flags=0);\n// Ends a drag and drop source (currently just an alias for ImGui::EndDragDropSource).\nIMPLOT_API void EndDragDropSource();\n\n//-----------------------------------------------------------------------------\n// [SECTION] Styling\n//-----------------------------------------------------------------------------\n\n// Styling colors in ImPlot works similarly to styling colors in ImGui, but\n// with one important difference. Like ImGui, all style colors are stored in an\n// indexable array in ImPlotStyle. You can permanently modify these values through\n// GetStyle().Colors, or temporarily modify them with Push/Pop functions below.\n// However, by default all style colors in ImPlot default to a special color\n// IMPLOT_AUTO_COL. The behavior of this color depends upon the style color to\n// which it as applied:\n//\n//     1) For style colors associated with plot items (e.g. ImPlotCol_Line),\n//        IMPLOT_AUTO_COL tells ImPlot to color the item with the next unused\n//        color in the current colormap. Thus, every item will have a different\n//        color up to the number of colors in the colormap, at which point the\n//        colormap will roll over. For most use cases, you should not need to\n//        set these style colors to anything but IMPLOT_COL_AUTO; you are\n//        probably better off changing the current colormap. However, if you\n//        need to explicitly color a particular item you may either Push/Pop\n//        the style color around the item in question, or use the SetNextXXXStyle\n//        API below. If you permanently set one of these style colors to a specific\n//        color, or forget to call Pop, then all subsequent items will be styled\n//        with the color you set.\n//\n//     2) For style colors associated with plot styling (e.g. ImPlotCol_PlotBg),\n//        IMPLOT_AUTO_COL tells ImPlot to set that color from color data in your\n//        **ImGuiStyle**. The ImGuiCol_ that these style colors default to are\n//        detailed above, and in general have been mapped to produce plots visually\n//        consistent with your current ImGui style. Of course, you are free to\n//        manually set these colors to whatever you like, and further can Push/Pop\n//        them around individual plots for plot-specific styling (e.g. coloring axes).\n\n// Provides access to plot style structure for permanant modifications to colors, sizes, etc.\nIMPLOT_API ImPlotStyle& GetStyle();\n\n// Style plot colors for current ImGui style (default).\nIMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = nullptr);\n// Style plot colors for ImGui \"Classic\".\nIMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = nullptr);\n// Style plot colors for ImGui \"Dark\".\nIMPLOT_API void StyleColorsDark(ImPlotStyle* dst = nullptr);\n// Style plot colors for ImGui \"Light\".\nIMPLOT_API void StyleColorsLight(ImPlotStyle* dst = nullptr);\n\n// Use PushStyleX to temporarily modify your ImPlotStyle. The modification\n// will last until the matching call to PopStyleX. You MUST call a pop for\n// every push, otherwise you will leak memory! This behaves just like ImGui.\n\n// Temporarily modify a style color. Don't forget to call PopStyleColor!\nIMPLOT_API void PushStyleColor(ImPlotCol idx, ImU32 col);\nIMPLOT_API void PushStyleColor(ImPlotCol idx, const ImVec4& col);\n// Undo temporary style color modification(s). Undo multiple pushes at once by increasing count.\nIMPLOT_API void PopStyleColor(int count = 1);\n\n// Temporarily modify a style variable of float type. Don't forget to call PopStyleVar!\nIMPLOT_API void PushStyleVar(ImPlotStyleVar idx, float val);\n// Temporarily modify a style variable of int type. Don't forget to call PopStyleVar!\nIMPLOT_API void PushStyleVar(ImPlotStyleVar idx, int val);\n// Temporarily modify a style variable of ImVec2 type. Don't forget to call PopStyleVar!\nIMPLOT_API void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val);\n// Undo temporary style variable modification(s). Undo multiple pushes at once by increasing count.\nIMPLOT_API void PopStyleVar(int count = 1);\n\n// The following can be used to modify the style of the next plot item ONLY. They do\n// NOT require calls to PopStyleX. Leave style attributes you don't want modified to\n// IMPLOT_AUTO or IMPLOT_AUTO_COL. Automatic styles will be deduced from the current\n// values in your ImPlotStyle or from Colormap data.\n\n// Set the line color and weight for the next item only.\nIMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO);\n// Set the fill color for the next item only.\nIMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);\n// Set the marker style for the next item only.\nIMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL);\n// Set the error bar style for the next item only.\nIMPLOT_API void SetNextErrorBarStyle(const ImVec4& col = IMPLOT_AUTO_COL, float size = IMPLOT_AUTO, float weight = IMPLOT_AUTO);\n\n// Gets the last item primary color (i.e. its legend icon color)\nIMPLOT_API ImVec4 GetLastItemColor();\n\n// Returns the null terminated string name for an ImPlotCol.\nIMPLOT_API const char* GetStyleColorName(ImPlotCol idx);\n// Returns the null terminated string name for an ImPlotMarker.\nIMPLOT_API const char* GetMarkerName(ImPlotMarker idx);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Colormaps\n//-----------------------------------------------------------------------------\n\n// Item styling is based on colormaps when the relevant ImPlotCol_XXX is set to\n// IMPLOT_AUTO_COL (default). Several built-in colormaps are available. You can\n// add and then push/pop your own colormaps as well. To permanently set a colormap,\n// modify the Colormap index member of your ImPlotStyle.\n\n// Colormap data will be ignored and a custom color will be used if you have done one of the following:\n//     1) Modified an item style color in your ImPlotStyle to anything other than IMPLOT_AUTO_COL.\n//     2) Pushed an item style color using PushStyleColor().\n//     3) Set the next item style with a SetNextXXXStyle function.\n\n// Add a new colormap. The color data will be copied. The colormap can be used by pushing either the returned index or the\n// string name with PushColormap. The colormap name must be unique and the size must be greater than 1. You will receive\n// an assert otherwise! By default colormaps are considered to be qualitative (i.e. discrete). If you want to create a\n// continuous colormap, set #qual=false. This will treat the colors you provide as keys, and ImPlot will build a linearly\n// interpolated lookup table. The memory footprint of this table will be exactly ((size-1)*255+1)*4 bytes.\nIMPLOT_API ImPlotColormap AddColormap(const char* name, const ImVec4* cols, int size, bool qual=true);\nIMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32*  cols, int size, bool qual=true);\n\n// Returns the number of available colormaps (i.e. the built-in + user-added count).\nIMPLOT_API int GetColormapCount();\n// Returns a null terminated string name for a colormap given an index. Returns nullptr if index is invalid.\nIMPLOT_API const char* GetColormapName(ImPlotColormap cmap);\n// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid.\nIMPLOT_API ImPlotColormap GetColormapIndex(const char* name);\n\n// Temporarily switch to one of the built-in (i.e. ImPlotColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to call PopColormap!\nIMPLOT_API void PushColormap(ImPlotColormap cmap);\n// Push a colormap by string name. Use built-in names such as \"Default\", \"Deep\", \"Jet\", etc. or a string you provided to AddColormap. Don't forget to call PopColormap!\nIMPLOT_API void PushColormap(const char* name);\n// Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count.\nIMPLOT_API void PopColormap(int count = 1);\n\n// Returns the next color from the current colormap and advances the colormap for the current plot.\n// Can also be used with no return value to skip colors if desired. You need to call this between Begin/EndPlot!\nIMPLOT_API ImVec4 NextColormapColor();\n\n// Colormap utils. If cmap = IMPLOT_AUTO (default), the current colormap is assumed.\n// Pass an explicit colormap index (built-in or user-added) to specify otherwise.\n\n// Returns the size of a colormap.\nIMPLOT_API int GetColormapSize(ImPlotColormap cmap = IMPLOT_AUTO);\n// Returns a color from a colormap given an index >= 0 (modulo will be performed).\nIMPLOT_API ImVec4 GetColormapColor(int idx, ImPlotColormap cmap = IMPLOT_AUTO);\n// Sample a color from the current colormap given t between 0 and 1.\nIMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);\n\n// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. \"##NoLabel\"). If scale_min > scale_max, the scale to color mapping will be reversed.\nIMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = \"%g\", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO);\n// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].\nIMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = nullptr, const char* format = \"\", ImPlotColormap cmap = IMPLOT_AUTO);\n// Shows a button with a colormap gradient brackground.\nIMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);\n\n// When items in a plot sample their color from a colormap, the color is cached and does not change\n// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted,\n// item colors will NOT update. If you need item colors to resample the new colormap, then use this\n// function to bust the cached colors. If #plot_title_id is nullptr, then every item in EVERY existing plot\n// will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the\n// latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever\n// need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo).\nIMPLOT_API void BustColorCache(const char* plot_title_id = nullptr);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Input Mapping\n//-----------------------------------------------------------------------------\n\n// Provides access to input mapping structure for permanant modifications to controls for pan, select, etc.\nIMPLOT_API ImPlotInputMap& GetInputMap();\n\n// Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.\nIMPLOT_API void MapInputDefault(ImPlotInputMap* dst = nullptr);\n// Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.\nIMPLOT_API void MapInputReverse(ImPlotInputMap* dst = nullptr);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Miscellaneous\n//-----------------------------------------------------------------------------\n\n// Render icons similar to those that appear in legends (nifty for data lists).\nIMPLOT_API void ItemIcon(const ImVec4& col);\nIMPLOT_API void ItemIcon(ImU32 col);\nIMPLOT_API void ColormapIcon(ImPlotColormap cmap);\n\n// Get the plot draw list for custom rendering to the current plot area. Call between Begin/EndPlot.\nIMPLOT_API ImDrawList* GetPlotDrawList();\n// Push clip rect for rendering to current plot area. The rect can be expanded or contracted by #expand pixels. Call between Begin/EndPlot.\nIMPLOT_API void PushPlotClipRect(float expand=0);\n// Pop plot clip rect. Call between Begin/EndPlot.\nIMPLOT_API void PopPlotClipRect();\n\n// Shows ImPlot style selector dropdown menu.\nIMPLOT_API bool ShowStyleSelector(const char* label);\n// Shows ImPlot colormap selector dropdown menu.\nIMPLOT_API bool ShowColormapSelector(const char* label);\n// Shows ImPlot input map selector dropdown menu.\nIMPLOT_API bool ShowInputMapSelector(const char* label);\n// Shows ImPlot style editor block (not a window).\nIMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = nullptr);\n// Add basic help/info block for end users (not a window).\nIMPLOT_API void ShowUserGuide();\n// Shows ImPlot metrics/debug information window.\nIMPLOT_API void ShowMetricsWindow(bool* p_popen = nullptr);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Demo\n//-----------------------------------------------------------------------------\n\n// Shows the ImPlot demo window (add implot_demo.cpp to your sources!)\nIMPLOT_API void ShowDemoWindow(bool* p_open = nullptr);\n\n}  // namespace ImPlot\n\n//-----------------------------------------------------------------------------\n// [SECTION] Obsolete API\n//-----------------------------------------------------------------------------\n\n// The following functions will be removed! Keep your copy of implot up to date!\n// Occasionally set '#define IMPLOT_DISABLE_OBSOLETE_FUNCTIONS' to stay ahead.\n// If you absolutely must use these functions and do not want to receive compiler\n// warnings, set '#define IMPLOT_DISABLE_OBSOLETE_WARNINGS'.\n\n#ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS\n\n#ifndef IMPLOT_DISABLE_DEPRECATED_WARNINGS\n#if __cplusplus > 201402L\n#define IMPLOT_DEPRECATED(method) [[deprecated]] method\n#elif defined( __GNUC__ ) && !defined( __INTEL_COMPILER ) && ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) )\n#define IMPLOT_DEPRECATED(method) method __attribute__( ( deprecated ) )\n#elif defined( _MSC_VER )\n#define IMPLOT_DEPRECATED(method) __declspec(deprecated) method\n#else\n#define IMPLOT_DEPRECATED(method) method\n#endif\n#else\n#define IMPLOT_DEPRECATED(method) method\n#endif\n\nenum ImPlotFlagsObsolete_ {\n    ImPlotFlags_YAxis2 = 1 << 20,\n    ImPlotFlags_YAxis3 = 1 << 21,\n};\n\nnamespace ImPlot {\n\n// OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0\nIMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id,\n                                             const char* x_label,  // = nullptr,\n                                             const char* y_label,  // = nullptr,\n                                             const ImVec2& size       = ImVec2(-1,0),\n                                             ImPlotFlags flags        = ImPlotFlags_None,\n                                             ImPlotAxisFlags x_flags  = 0,\n                                             ImPlotAxisFlags y_flags  = 0,\n                                             ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault,\n                                             ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault,\n                                             const char* y2_label     = nullptr,\n                                             const char* y3_label     = nullptr) );\n\n} // namespace ImPlot\n\n#endif\n"
  },
  {
    "path": "Source/External/imgui_tools/implot/implot_demo.cpp",
    "content": "// MIT License\n\n// Copyright (c) 2022 Evan Pezent\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// ImPlot v0.14\n\n// We define this so that the demo does not accidentally use deprecated API\n#ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS\n#define IMPLOT_DISABLE_OBSOLETE_FUNCTIONS\n#endif\n\n#include \"implot.h\"\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#ifdef _MSC_VER\n#define sprintf sprintf_s\n#endif\n\n#ifndef PI\n#define PI 3.14159265358979323846\n#endif\n\n#define CHECKBOX_FLAG(flags, flag) ImGui::CheckboxFlags(#flag, (unsigned int*)&flags, flag)\n\n// Encapsulates examples for customizing ImPlot.\nnamespace MyImPlot {\n\n// Example for Custom Data and Getters section.\nstruct Vector2f {\n    Vector2f(float _x, float _y) { x = _x; y = _y; }\n    float x, y;\n};\n\n// Example for Custom Data and Getters section.\nstruct WaveData {\n    double X, Amp, Freq, Offset;\n    WaveData(double x, double amp, double freq, double offset) { X = x; Amp = amp; Freq = freq; Offset = offset; }\n};\nImPlotPoint SineWave(int idx, void* wave_data);\nImPlotPoint SawWave(int idx, void* wave_data);\nImPlotPoint Spiral(int idx, void* wave_data);\n\n// Example for Tables section.\nvoid Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size);\n\n// Example for Custom Plotters and Tooltips section.\nvoid PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip = true, float width_percent = 0.25f, ImVec4 bullCol = ImVec4(0,1,0,1), ImVec4 bearCol = ImVec4(1,0,0,1));\n\n// Example for Custom Styles section.\nvoid StyleSeaborn();\n\n} // namespace MyImPlot\n\nnamespace ImPlot {\n\ntemplate <typename T>\ninline T RandomRange(T min, T max) {\n    T scale = rand() / (T) RAND_MAX;\n    return min + scale * ( max - min );\n}\n\nImVec4 RandomColor() {\n    ImVec4 col;\n    col.x = RandomRange(0.0f,1.0f);\n    col.y = RandomRange(0.0f,1.0f);\n    col.z = RandomRange(0.0f,1.0f);\n    col.w = 1.0f;\n    return col;\n}\n\ndouble RandomGauss() {\n\tstatic double V1, V2, S;\n\tstatic int phase = 0;\n\tdouble X;\n\tif(phase == 0) {\n\t\tdo {\n\t\t\tdouble U1 = (double)rand() / RAND_MAX;\n\t\t\tdouble U2 = (double)rand() / RAND_MAX;\n\t\t\tV1 = 2 * U1 - 1;\n\t\t\tV2 = 2 * U2 - 1;\n\t\t\tS = V1 * V1 + V2 * V2;\n\t\t\t} while(S >= 1 || S == 0);\n\n\t\tX = V1 * sqrt(-2 * log(S) / S);\n\t} else\n\t\tX = V2 * sqrt(-2 * log(S) / S);\n\tphase = 1 - phase;\n\treturn X;\n}\n\ntemplate <int N>\nstruct NormalDistribution {\n    NormalDistribution(double mean, double sd) {\n        for (int i = 0; i < N; ++i)\n            Data[i] = RandomGauss()*sd + mean;\n    }\n    double Data[N];\n};\n\n// utility structure for realtime plot\nstruct ScrollingBuffer {\n    int MaxSize;\n    int Offset;\n    ImVector<ImVec2> Data;\n    ScrollingBuffer(int max_size = 2000) {\n        MaxSize = max_size;\n        Offset  = 0;\n        Data.reserve(MaxSize);\n    }\n    void AddPoint(float x, float y) {\n        if (Data.size() < MaxSize)\n            Data.push_back(ImVec2(x,y));\n        else {\n            Data[Offset] = ImVec2(x,y);\n            Offset =  (Offset + 1) % MaxSize;\n        }\n    }\n    void Erase() {\n        if (Data.size() > 0) {\n            Data.shrink(0);\n            Offset  = 0;\n        }\n    }\n};\n\n// utility structure for realtime plot\nstruct RollingBuffer {\n    float Span;\n    ImVector<ImVec2> Data;\n    RollingBuffer() {\n        Span = 10.0f;\n        Data.reserve(2000);\n    }\n    void AddPoint(float x, float y) {\n        float xmod = fmodf(x, Span);\n        if (!Data.empty() && xmod < Data.back().x)\n            Data.shrink(0);\n        Data.push_back(ImVec2(xmod, y));\n    }\n};\n\n// Huge data used by Time Formatting example (~500 MB allocation!)\nstruct HugeTimeData {\n    HugeTimeData(double min) {\n        Ts = new double[Size];\n        Ys = new double[Size];\n        for (int i = 0; i < Size; ++i) {\n            Ts[i] = min + i;\n            Ys[i] = GetY(Ts[i]);\n        }\n    }\n    ~HugeTimeData() { delete[] Ts;  delete[] Ys; }\n    static double GetY(double t) {\n        return 0.5 + 0.25 * sin(t/86400/12) +  0.005 * sin(t/3600);\n    }\n    double* Ts;\n    double* Ys;\n    static const int Size = 60*60*24*366;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Demo Functions\n//-----------------------------------------------------------------------------\n\nvoid Demo_Help() {\n    ImGui::Text(\"ABOUT THIS DEMO:\");\n    ImGui::BulletText(\"Sections below are demonstrating many aspects of the library.\");\n    ImGui::BulletText(\"The \\\"Tools\\\" menu above gives access to: Style Editors (ImPlot/ImGui)\\n\"\n                        \"and Metrics (general purpose Dear ImGui debugging tool).\");\n    ImGui::Separator();\n    ImGui::Text(\"PROGRAMMER GUIDE:\");\n    ImGui::BulletText(\"See the ShowDemoWindow() code in implot_demo.cpp. <- you are here!\");\n    ImGui::BulletText(\"If you see visual artifacts, do one of the following:\");\n    ImGui::Indent();\n    ImGui::BulletText(\"Handle ImGuiBackendFlags_RendererHasVtxOffset for 16-bit indices in your backend.\");\n    ImGui::BulletText(\"Or, enable 32-bit indices in imconfig.h.\");\n    ImGui::BulletText(\"Your current configuration is:\");\n    ImGui::Indent();\n    ImGui::BulletText(\"ImDrawIdx: %d-bit\", (int)(sizeof(ImDrawIdx) * 8));\n    ImGui::BulletText(\"ImGuiBackendFlags_RendererHasVtxOffset: %s\", (ImGui::GetIO().BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) ? \"True\" : \"False\");\n    ImGui::Unindent();\n    ImGui::Unindent();\n    ImGui::Separator();\n    ImGui::Text(\"USER GUIDE:\");\n    ShowUserGuide();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid ButtonSelector(const char* label, ImGuiMouseButton* b) {\n    ImGui::PushID(label);\n    if (ImGui::RadioButton(\"LMB\",*b == ImGuiMouseButton_Left))\n        *b = ImGuiMouseButton_Left;\n    ImGui::SameLine();\n    if (ImGui::RadioButton(\"RMB\",*b == ImGuiMouseButton_Right))\n        *b = ImGuiMouseButton_Right;\n    ImGui::SameLine();\n    if (ImGui::RadioButton(\"MMB\",*b == ImGuiMouseButton_Middle))\n        *b = ImGuiMouseButton_Middle;\n    ImGui::PopID();\n}\n\nvoid ModSelector(const char* label, int* k) {\n    ImGui::PushID(label);\n    ImGui::CheckboxFlags(\"Ctrl\", (unsigned int*)k, ImGuiMod_Ctrl); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Shift\", (unsigned int*)k, ImGuiMod_Shift); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Alt\", (unsigned int*)k, ImGuiMod_Alt); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Super\", (unsigned int*)k, ImGuiMod_Super);\n    ImGui::PopID();\n}\n\nvoid InputMapping(const char* label, ImGuiMouseButton* b, int* k) {\n    ImGui::LabelText(\"##\",\"%s\",label);\n    if (b != nullptr) {\n        ImGui::SameLine(100);\n        ButtonSelector(label,b);\n    }\n    if (k != nullptr) {\n        ImGui::SameLine(300);\n        ModSelector(label,k);\n    }\n}\n\nvoid ShowInputMapping() {\n    ImPlotInputMap& map = ImPlot::GetInputMap();\n    InputMapping(\"Pan\",&map.Pan,&map.PanMod);\n    InputMapping(\"Fit\",&map.Fit,nullptr);\n    InputMapping(\"Select\",&map.Select,&map.SelectMod);\n    InputMapping(\"SelectHorzMod\",nullptr,&map.SelectHorzMod);\n    InputMapping(\"SelectVertMod\",nullptr,&map.SelectVertMod);\n    InputMapping(\"SelectCancel\",&map.SelectCancel,nullptr);\n    InputMapping(\"Menu\",&map.Menu,nullptr);\n    InputMapping(\"OverrideMod\",nullptr,&map.OverrideMod);\n    InputMapping(\"ZoomMod\",nullptr,&map.ZoomMod);\n    ImGui::SliderFloat(\"ZoomRate\",&map.ZoomRate,-1,1);\n}\n\nvoid Demo_Config() {\n    ImGui::ShowFontSelector(\"Font\");\n    ImGui::ShowStyleSelector(\"ImGui Style\");\n    ImPlot::ShowStyleSelector(\"ImPlot Style\");\n    ImPlot::ShowColormapSelector(\"ImPlot Colormap\");\n    ImPlot::ShowInputMapSelector(\"Input Map\");\n    ImGui::Separator();\n    ImGui::Checkbox(\"Use Local Time\", &ImPlot::GetStyle().UseLocalTime);\n    ImGui::Checkbox(\"Use ISO 8601\", &ImPlot::GetStyle().UseISO8601);\n    ImGui::Checkbox(\"Use 24 Hour Clock\", &ImPlot::GetStyle().Use24HourClock);\n    ImGui::Separator();\n    if (ImPlot::BeginPlot(\"Preview\")) {\n        static double now = (double)time(nullptr);\n        ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);\n        ImPlot::SetupAxisLimits(ImAxis_X1, now, now + 24*3600);\n        for (int i = 0; i < 10; ++i) {\n            double x[2] = {now, now + 24*3600};\n            double y[2] = {0,i/9.0};\n            ImGui::PushID(i);\n            ImPlot::PlotLine(\"##Line\",x,y,2);\n            ImGui::PopID();\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_LinePlots() {\n    static float xs1[1001], ys1[1001];\n    for (int i = 0; i < 1001; ++i) {\n        xs1[i] = i * 0.001f;\n        ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + (float)ImGui::GetTime() / 10));\n    }\n    static double xs2[20], ys2[20];\n    for (int i = 0; i < 20; ++i) {\n        xs2[i] = i * 1/19.0f;\n        ys2[i] = xs2[i] * xs2[i];\n    }\n    if (ImPlot::BeginPlot(\"Line Plots\")) {\n        ImPlot::SetupAxes(\"x\",\"y\");\n        ImPlot::PlotLine(\"f(x)\", xs1, ys1, 1001);\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);\n        ImPlot::PlotLine(\"g(x)\", xs2, ys2, 20,ImPlotLineFlags_Segments);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_FilledLinePlots() {\n    static double xs1[101], ys1[101], ys2[101], ys3[101];\n    srand(0);\n    for (int i = 0; i < 101; ++i) {\n        xs1[i] = (float)i;\n        ys1[i] = RandomRange(400.0,450.0);\n        ys2[i] = RandomRange(275.0,350.0);\n        ys3[i] = RandomRange(150.0,225.0);\n    }\n    static bool show_lines = true;\n    static bool show_fills = true;\n    static float fill_ref = 0;\n    static int shade_mode = 0;\n    static ImPlotShadedFlags flags = 0;\n    ImGui::Checkbox(\"Lines\",&show_lines); ImGui::SameLine();\n    ImGui::Checkbox(\"Fills\",&show_fills);\n    if (show_fills) {\n        ImGui::SameLine();\n        if (ImGui::RadioButton(\"To -INF\",shade_mode == 0))\n            shade_mode = 0;\n        ImGui::SameLine();\n        if (ImGui::RadioButton(\"To +INF\",shade_mode == 1))\n            shade_mode = 1;\n        ImGui::SameLine();\n        if (ImGui::RadioButton(\"To Ref\",shade_mode == 2))\n            shade_mode = 2;\n        if (shade_mode == 2) {\n            ImGui::SameLine();\n            ImGui::SetNextItemWidth(100);\n            ImGui::DragFloat(\"##Ref\",&fill_ref, 1, -100, 500);\n        }\n    }\n\n    if (ImPlot::BeginPlot(\"Stock Prices\")) {\n        ImPlot::SetupAxes(\"Days\",\"Price\");\n        ImPlot::SetupAxesLimits(0,100,0,500);\n        if (show_fills) {\n            ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);\n            ImPlot::PlotShaded(\"Stock 1\", xs1, ys1, 101, shade_mode == 0 ? -INFINITY : shade_mode == 1 ? INFINITY : fill_ref, flags);\n            ImPlot::PlotShaded(\"Stock 2\", xs1, ys2, 101, shade_mode == 0 ? -INFINITY : shade_mode == 1 ? INFINITY : fill_ref, flags);\n            ImPlot::PlotShaded(\"Stock 3\", xs1, ys3, 101, shade_mode == 0 ? -INFINITY : shade_mode == 1 ? INFINITY : fill_ref, flags);\n            ImPlot::PopStyleVar();\n        }\n        if (show_lines) {\n            ImPlot::PlotLine(\"Stock 1\", xs1, ys1, 101);\n            ImPlot::PlotLine(\"Stock 2\", xs1, ys2, 101);\n            ImPlot::PlotLine(\"Stock 3\", xs1, ys3, 101);\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_ShadedPlots() {\n    static float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001];\n    srand(0);\n    for (int i = 0; i < 1001; ++i) {\n        xs[i]  = i * 0.001f;\n        ys[i]  = 0.25f + 0.25f * sinf(25 * xs[i]) * sinf(5 * xs[i]) + RandomRange(-0.01f, 0.01f);\n        ys1[i] = ys[i] + RandomRange(0.1f, 0.12f);\n        ys2[i] = ys[i] - RandomRange(0.1f, 0.12f);\n        ys3[i] = 0.75f + 0.2f * sinf(25 * xs[i]);\n        ys4[i] = 0.75f + 0.1f * cosf(25 * xs[i]);\n    }\n    static float alpha = 0.25f;\n    ImGui::DragFloat(\"Alpha\",&alpha,0.01f,0,1);\n\n    if (ImPlot::BeginPlot(\"Shaded Plots\")) {\n        ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha);\n        ImPlot::PlotShaded(\"Uncertain Data\",xs,ys1,ys2,1001);\n        ImPlot::PlotLine(\"Uncertain Data\", xs, ys, 1001);\n        ImPlot::PlotShaded(\"Overlapping\",xs,ys3,ys4,1001);\n        ImPlot::PlotLine(\"Overlapping\",xs,ys3,1001);\n        ImPlot::PlotLine(\"Overlapping\",xs,ys4,1001);\n        ImPlot::PopStyleVar();\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_ScatterPlots() {\n    srand(0);\n    static float xs1[100], ys1[100];\n    for (int i = 0; i < 100; ++i) {\n        xs1[i] = i * 0.01f;\n        ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX);\n    }\n    static float xs2[50], ys2[50];\n    for (int i = 0; i < 50; i++) {\n        xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX);\n        ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX);\n    }\n\n    if (ImPlot::BeginPlot(\"Scatter Plot\")) {\n        ImPlot::PlotScatter(\"Data 1\", xs1, ys1, 100);\n        ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6, ImPlot::GetColormapColor(1), IMPLOT_AUTO, ImPlot::GetColormapColor(1));\n        ImPlot::PlotScatter(\"Data 2\", xs2, ys2, 50);\n        ImPlot::PopStyleVar();\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_StairstepPlots() {\n    static float ys1[21], ys2[21];\n    for (int i = 0; i < 21; ++i) {\n        ys1[i] = 0.75f + 0.2f * sinf(10 * i * 0.05f);\n        ys2[i] = 0.25f + 0.2f * sinf(10 * i * 0.05f);\n    }\n    static ImPlotStairsFlags flags = 0;\n    CHECKBOX_FLAG(flags, ImPlotStairsFlags_Shaded);\n    if (ImPlot::BeginPlot(\"Stairstep Plot\")) {\n        ImPlot::SetupAxes(\"x\",\"f(x)\");\n        ImPlot::SetupAxesLimits(0,1,0,1);\n\n        ImPlot::PushStyleColor(ImPlotCol_Line, ImVec4(0.5f,0.5f,0.5f,1.0f));\n        ImPlot::PlotLine(\"##1\",ys1,21,0.05f);\n        ImPlot::PlotLine(\"##2\",ys2,21,0.05f);\n        ImPlot::PopStyleColor();\n\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);\n        ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL, 0.25f);\n        ImPlot::PlotStairs(\"Post Step (default)\", ys1, 21, 0.05f, 0, flags);\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);\n        ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL, 0.25f);\n        ImPlot::PlotStairs(\"Pre Step\", ys2, 21, 0.05f, 0, flags|ImPlotStairsFlags_PreStep);\n\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_BarPlots() {\n    static ImS8  data[10] = {1,2,3,4,5,6,7,8,9,10};\n    if (ImPlot::BeginPlot(\"Bar Plot\")) {\n        ImPlot::PlotBars(\"Vertical\",data,10,0.7,1);\n        ImPlot::PlotBars(\"Horizontal\",data,10,0.4,1,ImPlotBarsFlags_Horizontal);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_BarGroups() {\n    static ImS8  data[30] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90,  // midterm\n                             80, 62, 56, 99, 55, 78, 88, 78, 90, 100, // final\n                             80, 69, 52, 92, 72, 78, 75, 76, 89, 95}; // course\n\n    static const char*  ilabels[]   = {\"Midterm Exam\",\"Final Exam\",\"Course Grade\"};\n    static const char*  glabels[]   = {\"S1\",\"S2\",\"S3\",\"S4\",\"S5\",\"S6\",\"S7\",\"S8\",\"S9\",\"S10\"};\n    static const double positions[] = {0,1,2,3,4,5,6,7,8,9};\n\n    static int items  = 3;\n    static int groups = 10;\n    static float size = 0.67f;\n\n    static ImPlotBarGroupsFlags flags = 0;\n    static bool horz = false;\n\n    ImGui::CheckboxFlags(\"Stacked\", (unsigned int*)&flags, ImPlotBarGroupsFlags_Stacked);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"Horizontal\",&horz);\n\n    ImGui::SliderInt(\"Items\",&items,1,3);\n    ImGui::SliderFloat(\"Size\",&size,0,1);\n\n    if (ImPlot::BeginPlot(\"Bar Group\")) {\n        ImPlot::SetupLegend(ImPlotLocation_East, ImPlotLegendFlags_Outside);\n        if (horz) {\n            ImPlot::SetupAxes(\"Score\",\"Student\",ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit);\n            ImPlot::SetupAxisTicks(ImAxis_Y1,positions, groups, glabels);\n            ImPlot::PlotBarGroups(ilabels,data,items,groups,size,0,flags|ImPlotBarGroupsFlags_Horizontal);\n        }\n        else {\n            ImPlot::SetupAxes(\"Student\",\"Score\",ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit);\n            ImPlot::SetupAxisTicks(ImAxis_X1,positions, groups, glabels);\n            ImPlot::PlotBarGroups(ilabels,data,items,groups,size,0,flags);\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_BarStacks() {\n\n    static ImPlotColormap Liars = -1;\n    if (Liars == -1) {\n        static const ImU32 Liars_Data[6] = { 4282515870, 4282609140, 4287357182, 4294630301, 4294945280, 4294921472 };\n        Liars = ImPlot::AddColormap(\"Liars\", Liars_Data, 6);\n    }\n\n    static bool diverging = true;\n    ImGui::Checkbox(\"Diverging\",&diverging);\n\n    static const char* politicians[] = {\"Trump\",\"Bachman\",\"Cruz\",\"Gingrich\",\"Palin\",\"Santorum\",\"Walker\",\"Perry\",\"Ryan\",\"McCain\",\"Rubio\",\"Romney\",\"Rand Paul\",\"Christie\",\"Biden\",\"Kasich\",\"Sanders\",\"J Bush\",\"H Clinton\",\"Obama\"};\n    static int data_reg[] = {18,26,7,14,10,8,6,11,4,4,3,8,6,8,6,5,0,3,1,2,                // Pants on Fire\n                             43,36,30,21,30,27,25,17,11,22,15,16,16,17,12,12,14,6,13,12,  // False\n                             16,13,28,22,15,21,15,18,30,17,24,18,13,10,14,15,17,22,14,12, // Mostly False\n                             17,10,13,25,12,22,19,26,23,17,22,27,20,26,29,17,18,22,21,27, // Half True\n                             5,7,16,10,10,12,23,13,17,20,22,16,23,19,20,26,36,29,27,26,   // Mostly True\n                             1,8,6,8,23,10,12,15,15,20,14,15,22,20,19,25,15,18,24,21};    // True\n    static const char* labels_reg[] = {\"Pants on Fire\",\"False\",\"Mostly False\",\"Half True\",\"Mostly True\",\"True\"};\n\n\n    static int data_div[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                                         // Pants on Fire (dummy, to order legend logically)\n                             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                                         // False         (dummy, to order legend logically)\n                             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                                         // Mostly False  (dummy, to order legend logically)\n                             -16,-13,-28,-22,-15,-21,-15,-18,-30,-17,-24,-18,-13,-10,-14,-15,-17,-22,-14,-12, // Mostly False\n                             -43,-36,-30,-21,-30,-27,-25,-17,-11,-22,-15,-16,-16,-17,-12,-12,-14,-6,-13,-12,  // False\n                             -18,-26,-7,-14,-10,-8,-6,-11,-4,-4,-3,-8,-6,-8,-6,-5,0,-3,-1,-2,                 // Pants on Fire\n                             17,10,13,25,12,22,19,26,23,17,22,27,20,26,29,17,18,22,21,27,                     // Half True\n                             5,7,16,10,10,12,23,13,17,20,22,16,23,19,20,26,36,29,27,26,                       // Mostly True\n                             1,8,6,8,23,10,12,15,15,20,14,15,22,20,19,25,15,18,24,21};                        // True\n    static const char* labels_div[] = {\"Pants on Fire\",\"False\",\"Mostly False\",\"Mostly False\",\"False\",\"Pants on Fire\",\"Half True\",\"Mostly True\",\"True\"};\n\n    ImPlot::PushColormap(Liars);\n    if (ImPlot::BeginPlot(\"PolitiFact: Who Lies More?\",ImVec2(-1,400),ImPlotFlags_NoMouseText)) {\n        ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Outside|ImPlotLegendFlags_Horizontal);\n        ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Invert);\n        ImPlot::SetupAxisTicks(ImAxis_Y1,0,19,20,politicians,false);\n        if (diverging)\n            ImPlot::PlotBarGroups(labels_div,data_div,9,20,0.75,0,ImPlotBarGroupsFlags_Stacked|ImPlotBarGroupsFlags_Horizontal);\n        else\n            ImPlot::PlotBarGroups(labels_reg,data_reg,6,20,0.75,0,ImPlotBarGroupsFlags_Stacked|ImPlotBarGroupsFlags_Horizontal);\n        ImPlot::EndPlot();\n    }\n    ImPlot::PopColormap();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_ErrorBars() {\n    static float xs[5]    = {1,2,3,4,5};\n    static float bar[5]   = {1,2,5,3,4};\n    static float lin1[5]  = {8,8,9,7,8};\n    static float lin2[5]  = {6,7,6,9,6};\n    static float err1[5]  = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f};\n    static float err2[5]  = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f};\n    static float err3[5]  = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f};\n    static float err4[5]  = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f};\n\n\n    if (ImPlot::BeginPlot(\"##ErrorBars\")) {\n        ImPlot::SetupAxesLimits(0, 6, 0, 10);\n        ImPlot::PlotBars(\"Bar\", xs, bar, 5, 0.5f);\n        ImPlot::PlotErrorBars(\"Bar\", xs, bar, err1, 5);\n        ImPlot::SetNextErrorBarStyle(ImPlot::GetColormapColor(1), 0);\n        ImPlot::PlotErrorBars(\"Line\", xs, lin1, err1, err2, 5);\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Square);\n        ImPlot::PlotLine(\"Line\", xs, lin1, 5);\n        ImPlot::PushStyleColor(ImPlotCol_ErrorBar, ImPlot::GetColormapColor(2));\n        ImPlot::PlotErrorBars(\"Scatter\", xs, lin2, err2, 5);\n        ImPlot::PlotErrorBars(\"Scatter\", xs, lin2,  err3, err4, 5, ImPlotErrorBarsFlags_Horizontal);\n        ImPlot::PopStyleColor();\n        ImPlot::PlotScatter(\"Scatter\", xs, lin2, 5);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_StemPlots() {\n    static double xs[51], ys1[51], ys2[51];\n    for (int i = 0; i < 51; ++i) {\n        xs[i] = i * 0.02;\n        ys1[i] = 1.0 + 0.5 * sin(25*xs[i])*cos(2*xs[i]);\n        ys2[i] = 0.5 + 0.25  * sin(10*xs[i]) * sin(xs[i]);\n    }\n    if (ImPlot::BeginPlot(\"Stem Plots\")) {\n        ImPlot::SetupAxisLimits(ImAxis_X1,0,1.0);\n        ImPlot::SetupAxisLimits(ImAxis_Y1,0,1.6);\n        ImPlot::PlotStems(\"Stems 1\",xs,ys1,51);\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);\n        ImPlot::PlotStems(\"Stems 2\", xs, ys2,51);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_InfiniteLines() {\n    static double vals[] = {0.25, 0.5, 0.75};\n    if (ImPlot::BeginPlot(\"##Infinite\")) {\n        ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoInitialFit,ImPlotAxisFlags_NoInitialFit);\n        ImPlot::PlotInfLines(\"Vertical\",vals,3);\n        ImPlot::PlotInfLines(\"Horizontal\",vals,3,ImPlotInfLinesFlags_Horizontal);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_PieCharts() {\n    static const char* labels1[]    = {\"Frogs\",\"Hogs\",\"Dogs\",\"Logs\"};\n    static float data1[]            = {0.15f,  0.30f,  0.2f, 0.05f};\n    static ImPlotPieChartFlags flags = 0;\n    ImGui::SetNextItemWidth(250);\n    ImGui::DragFloat4(\"Values\", data1, 0.01f, 0, 1);\n    if ((data1[0] + data1[1] + data1[2] + data1[3]) < 1) {\n        ImGui::SameLine();\n        CHECKBOX_FLAG(flags,ImPlotPieChartFlags_Normalize);\n    }\n\n    if (ImPlot::BeginPlot(\"##Pie1\", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {\n        ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);\n        ImPlot::SetupAxesLimits(0, 1, 0, 1);\n        ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, \"%.2f\", 90, flags);\n        ImPlot::EndPlot();\n    }\n\n    ImGui::SameLine();\n\n    static const char* labels2[]   = {\"A\",\"B\",\"C\",\"D\",\"E\"};\n    static int data2[]             = {1,1,2,3,5};\n\n    ImPlot::PushColormap(ImPlotColormap_Pastel);\n    if (ImPlot::BeginPlot(\"##Pie2\", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {\n        ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);\n        ImPlot::SetupAxesLimits(0, 1, 0, 1);\n        ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, \"%.0f\", 180, flags);\n        ImPlot::EndPlot();\n    }\n    ImPlot::PopColormap();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Heatmaps() {\n    static float values1[7][7]  = {{0.8f, 2.4f, 2.5f, 3.9f, 0.0f, 4.0f, 0.0f},\n                                    {2.4f, 0.0f, 4.0f, 1.0f, 2.7f, 0.0f, 0.0f},\n                                    {1.1f, 2.4f, 0.8f, 4.3f, 1.9f, 4.4f, 0.0f},\n                                    {0.6f, 0.0f, 0.3f, 0.0f, 3.1f, 0.0f, 0.0f},\n                                    {0.7f, 1.7f, 0.6f, 2.6f, 2.2f, 6.2f, 0.0f},\n                                    {1.3f, 1.2f, 0.0f, 0.0f, 0.0f, 3.2f, 5.1f},\n                                    {0.1f, 2.0f, 0.0f, 1.4f, 0.0f, 1.9f, 6.3f}};\n    static float scale_min       = 0;\n    static float scale_max       = 6.3f;\n    static const char* xlabels[] = {\"C1\",\"C2\",\"C3\",\"C4\",\"C5\",\"C6\",\"C7\"};\n    static const char* ylabels[] = {\"R1\",\"R2\",\"R3\",\"R4\",\"R5\",\"R6\",\"R7\"};\n\n    static ImPlotColormap map = ImPlotColormap_Viridis;\n    if (ImPlot::ColormapButton(ImPlot::GetColormapName(map),ImVec2(225,0),map)) {\n        map = (map + 1) % ImPlot::GetColormapCount();\n        // We bust the color cache of our plots so that item colors will\n        // resample the new colormap in the event that they have already\n        // been created. See documentation in implot.h.\n        BustColorCache(\"##Heatmap1\");\n        BustColorCache(\"##Heatmap2\");\n    }\n\n    ImGui::SameLine();\n    ImGui::LabelText(\"##Colormap Index\", \"%s\", \"Change Colormap\");\n    ImGui::SetNextItemWidth(225);\n    ImGui::DragFloatRange2(\"Min / Max\",&scale_min, &scale_max, 0.01f, -20, 20);\n\n    static ImPlotHeatmapFlags hm_flags = 0;\n\n    ImGui::CheckboxFlags(\"Column Major\", (unsigned int*)&hm_flags, ImPlotHeatmapFlags_ColMajor);\n\n    static ImPlotAxisFlags axes_flags = ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoTickMarks;\n\n    ImPlot::PushColormap(map);\n\n    if (ImPlot::BeginPlot(\"##Heatmap1\",ImVec2(225,225),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) {\n        ImPlot::SetupAxes(nullptr, nullptr, axes_flags, axes_flags);\n        ImPlot::SetupAxisTicks(ImAxis_X1,0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels);\n        ImPlot::SetupAxisTicks(ImAxis_Y1,1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels);\n        ImPlot::PlotHeatmap(\"heat\",values1[0],7,7,scale_min,scale_max,\"%g\",ImPlotPoint(0,0),ImPlotPoint(1,1),hm_flags);\n        ImPlot::EndPlot();\n    }\n    ImGui::SameLine();\n    ImPlot::ColormapScale(\"##HeatScale\",scale_min, scale_max, ImVec2(60,225));\n\n    ImGui::SameLine();\n\n    const int size = 80;\n    static double values2[size*size];\n    srand((unsigned int)(ImGui::GetTime()*1000000));\n    for (int i = 0; i < size*size; ++i)\n        values2[i] = RandomRange(0.0,1.0);\n\n    if (ImPlot::BeginPlot(\"##Heatmap2\",ImVec2(225,225))) {\n        ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);\n        ImPlot::SetupAxesLimits(-1,1,-1,1);\n        ImPlot::PlotHeatmap(\"heat1\",values2,size,size,0,1,nullptr);\n        ImPlot::PlotHeatmap(\"heat2\",values2,size,size,0,1,nullptr, ImPlotPoint(-1,-1), ImPlotPoint(0,0));\n        ImPlot::EndPlot();\n    }\n    ImPlot::PopColormap();\n\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Histogram() {\n    static ImPlotHistogramFlags hist_flags = ImPlotHistogramFlags_Density;\n    static int  bins       = 50;\n    static double mu       = 5;\n    static double sigma    = 2;\n    ImGui::SetNextItemWidth(200);\n    if (ImGui::RadioButton(\"Sqrt\",bins==ImPlotBin_Sqrt))       { bins = ImPlotBin_Sqrt;    } ImGui::SameLine();\n    if (ImGui::RadioButton(\"Sturges\",bins==ImPlotBin_Sturges)) { bins = ImPlotBin_Sturges; } ImGui::SameLine();\n    if (ImGui::RadioButton(\"Rice\",bins==ImPlotBin_Rice))       { bins = ImPlotBin_Rice;    } ImGui::SameLine();\n    if (ImGui::RadioButton(\"Scott\",bins==ImPlotBin_Scott))     { bins = ImPlotBin_Scott;   } ImGui::SameLine();\n    if (ImGui::RadioButton(\"N Bins\",bins>=0))                  { bins = 50;                }\n    if (bins>=0) {\n        ImGui::SameLine();\n        ImGui::SetNextItemWidth(200);\n        ImGui::SliderInt(\"##Bins\", &bins, 1, 100);\n    }\n    ImGui::CheckboxFlags(\"Horizontal\", (unsigned int*)&hist_flags, ImPlotHistogramFlags_Horizontal);\n    ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Density\", (unsigned int*)&hist_flags, ImPlotHistogramFlags_Density);\n    ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Cumulative\", (unsigned int*)&hist_flags, ImPlotHistogramFlags_Cumulative);\n\n    static bool range = false;\n    ImGui::Checkbox(\"Range\", &range);\n    static float rmin = -3;\n    static float rmax = 13;\n    if (range) {\n        ImGui::SameLine();\n        ImGui::SetNextItemWidth(200);\n        ImGui::DragFloat2(\"##Range\",&rmin,0.1f,-3,13);\n        ImGui::SameLine();\n        ImGui::CheckboxFlags(\"Exclude Outliers\", (unsigned int*)&hist_flags, ImPlotHistogramFlags_NoOutliers);\n    }\n    static NormalDistribution<10000> dist(mu, sigma);\n    static double x[100];\n    static double y[100];\n    if (hist_flags & ImPlotHistogramFlags_Density) {\n        for (int i = 0; i < 100; ++i) {\n            x[i] = -3 + 16 * (double)i/99.0;\n            y[i] = exp( - (x[i]-mu)*(x[i]-mu) / (2*sigma*sigma)) / (sigma * sqrt(2*3.141592653589793238));\n        }\n        if (hist_flags & ImPlotHistogramFlags_Cumulative) {\n            for (int i = 1; i < 100; ++i)\n                y[i] += y[i-1];\n            for (int i = 0; i < 100; ++i)\n                y[i] /= y[99];\n        }\n    }\n\n    if (ImPlot::BeginPlot(\"##Histograms\")) {\n        ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit);\n        ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f);\n        ImPlot::PlotHistogram(\"Empirical\", dist.Data, 10000, bins, 1.0, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), hist_flags);\n        if ((hist_flags & ImPlotHistogramFlags_Density) && !(hist_flags & ImPlotHistogramFlags_NoOutliers)) {\n            if (hist_flags & ImPlotHistogramFlags_Horizontal)\n                ImPlot::PlotLine(\"Theoretical\",y,x,100);\n            else\n                ImPlot::PlotLine(\"Theoretical\",x,y,100);\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Histogram2D() {\n    static int count     = 50000;\n    static int xybins[2] = {100,100};\n\n    static ImPlotHistogramFlags hist_flags = 0;\n\n    ImGui::SliderInt(\"Count\",&count,100,100000);\n    ImGui::SliderInt2(\"Bins\",xybins,1,500);\n    ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Density\", (unsigned int*)&hist_flags, ImPlotHistogramFlags_Density);\n\n    static NormalDistribution<100000> dist1(1, 2);\n    static NormalDistribution<100000> dist2(1, 1);\n    double max_count = 0;\n    ImPlotAxisFlags flags = ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Foreground;\n    ImPlot::PushColormap(\"Hot\");\n    if (ImPlot::BeginPlot(\"##Hist2D\",ImVec2(ImGui::GetContentRegionAvail().x-100-ImGui::GetStyle().ItemSpacing.x,0))) {\n        ImPlot::SetupAxes(nullptr, nullptr, flags, flags);\n        ImPlot::SetupAxesLimits(-6,6,-6,6);\n        max_count = ImPlot::PlotHistogram2D(\"Hist2D\",dist1.Data,dist2.Data,count,xybins[0],xybins[1],ImPlotRect(-6,6,-6,6), hist_flags);\n        ImPlot::EndPlot();\n    }\n    ImGui::SameLine();\n    ImPlot::ColormapScale(hist_flags & ImPlotHistogramFlags_Density ? \"Density\" : \"Count\",0,max_count,ImVec2(100,0));\n    ImPlot::PopColormap();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_DigitalPlots() {\n    ImGui::BulletText(\"Digital plots do not respond to Y drag and zoom, so that\");\n    ImGui::Indent();\n    ImGui::Text(\"you can drag analog plots over the rising/falling digital edge.\");\n    ImGui::Unindent();\n\n    static bool paused = false;\n    static ScrollingBuffer dataDigital[2];\n    static ScrollingBuffer dataAnalog[2];\n    static bool showDigital[2] = {true, false};\n    static bool showAnalog[2] = {true, false};\n\n    char label[32];\n    ImGui::Checkbox(\"digital_0\", &showDigital[0]); ImGui::SameLine();\n    ImGui::Checkbox(\"digital_1\", &showDigital[1]); ImGui::SameLine();\n    ImGui::Checkbox(\"analog_0\",  &showAnalog[0]);  ImGui::SameLine();\n    ImGui::Checkbox(\"analog_1\",  &showAnalog[1]);\n\n    static float t = 0;\n    if (!paused) {\n        t += ImGui::GetIO().DeltaTime;\n        //digital signal values\n        if (showDigital[0])\n            dataDigital[0].AddPoint(t, sinf(2*t) > 0.45);\n        if (showDigital[1])\n            dataDigital[1].AddPoint(t, sinf(2*t) < 0.45);\n        //Analog signal values\n        if (showAnalog[0])\n            dataAnalog[0].AddPoint(t, sinf(2*t));\n        if (showAnalog[1])\n            dataAnalog[1].AddPoint(t, cosf(2*t));\n    }\n    if (ImPlot::BeginPlot(\"##Digital\")) {\n        ImPlot::SetupAxisLimits(ImAxis_X1, t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always);\n        ImPlot::SetupAxisLimits(ImAxis_Y1, -1, 1);\n        for (int i = 0; i < 2; ++i) {\n            if (showDigital[i] && dataDigital[i].Data.size() > 0) {\n                snprintf(label, sizeof(label), \"digital_%d\", i);\n                ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), 0, dataDigital[i].Offset, 2 * sizeof(float));\n            }\n        }\n        for (int i = 0; i < 2; ++i) {\n            if (showAnalog[i]) {\n                snprintf(label, sizeof(label), \"analog_%d\", i);\n                if (dataAnalog[i].Data.size() > 0)\n                    ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), 0, dataAnalog[i].Offset, 2 * sizeof(float));\n            }\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Images() {\n    ImGui::BulletText(\"Below we are displaying the font texture, which is the only texture we have\\naccess to in this demo.\");\n    ImGui::BulletText(\"Use the 'ImTextureID' type as storage to pass pointers or identifiers to your\\nown texture data.\");\n    ImGui::BulletText(\"See ImGui Wiki page 'Image Loading and Displaying Examples'.\");\n    static ImVec2 bmin(0,0);\n    static ImVec2 bmax(1,1);\n    static ImVec2 uv0(0,0);\n    static ImVec2 uv1(1,1);\n    static ImVec4 tint(1,1,1,1);\n    ImGui::SliderFloat2(\"Min\", &bmin.x, -2, 2, \"%.1f\");\n    ImGui::SliderFloat2(\"Max\", &bmax.x, -2, 2, \"%.1f\");\n    ImGui::SliderFloat2(\"UV0\", &uv0.x, -2, 2, \"%.1f\");\n    ImGui::SliderFloat2(\"UV1\", &uv1.x, -2, 2, \"%.1f\");\n    ImGui::ColorEdit4(\"Tint\",&tint.x);\n    if (ImPlot::BeginPlot(\"##image\")) {\n        ImPlot::PlotImage(\"my image\",ImGui::GetIO().Fonts->TexID, bmin, bmax, uv0, uv1, tint);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_RealtimePlots() {\n    ImGui::BulletText(\"Move your mouse to change the data!\");\n    ImGui::BulletText(\"This example assumes 60 FPS. Higher FPS requires larger buffer size.\");\n    static ScrollingBuffer sdata1, sdata2;\n    static RollingBuffer   rdata1, rdata2;\n    ImVec2 mouse = ImGui::GetMousePos();\n    static float t = 0;\n    t += ImGui::GetIO().DeltaTime;\n    sdata1.AddPoint(t, mouse.x * 0.0005f);\n    rdata1.AddPoint(t, mouse.x * 0.0005f);\n    sdata2.AddPoint(t, mouse.y * 0.0005f);\n    rdata2.AddPoint(t, mouse.y * 0.0005f);\n\n    static float history = 10.0f;\n    ImGui::SliderFloat(\"History\",&history,1,30,\"%.1f s\");\n    rdata1.Span = history;\n    rdata2.Span = history;\n\n    static ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels;\n\n    if (ImPlot::BeginPlot(\"##Scrolling\", ImVec2(-1,150))) {\n        ImPlot::SetupAxes(nullptr, nullptr, flags, flags);\n        ImPlot::SetupAxisLimits(ImAxis_X1,t - history, t, ImGuiCond_Always);\n        ImPlot::SetupAxisLimits(ImAxis_Y1,0,1);\n        ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f);\n        ImPlot::PlotShaded(\"Mouse X\", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), -INFINITY, 0, sdata1.Offset, 2 * sizeof(float));\n        ImPlot::PlotLine(\"Mouse Y\", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), 0, sdata2.Offset, 2*sizeof(float));\n        ImPlot::EndPlot();\n    }\n    if (ImPlot::BeginPlot(\"##Rolling\", ImVec2(-1,150))) {\n        ImPlot::SetupAxes(nullptr, nullptr, flags, flags);\n        ImPlot::SetupAxisLimits(ImAxis_X1,0,history, ImGuiCond_Always);\n        ImPlot::SetupAxisLimits(ImAxis_Y1,0,1);\n        ImPlot::PlotLine(\"Mouse X\", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 0, 2 * sizeof(float));\n        ImPlot::PlotLine(\"Mouse Y\", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 0, 2 * sizeof(float));\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_MarkersAndText() {\n    static float mk_size = ImPlot::GetStyle().MarkerSize;\n    static float mk_weight = ImPlot::GetStyle().MarkerWeight;\n    ImGui::DragFloat(\"Marker Size\",&mk_size,0.1f,2.0f,10.0f,\"%.2f px\");\n    ImGui::DragFloat(\"Marker Weight\", &mk_weight,0.05f,0.5f,3.0f,\"%.2f px\");\n\n    if (ImPlot::BeginPlot(\"##MarkerStyles\", ImVec2(-1,0), ImPlotFlags_CanvasOnly)) {\n\n        ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);\n        ImPlot::SetupAxesLimits(0, 10, 0, 12);\n\n        ImS8 xs[2] = {1,4};\n        ImS8 ys[2] = {10,11};\n\n        // filled markers\n        for (int m = 0; m < ImPlotMarker_COUNT; ++m) {\n            ImGui::PushID(m);\n            ImPlot::SetNextMarkerStyle(m, mk_size, IMPLOT_AUTO_COL, mk_weight);\n            ImPlot::PlotLine(\"##Filled\", xs, ys, 2);\n            ImGui::PopID();\n            ys[0]--; ys[1]--;\n        }\n        xs[0] = 6; xs[1] = 9; ys[0] = 10; ys[1] = 11;\n        // open markers\n        for (int m = 0; m < ImPlotMarker_COUNT; ++m) {\n            ImGui::PushID(m);\n            ImPlot::SetNextMarkerStyle(m, mk_size, ImVec4(0,0,0,0), mk_weight);\n            ImPlot::PlotLine(\"##Open\", xs, ys, 2);\n            ImGui::PopID();\n            ys[0]--; ys[1]--;\n        }\n\n        ImPlot::PlotText(\"Filled Markers\", 2.5f, 6.0f);\n        ImPlot::PlotText(\"Open Markers\",   7.5f, 6.0f);\n\n        ImPlot::PushStyleColor(ImPlotCol_InlayText, ImVec4(1,0,1,1));\n        ImPlot::PlotText(\"Vertical Text\", 5.0f, 6.0f, ImVec2(0,0), ImPlotTextFlags_Vertical);\n        ImPlot::PopStyleColor();\n\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_NaNValues() {\n\n    static bool include_nan = true;\n    static ImPlotLineFlags flags = 0;\n\n    float data1[5] = {0.0f,0.25f,0.5f,0.75f,1.0f};\n    float data2[5] = {0.0f,0.25f,0.5f,0.75f,1.0f};\n\n    if (include_nan)\n        data1[2] = NAN;\n\n    ImGui::Checkbox(\"Include NaN\",&include_nan);\n    ImGui::SameLine();\n    ImGui::CheckboxFlags(\"Skip NaN\", (unsigned int*)&flags, ImPlotLineFlags_SkipNaN);\n\n    if (ImPlot::BeginPlot(\"##NaNValues\")) {\n        ImPlot::SetNextMarkerStyle(ImPlotMarker_Square);\n        ImPlot::PlotLine(\"line\", data1, data2, 5, flags);\n        ImPlot::PlotBars(\"bars\", data1, 5);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_LogScale() {\n    static double xs[1001], ys1[1001], ys2[1001], ys3[1001];\n    for (int i = 0; i < 1001; ++i) {\n        xs[i]  = i*0.1f;\n        ys1[i] = sin(xs[i]) + 1;\n        ys2[i] = log(xs[i]);\n        ys3[i] = pow(10.0, xs[i]);\n    }\n    if (ImPlot::BeginPlot(\"Log Plot\", ImVec2(-1,0))) {\n        ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Log10);\n        ImPlot::SetupAxesLimits(0.1, 100, 0, 10);\n        ImPlot::PlotLine(\"f(x) = x\",        xs, xs,  1001);\n        ImPlot::PlotLine(\"f(x) = sin(x)+1\", xs, ys1, 1001);\n        ImPlot::PlotLine(\"f(x) = log(x)\",   xs, ys2, 1001);\n        ImPlot::PlotLine(\"f(x) = 10^x\",     xs, ys3, 21);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_SymmetricLogScale() {\n    static double xs[1001], ys1[1001], ys2[1001];\n    for (int i = 0; i < 1001; ++i) {\n        xs[i]  = i*0.1f-50;\n        ys1[i] = sin(xs[i]);\n        ys2[i] = i*0.002 - 1;\n    }\n    if (ImPlot::BeginPlot(\"SymLog Plot\", ImVec2(-1,0))) {\n        ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_SymLog);\n        ImPlot::PlotLine(\"f(x) = a*x+b\",xs,ys2,1001);\n        ImPlot::PlotLine(\"f(x) = sin(x)\",xs,ys1,1001);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_TimeScale() {\n\n    static double t_min = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)\n    static double t_max = 1640995200; // 01/01/2022 @ 12:00:00am (UTC)\n\n    ImGui::BulletText(\"When ImPlotAxisFlags_Time is enabled on the X-Axis, values are interpreted as\\n\"\n                        \"UNIX timestamps in seconds and axis labels are formated as date/time.\");\n    ImGui::BulletText(\"By default, labels are in UTC time but can be set to use local time instead.\");\n\n    ImGui::Checkbox(\"Local Time\",&ImPlot::GetStyle().UseLocalTime);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"ISO 8601\",&ImPlot::GetStyle().UseISO8601);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"24 Hour Clock\",&ImPlot::GetStyle().Use24HourClock);\n\n    static HugeTimeData* data = nullptr;\n    if (data == nullptr) {\n        ImGui::SameLine();\n        if (ImGui::Button(\"Generate Huge Data (~500MB!)\")) {\n            static HugeTimeData sdata(t_min);\n            data = &sdata;\n        }\n    }\n\n    if (ImPlot::BeginPlot(\"##Time\", ImVec2(-1,0))) {\n        ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);\n        ImPlot::SetupAxesLimits(t_min,t_max,0,1);\n        if (data != nullptr) {\n            // downsample our data\n            int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1;\n            int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min);\n            start = start < 0 ? 0 : start > HugeTimeData::Size - 1 ? HugeTimeData::Size - 1 : start;\n            int end = (int)(ImPlot::GetPlotLimits().X.Max - t_min) + 1000;\n            end = end < 0 ? 0 : end > HugeTimeData::Size - 1 ? HugeTimeData::Size - 1 : end;\n            int size = (end - start)/downsample;\n            // plot it\n            ImPlot::PlotLine(\"Time Series\", &data->Ts[start], &data->Ys[start], size, 0, 0, sizeof(double)*downsample);\n        }\n        // plot time now\n        double t_now = (double)time(nullptr);\n        double y_now = HugeTimeData::GetY(t_now);\n        ImPlot::PlotScatter(\"Now\",&t_now,&y_now,1);\n        ImPlot::Annotation(t_now,y_now,ImPlot::GetLastItemColor(),ImVec2(10,10),false,\"Now\");\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nstatic inline double TransformForward_Sqrt(double v, void*) {\n    return sqrt(v);\n}\n\nstatic inline double TransformInverse_Sqrt(double v, void*) {\n    return v*v;\n}\n\nvoid Demo_CustomScale() {\n    static float v[100];\n    for (int i = 0; i < 100; ++i) {\n        v[i] = i*0.01f;\n    }\n    if (ImPlot::BeginPlot(\"Sqrt\")) {\n        ImPlot::SetupAxis(ImAxis_X1, \"Linear\");\n        ImPlot::SetupAxis(ImAxis_Y1, \"Sqrt\");\n        ImPlot::SetupAxisScale(ImAxis_Y1, TransformForward_Sqrt, TransformInverse_Sqrt);\n        ImPlot::SetupAxisLimitsConstraints(ImAxis_Y1, 0, INFINITY);\n        ImPlot::PlotLine(\"##data\",v,v,100);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_MultipleAxes() {\n    static float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001];\n    for (int i = 0; i < 1001; ++i) {\n        xs[i]  = (i*0.1f);\n        xs2[i] = xs[i] + 10.0f;\n        ys1[i] = sinf(xs[i]) * 3 + 1;\n        ys2[i] = cosf(xs[i]) * 0.2f + 0.5f;\n        ys3[i] = sinf(xs[i]+0.5f) * 100 + 200;\n    }\n\n    static bool x2_axis = true;\n    static bool y2_axis = true;\n    static bool y3_axis = true;\n\n    ImGui::Checkbox(\"X-Axis 2\", &x2_axis);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"Y-Axis 2\", &y2_axis);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"Y-Axis 3\", &y3_axis);\n\n    ImGui::BulletText(\"You can drag axes to the opposite side of the plot.\");\n    ImGui::BulletText(\"Hover over legend items to see which axis they are plotted on.\");\n\n    if (ImPlot::BeginPlot(\"Multi-Axis Plot\", ImVec2(-1,0))) {\n        ImPlot::SetupAxes(\"X-Axis 1\", \"Y-Axis 1\");\n        ImPlot::SetupAxesLimits(0, 100, 0, 10);\n        if (x2_axis) {\n            ImPlot::SetupAxis(ImAxis_X2, \"X-Axis 2\",ImPlotAxisFlags_AuxDefault);\n            ImPlot::SetupAxisLimits(ImAxis_X2, 0, 100);\n        }\n        if (y2_axis) {\n            ImPlot::SetupAxis(ImAxis_Y2, \"Y-Axis 2\",ImPlotAxisFlags_AuxDefault);\n            ImPlot::SetupAxisLimits(ImAxis_Y2, 0, 1);\n        }\n        if (y3_axis) {\n            ImPlot::SetupAxis(ImAxis_Y3, \"Y-Axis 3\",ImPlotAxisFlags_AuxDefault);\n            ImPlot::SetupAxisLimits(ImAxis_Y3, 0, 300);\n        }\n\n        ImPlot::PlotLine(\"f(x) = x\", xs, xs, 1001);\n        if (x2_axis) {\n            ImPlot::SetAxes(ImAxis_X2, ImAxis_Y1);\n            ImPlot::PlotLine(\"f(x) = sin(x)*3+1\", xs2, ys1, 1001);\n        }\n        if (y2_axis) {\n            ImPlot::SetAxes(ImAxis_X1, ImAxis_Y2);\n            ImPlot::PlotLine(\"f(x) = cos(x)*.2+.5\", xs, ys2, 1001);\n        }\n        if (y3_axis) {\n            ImPlot::SetAxes(ImAxis_X2, ImAxis_Y3);\n            ImPlot::PlotLine(\"f(x) = sin(x+.5)*100+200 \", xs2, ys3, 1001);\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_LinkedAxes() {\n    static ImPlotRect lims(0,1,0,1);\n    static bool linkx = true, linky = true;\n    int data[2] = {0,1};\n    ImGui::Checkbox(\"Link X\", &linkx);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"Link Y\", &linky);\n\n    ImGui::DragScalarN(\"Limits\",ImGuiDataType_Double,&lims.X.Min,4,0.01f);\n\n    if (BeginAlignedPlots(\"AlignedGroup\")) {\n        if (ImPlot::BeginPlot(\"Plot A\")) {\n            ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : nullptr, linkx ? &lims.X.Max : nullptr);\n            ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : nullptr, linky ? &lims.Y.Max : nullptr);\n            ImPlot::PlotLine(\"Line\",data,2);\n            ImPlot::EndPlot();\n        }\n        if (ImPlot::BeginPlot(\"Plot B\")) {\n            ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : nullptr, linkx ? &lims.X.Max : nullptr);\n            ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : nullptr, linky ? &lims.Y.Max : nullptr);\n            ImPlot::PlotLine(\"Line\",data,2);\n            ImPlot::EndPlot();\n        }\n        ImPlot::EndAlignedPlots();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_AxisConstraints() {\n    static float constraints[4] = {-10,10,1,20};\n    static ImPlotAxisFlags flags;\n    ImGui::DragFloat2(\"Limits Constraints\", &constraints[0], 0.01f);\n    ImGui::DragFloat2(\"Zoom Constraints\", &constraints[2], 0.01f);\n    CHECKBOX_FLAG(flags, ImPlotAxisFlags_PanStretch);\n    if (ImPlot::BeginPlot(\"##AxisConstraints\",ImVec2(-1,0))) {\n        ImPlot::SetupAxes(\"X\",\"Y\",flags,flags);\n        ImPlot::SetupAxesLimits(-1,1,-1,1);\n        ImPlot::SetupAxisLimitsConstraints(ImAxis_X1,constraints[0], constraints[1]);\n        ImPlot::SetupAxisZoomConstraints(ImAxis_X1,constraints[2], constraints[3]);\n        ImPlot::SetupAxisLimitsConstraints(ImAxis_Y1,constraints[0], constraints[1]);\n        ImPlot::SetupAxisZoomConstraints(ImAxis_Y1,constraints[2], constraints[3]);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_EqualAxes() {\n    ImGui::BulletText(\"Equal constraint applies to axis pairs (e.g ImAxis_X1/Y1, ImAxis_X2/Y2)\");\n    static double xs1[360], ys1[360];\n    for (int i = 0; i < 360; ++i) {\n        double angle = i * 2 * PI / 359.0;\n        xs1[i] = cos(angle); ys1[i] = sin(angle);\n    }\n    float xs2[] = {-1,0,1,0,-1};\n    float ys2[] = {0,1,0,-1,0};\n    if (ImPlot::BeginPlot(\"##EqualAxes\",ImVec2(-1,0),ImPlotFlags_Equal)) {\n        ImPlot::SetupAxis(ImAxis_X2, nullptr, ImPlotAxisFlags_AuxDefault);\n        ImPlot::SetupAxis(ImAxis_Y2, nullptr, ImPlotAxisFlags_AuxDefault);\n        ImPlot::PlotLine(\"Circle\",xs1,ys1,360);\n        ImPlot::SetAxes(ImAxis_X2, ImAxis_Y2);\n        ImPlot::PlotLine(\"Diamond\",xs2,ys2,5);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_AutoFittingData() {\n    ImGui::BulletText(\"The Y-axis has been configured to auto-fit to only the data visible in X-axis range.\");\n    ImGui::BulletText(\"Zoom and pan the X-axis. Disable Stems to see a difference in fit.\");\n    ImGui::BulletText(\"If ImPlotAxisFlags_RangeFit is disabled, the axis will fit ALL data.\");\n\n    static ImPlotAxisFlags xflags = ImPlotAxisFlags_None;\n    static ImPlotAxisFlags yflags = ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_RangeFit;\n\n    ImGui::TextUnformatted(\"X: \"); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"ImPlotAxisFlags_AutoFit##X\", (unsigned int*)&xflags, ImPlotAxisFlags_AutoFit); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"ImPlotAxisFlags_RangeFit##X\", (unsigned int*)&xflags, ImPlotAxisFlags_RangeFit);\n\n    ImGui::TextUnformatted(\"Y: \"); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"ImPlotAxisFlags_AutoFit##Y\", (unsigned int*)&yflags, ImPlotAxisFlags_AutoFit); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"ImPlotAxisFlags_RangeFit##Y\", (unsigned int*)&yflags, ImPlotAxisFlags_RangeFit);\n\n    static double data[101];\n    srand(0);\n    for (int i = 0; i < 101; ++i)\n        data[i] = 1 + sin(i/10.0f);\n\n    if (ImPlot::BeginPlot(\"##DataFitting\")) {\n        ImPlot::SetupAxes(\"X\",\"Y\",xflags,yflags);\n        ImPlot::PlotLine(\"Line\",data,101);\n        ImPlot::PlotStems(\"Stems\",data,101);\n        ImPlot::EndPlot();\n    };\n}\n\n//-----------------------------------------------------------------------------\n\nImPlotPoint SinewaveGetter(int i, void* data) {\n    float f = *(float*)data;\n    return ImPlotPoint(i,sinf(f*i));\n}\n\nvoid Demo_SubplotsSizing() {\n\n    static ImPlotSubplotFlags flags = ImPlotSubplotFlags_None;\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_NoResize\", (unsigned int*)&flags, ImPlotSubplotFlags_NoResize);\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_NoTitle\", (unsigned int*)&flags, ImPlotSubplotFlags_NoTitle);\n\n    static int rows = 3;\n    static int cols = 3;\n    ImGui::SliderInt(\"Rows\",&rows,1,5);\n    ImGui::SliderInt(\"Cols\",&cols,1,5);\n    static float rratios[] = {5,1,1,1,1,1};\n    static float cratios[] = {5,1,1,1,1,1};\n    ImGui::DragScalarN(\"Row Ratios\",ImGuiDataType_Float,rratios,rows,0.01f,nullptr);\n    ImGui::DragScalarN(\"Col Ratios\",ImGuiDataType_Float,cratios,cols,0.01f,nullptr);\n    if (ImPlot::BeginSubplots(\"My Subplots\", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) {\n        for (int i = 0; i < rows*cols; ++i) {\n            if (ImPlot::BeginPlot(\"\",ImVec2(),ImPlotFlags_NoLegend)) {\n                ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);\n                float fi = 0.01f * (i+1);\n                ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet));\n                ImPlot::PlotLineG(\"data\",SinewaveGetter,&fi,1000);\n                ImPlot::EndPlot();\n            }\n        }\n        ImPlot::EndSubplots();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_SubplotItemSharing() {\n    static ImPlotSubplotFlags flags = ImPlotSubplotFlags_ShareItems;\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_ShareItems\", (unsigned int*)&flags, ImPlotSubplotFlags_ShareItems);\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_ColMajor\", (unsigned int*)&flags, ImPlotSubplotFlags_ColMajor);\n    ImGui::BulletText(\"Drag and drop items from the legend onto plots (except for 'common')\");\n    static int rows = 2;\n    static int cols = 3;\n    static int id[] = {0,1,2,3,4,5};\n    static int curj = -1;\n    if (ImPlot::BeginSubplots(\"##ItemSharing\", rows, cols, ImVec2(-1,400), flags)) {\n        for (int i = 0; i < rows*cols; ++i) {\n            if (ImPlot::BeginPlot(\"\")) {\n                float fc = 0.01f;\n                ImPlot::PlotLineG(\"common\",SinewaveGetter,&fc,1000);\n                for (int j = 0; j < 6; ++j) {\n                    if (id[j] == i) {\n                        char label[8];\n                        float fj = 0.01f * (j+2);\n                        snprintf(label, sizeof(label), \"data%d\", j);\n                        ImPlot::PlotLineG(label,SinewaveGetter,&fj,1000);\n                        if (ImPlot::BeginDragDropSourceItem(label)) {\n                            curj = j;\n                            ImGui::SetDragDropPayload(\"MY_DND\",nullptr,0);\n                            ImPlot::ItemIcon(GetLastItemColor()); ImGui::SameLine();\n                            ImGui::TextUnformatted(label);\n                            ImPlot::EndDragDropSource();\n                        }\n                    }\n                }\n                if (ImPlot::BeginDragDropTargetPlot()) {\n                    if (ImGui::AcceptDragDropPayload(\"MY_DND\"))\n                        id[curj] = i;\n                    ImPlot::EndDragDropTarget();\n                }\n                ImPlot::EndPlot();\n            }\n        }\n        ImPlot::EndSubplots();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_SubplotAxisLinking() {\n    static ImPlotSubplotFlags flags = ImPlotSubplotFlags_LinkRows | ImPlotSubplotFlags_LinkCols;\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_LinkRows\", (unsigned int*)&flags, ImPlotSubplotFlags_LinkRows);\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_LinkCols\", (unsigned int*)&flags, ImPlotSubplotFlags_LinkCols);\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_LinkAllX\", (unsigned int*)&flags, ImPlotSubplotFlags_LinkAllX);\n    ImGui::CheckboxFlags(\"ImPlotSubplotFlags_LinkAllY\", (unsigned int*)&flags, ImPlotSubplotFlags_LinkAllY);\n\n    static int rows = 2;\n    static int cols = 2;\n    if (ImPlot::BeginSubplots(\"##AxisLinking\", rows, cols, ImVec2(-1,400), flags)) {\n        for (int i = 0; i < rows*cols; ++i) {\n            if (ImPlot::BeginPlot(\"\")) {\n                ImPlot::SetupAxesLimits(0,1000,-1,1);\n                float fc = 0.01f;\n                ImPlot::PlotLineG(\"common\",SinewaveGetter,&fc,1000);\n                ImPlot::EndPlot();\n            }\n        }\n        ImPlot::EndSubplots();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_LegendOptions() {\n    static ImPlotLocation loc = ImPlotLocation_East;\n    ImGui::CheckboxFlags(\"North\", (unsigned int*)&loc, ImPlotLocation_North); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"South\", (unsigned int*)&loc, ImPlotLocation_South); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"West\",  (unsigned int*)&loc, ImPlotLocation_West);  ImGui::SameLine();\n    ImGui::CheckboxFlags(\"East\",  (unsigned int*)&loc, ImPlotLocation_East);\n\n    static ImPlotLegendFlags flags = 0;\n\n    CHECKBOX_FLAG(flags, ImPlotLegendFlags_Horizontal);\n    CHECKBOX_FLAG(flags, ImPlotLegendFlags_Outside);\n    CHECKBOX_FLAG(flags, ImPlotLegendFlags_Sort);\n\n    ImGui::SliderFloat2(\"LegendPadding\", (float*)&GetStyle().LegendPadding, 0.0f, 20.0f, \"%.0f\");\n    ImGui::SliderFloat2(\"LegendInnerPadding\", (float*)&GetStyle().LegendInnerPadding, 0.0f, 10.0f, \"%.0f\");\n    ImGui::SliderFloat2(\"LegendSpacing\", (float*)&GetStyle().LegendSpacing, 0.0f, 5.0f, \"%.0f\");\n\n    if (ImPlot::BeginPlot(\"##Legend\",ImVec2(-1,0))) {\n        ImPlot::SetupLegend(loc, flags);\n        static MyImPlot::WaveData data1(0.001, 0.2, 4, 0.2);\n        static MyImPlot::WaveData data2(0.001, 0.2, 4, 0.4);\n        static MyImPlot::WaveData data3(0.001, 0.2, 4, 0.6);\n        static MyImPlot::WaveData data4(0.001, 0.2, 4, 0.8);\n        static MyImPlot::WaveData data5(0.001, 0.2, 4, 1.0);\n\n        ImPlot::PlotLineG(\"Item B\", MyImPlot::SawWave, &data1, 1000);         // \"Item B\" added to legend\n        ImPlot::PlotLineG(\"Item A##IDText\", MyImPlot::SawWave, &data2, 1000);  // \"Item A\" added to legend, text after ## used for ID only\n        ImPlot::PlotLineG(\"##NotListed\", MyImPlot::SawWave, &data3, 1000);     // plotted, but not added to legend\n        ImPlot::PlotLineG(\"Item C\", MyImPlot::SawWave, &data4, 1000);         // \"Item C\" added to legend\n        ImPlot::PlotLineG(\"Item C\", MyImPlot::SawWave,  &data5, 1000);         // combined with previous \"Item C\"\n\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_DragPoints() {\n    ImGui::BulletText(\"Click and drag each point.\");\n    static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;\n    ImGui::CheckboxFlags(\"NoCursors\", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"NoFit\", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"NoInput\", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);\n    ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks;\n    if (ImPlot::BeginPlot(\"##Bezier\",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) {\n        ImPlot::SetupAxes(nullptr,nullptr,ax_flags,ax_flags);\n        ImPlot::SetupAxesLimits(0,1,0,1);\n        static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4),  ImPlotPoint(0.8,0.6),  ImPlotPoint(.95f,.95f)};\n\n        ImPlot::DragPoint(0,&P[0].x,&P[0].y, ImVec4(0,0.9f,0,1),4,flags);\n        ImPlot::DragPoint(1,&P[1].x,&P[1].y, ImVec4(1,0.5f,1,1),4,flags);\n        ImPlot::DragPoint(2,&P[2].x,&P[2].y, ImVec4(0,0.5f,1,1),4,flags);\n        ImPlot::DragPoint(3,&P[3].x,&P[3].y, ImVec4(0,0.9f,0,1),4,flags);\n\n        static ImPlotPoint B[100];\n        for (int i = 0; i < 100; ++i) {\n            double t  = i / 99.0;\n            double u  = 1 - t;\n            double w1 = u*u*u;\n            double w2 = 3*u*u*t;\n            double w3 = 3*u*t*t;\n            double w4 = t*t*t;\n            B[i] = ImPlotPoint(w1*P[0].x + w2*P[1].x + w3*P[2].x + w4*P[3].x, w1*P[0].y + w2*P[1].y + w3*P[2].y + w4*P[3].y);\n        }\n\n\n        ImPlot::SetNextLineStyle(ImVec4(1,0.5f,1,1));\n        ImPlot::PlotLine(\"##h1\",&P[0].x, &P[0].y, 2, 0, 0, sizeof(ImPlotPoint));\n        ImPlot::SetNextLineStyle(ImVec4(0,0.5f,1,1));\n        ImPlot::PlotLine(\"##h2\",&P[2].x, &P[2].y, 2, 0, 0, sizeof(ImPlotPoint));\n        ImPlot::SetNextLineStyle(ImVec4(0,0.9f,0,1), 2);\n        ImPlot::PlotLine(\"##bez\",&B[0].x, &B[0].y, 100, 0, 0, sizeof(ImPlotPoint));\n\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_DragLines() {\n    ImGui::BulletText(\"Click and drag the horizontal and vertical lines.\");\n    static double x1 = 0.2;\n    static double x2 = 0.8;\n    static double y1 = 0.25;\n    static double y2 = 0.75;\n    static double f = 0.1;\n    static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;\n    ImGui::CheckboxFlags(\"NoCursors\", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"NoFit\", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"NoInput\", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);\n    if (ImPlot::BeginPlot(\"##lines\",ImVec2(-1,0))) {\n        ImPlot::SetupAxesLimits(0,1,0,1);\n        ImPlot::DragLineX(0,&x1,ImVec4(1,1,1,1),1,flags);\n        ImPlot::DragLineX(1,&x2,ImVec4(1,1,1,1),1,flags);\n        ImPlot::DragLineY(2,&y1,ImVec4(1,1,1,1),1,flags);\n        ImPlot::DragLineY(3,&y2,ImVec4(1,1,1,1),1,flags);\n        double xs[1000], ys[1000];\n        for (int i = 0; i < 1000; ++i) {\n            xs[i] = (x2+x1)/2+fabs(x2-x1)*(i/1000.0f - 0.5f);\n            ys[i] = (y1+y2)/2+fabs(y2-y1)/2*sin(f*i/10);\n        }\n        ImPlot::PlotLine(\"Interactive Data\", xs, ys, 1000);\n        ImPlot::DragLineY(120482,&f,ImVec4(1,0.5f,1,1),1,flags);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_DragRects() {\n\n    static float x_data[512];\n    static float y_data1[512];\n    static float y_data2[512];\n    static float y_data3[512];\n    static float sampling_freq = 44100;\n    static float freq = 500;\n    for (size_t i = 0; i < 512; ++i) {\n        const float t = i / sampling_freq;\n        x_data[i] = t;\n        const float arg = 2 * 3.14f * freq * t;\n        y_data1[i] = sinf(arg);\n        y_data2[i] = y_data1[i] * -0.6f + sinf(2 * arg) * 0.4f;\n        y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f;\n    }\n    ImGui::BulletText(\"Click and drag the edges, corners, and center of the rect.\");\n    static ImPlotRect rect(0.0025,0.0045,0,0.5);\n    static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;\n    ImGui::CheckboxFlags(\"NoCursors\", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"NoFit\", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();\n    ImGui::CheckboxFlags(\"NoInput\", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);\n\n    if (ImPlot::BeginPlot(\"##Main\",ImVec2(-1,150))) {\n        ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoTickLabels,ImPlotAxisFlags_NoTickLabels);\n        ImPlot::SetupAxesLimits(0,0.01,-1,1);\n        ImPlot::PlotLine(\"Signal 1\", x_data, y_data1, 512);\n        ImPlot::PlotLine(\"Signal 2\", x_data, y_data2, 512);\n        ImPlot::PlotLine(\"Signal 3\", x_data, y_data3, 512);\n        ImPlot::DragRect(0,&rect.X.Min,&rect.Y.Min,&rect.X.Max,&rect.Y.Max,ImVec4(1,0,1,1),flags);\n        ImPlot::EndPlot();\n    }\n    if (ImPlot::BeginPlot(\"##rect\",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) {\n        ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);\n        ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always);\n        ImPlot::PlotLine(\"Signal 1\", x_data, y_data1, 512);\n        ImPlot::PlotLine(\"Signal 2\", x_data, y_data2, 512);\n        ImPlot::PlotLine(\"Signal 3\", x_data, y_data3, 512);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nImPlotPoint FindCentroid(const ImVector<ImPlotPoint>& data, const ImPlotRect& bounds, int& cnt) {\n    cnt = 0;\n    ImPlotPoint avg;\n    ImPlotRect bounds_fixed;\n    bounds_fixed.X.Min = bounds.X.Min < bounds.X.Max ? bounds.X.Min : bounds.X.Max;\n    bounds_fixed.X.Max = bounds.X.Min < bounds.X.Max ? bounds.X.Max : bounds.X.Min;\n    bounds_fixed.Y.Min = bounds.Y.Min < bounds.Y.Max ? bounds.Y.Min : bounds.Y.Max;\n    bounds_fixed.Y.Max = bounds.Y.Min < bounds.Y.Max ? bounds.Y.Max : bounds.Y.Min;\n    for (int i = 0; i < data.size(); ++i) {\n        if (bounds_fixed.Contains(data[i].x, data[i].y)) {\n            avg.x += data[i].x;\n            avg.y += data[i].y;\n            cnt++;\n        }\n    }\n    if (cnt > 0) {\n        avg.x = avg.x / cnt;\n        avg.y = avg.y / cnt;\n    }\n    return avg;\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Querying() {\n    static ImVector<ImPlotPoint> data;\n    static ImVector<ImPlotRect> rects;\n    static ImPlotRect limits, select;\n    static bool init = true;\n    if (init) {\n        for (int i = 0; i < 50; ++i)\n        {\n            double x = RandomRange(0.1, 0.9);\n            double y = RandomRange(0.1, 0.9);\n            data.push_back(ImPlotPoint(x,y));\n        }\n        init = false;\n    }\n\n    ImGui::BulletText(\"Box select and left click mouse to create a new query rect.\");\n    ImGui::BulletText(\"Ctrl + click in the plot area to draw points.\");\n\n    if (ImGui::Button(\"Clear Queries\"))\n        rects.shrink(0);\n\n    if (ImPlot::BeginPlot(\"##Centroid\")) {\n        ImPlot::SetupAxesLimits(0,1,0,1);\n        if (ImPlot::IsPlotHovered() && ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyCtrl) {\n            ImPlotPoint pt = ImPlot::GetPlotMousePos();\n            data.push_back(pt);\n        }\n        ImPlot::PlotScatter(\"Points\", &data[0].x, &data[0].y, data.size(), 0, 0, 2 * sizeof(double));\n        if (ImPlot::IsPlotSelected()) {\n            select = ImPlot::GetPlotSelection();\n            int cnt;\n            ImPlotPoint centroid = FindCentroid(data,select,cnt);\n            if (cnt > 0) {\n                ImPlot::SetNextMarkerStyle(ImPlotMarker_Square,6);\n                ImPlot::PlotScatter(\"Centroid\", &centroid.x, &centroid.y, 1);\n            }\n            if (ImGui::IsMouseClicked(ImPlot::GetInputMap().SelectCancel)) {\n                CancelPlotSelection();\n                rects.push_back(select);\n            }\n        }\n        for (int i = 0; i < rects.size(); ++i) {\n            int cnt;\n            ImPlotPoint centroid = FindCentroid(data,rects[i],cnt);\n            if (cnt > 0) {\n                ImPlot::SetNextMarkerStyle(ImPlotMarker_Square,6);\n                ImPlot::PlotScatter(\"Centroid\", &centroid.x, &centroid.y, 1);\n            }\n            ImPlot::DragRect(i,&rects[i].X.Min,&rects[i].Y.Min,&rects[i].X.Max,&rects[i].Y.Max,ImVec4(1,0,1,1));\n        }\n        limits  = ImPlot::GetPlotLimits();\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Annotations() {\n    static bool clamp = false;\n    ImGui::Checkbox(\"Clamp\",&clamp);\n    if (ImPlot::BeginPlot(\"##Annotations\")) {\n        ImPlot::SetupAxesLimits(0,2,0,1);\n        static float p[] = {0.25f, 0.25f, 0.75f, 0.75f, 0.25f};\n        ImPlot::PlotScatter(\"##Points\",&p[0],&p[1],4);\n        ImVec4 col = GetLastItemColor();\n        ImPlot::Annotation(0.25,0.25,col,ImVec2(-15,15),clamp,\"BL\");\n        ImPlot::Annotation(0.75,0.25,col,ImVec2(15,15),clamp,\"BR\");\n        ImPlot::Annotation(0.75,0.75,col,ImVec2(15,-15),clamp,\"TR\");\n        ImPlot::Annotation(0.25,0.75,col,ImVec2(-15,-15),clamp,\"TL\");\n        ImPlot::Annotation(0.5,0.5,col,ImVec2(0,0),clamp,\"Center\");\n\n        ImPlot::Annotation(1.25,0.75,ImVec4(0,1,0,1),ImVec2(0,0),clamp);\n\n        float bx[] = {1.2f,1.5f,1.8f};\n        float by[] = {0.25f, 0.5f, 0.75f};\n        ImPlot::PlotBars(\"##Bars\",bx,by,3,0.2);\n        for (int i = 0; i < 3; ++i)\n            ImPlot::Annotation(bx[i],by[i],ImVec4(0,0,0,0),ImVec2(0,-5),clamp,\"B[%d]=%.2f\",i,by[i]);\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Tags() {\n    static bool show = true;\n    ImGui::Checkbox(\"Show Tags\",&show);\n    if (ImPlot::BeginPlot(\"##Tags\")) {\n        ImPlot::SetupAxis(ImAxis_X2);\n        ImPlot::SetupAxis(ImAxis_Y2);\n        if (show) {\n            ImPlot::TagX(0.25, ImVec4(1,1,0,1));\n            ImPlot::TagY(0.75, ImVec4(1,1,0,1));\n            static double drag_tag = 0.25;\n            ImPlot::DragLineY(0,&drag_tag,ImVec4(1,0,0,1),1,ImPlotDragToolFlags_NoFit);\n            ImPlot::TagY(drag_tag, ImVec4(1,0,0,1), \"Drag\");\n            SetAxes(ImAxis_X2, ImAxis_Y2);\n            ImPlot::TagX(0.5, ImVec4(0,1,1,1), \"%s\", \"MyTag\");\n            ImPlot::TagY(0.5, ImVec4(0,1,1,1), \"Tag: %d\", 42);\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_DragAndDrop() {\n    ImGui::BulletText(\"Drag/drop items from the left column.\");\n    ImGui::BulletText(\"Drag/drop items between plots.\");\n    ImGui::Indent();\n    ImGui::BulletText(\"Plot 1 Targets: Plot, Y-Axes, Legend\");\n    ImGui::BulletText(\"Plot 1 Sources: Legend Item Labels\");\n    ImGui::BulletText(\"Plot 2 Targets: Plot, X-Axis, Y-Axis\");\n    ImGui::BulletText(\"Plot 2 Sources: Plot, X-Axis, Y-Axis (hold Ctrl)\");\n    ImGui::Unindent();\n\n    // convenience struct to manage DND items; do this however you like\n    struct MyDndItem {\n        int              Idx;\n        int              Plt;\n        ImAxis           Yax;\n        char             Label[16];\n        ImVector<ImVec2> Data;\n        ImVec4           Color;\n        MyDndItem()        {\n            static int i = 0;\n            Idx = i++;\n            Plt = 0;\n            Yax = ImAxis_Y1;\n            snprintf(Label, sizeof(Label), \"%02d Hz\", Idx+1);\n            Color = RandomColor();\n            Data.reserve(1001);\n            for (int k = 0; k < 1001; ++k) {\n                float t = k * 1.0f / 999;\n                Data.push_back(ImVec2(t, 0.5f + 0.5f * sinf(2*3.14f*t*(Idx+1))));\n            }\n        }\n        void Reset() { Plt = 0; Yax = ImAxis_Y1; }\n    };\n\n    const int         k_dnd = 20;\n    static MyDndItem  dnd[k_dnd];\n    static MyDndItem* dndx = nullptr; // for plot 2\n    static MyDndItem* dndy = nullptr; // for plot 2\n\n    // child window to serve as initial source for our DND items\n    ImGui::BeginChild(\"DND_LEFT\",ImVec2(100,400));\n    if (ImGui::Button(\"Reset Data\")) {\n        for (int k = 0; k < k_dnd; ++k)\n            dnd[k].Reset();\n        dndx = dndy = nullptr;\n    }\n    for (int k = 0; k < k_dnd; ++k) {\n        if (dnd[k].Plt > 0)\n            continue;\n        ImPlot::ItemIcon(dnd[k].Color); ImGui::SameLine();\n        ImGui::Selectable(dnd[k].Label, false, 0, ImVec2(100, 0));\n        if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {\n            ImGui::SetDragDropPayload(\"MY_DND\", &k, sizeof(int));\n            ImPlot::ItemIcon(dnd[k].Color); ImGui::SameLine();\n            ImGui::TextUnformatted(dnd[k].Label);\n            ImGui::EndDragDropSource();\n        }\n    }\n    ImGui::EndChild();\n    if (ImGui::BeginDragDropTarget()) {\n        if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n            int i = *(int*)payload->Data; dnd[i].Reset();\n        }\n        ImGui::EndDragDropTarget();\n    }\n\n    ImGui::SameLine();\n    ImGui::BeginChild(\"DND_RIGHT\",ImVec2(-1,400));\n    // plot 1 (time series)\n    ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight;\n    if (ImPlot::BeginPlot(\"##DND1\", ImVec2(-1,195))) {\n        ImPlot::SetupAxis(ImAxis_X1, nullptr, flags|ImPlotAxisFlags_Lock);\n        ImPlot::SetupAxis(ImAxis_Y1, \"[drop here]\", flags);\n        ImPlot::SetupAxis(ImAxis_Y2, \"[drop here]\", flags|ImPlotAxisFlags_Opposite);\n        ImPlot::SetupAxis(ImAxis_Y3, \"[drop here]\", flags|ImPlotAxisFlags_Opposite);\n\n        for (int k = 0; k < k_dnd; ++k) {\n            if (dnd[k].Plt == 1 && dnd[k].Data.size() > 0) {\n                ImPlot::SetAxis(dnd[k].Yax);\n                ImPlot::SetNextLineStyle(dnd[k].Color);\n                ImPlot::PlotLine(dnd[k].Label, &dnd[k].Data[0].x, &dnd[k].Data[0].y, dnd[k].Data.size(), 0, 0, 2 * sizeof(float));\n                // allow legend item labels to be DND sources\n                if (ImPlot::BeginDragDropSourceItem(dnd[k].Label)) {\n                    ImGui::SetDragDropPayload(\"MY_DND\", &k, sizeof(int));\n                    ImPlot::ItemIcon(dnd[k].Color); ImGui::SameLine();\n                    ImGui::TextUnformatted(dnd[k].Label);\n                    ImPlot::EndDragDropSource();\n                }\n            }\n        }\n        // allow the main plot area to be a DND target\n        if (ImPlot::BeginDragDropTargetPlot()) {\n            if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n                int i = *(int*)payload->Data; dnd[i].Plt = 1; dnd[i].Yax = ImAxis_Y1;\n            }\n            ImPlot::EndDragDropTarget();\n        }\n        // allow each y-axis to be a DND target\n        for (int y = ImAxis_Y1; y <= ImAxis_Y3; ++y) {\n            if (ImPlot::BeginDragDropTargetAxis(y)) {\n                if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n                    int i = *(int*)payload->Data; dnd[i].Plt = 1; dnd[i].Yax = y;\n                }\n                ImPlot::EndDragDropTarget();\n            }\n        }\n        // allow the legend to be a DND target\n        if (ImPlot::BeginDragDropTargetLegend()) {\n            if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n                int i = *(int*)payload->Data; dnd[i].Plt = 1; dnd[i].Yax = ImAxis_Y1;\n            }\n            ImPlot::EndDragDropTarget();\n        }\n        ImPlot::EndPlot();\n    }\n    // plot 2 (Lissajous)\n    if (ImPlot::BeginPlot(\"##DND2\", ImVec2(-1,195))) {\n        ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndx != nullptr ? dndx->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]);\n        ImPlot::SetupAxis(ImAxis_X1, dndx == nullptr ? \"[drop here]\" : dndx->Label, flags);\n        ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndy != nullptr ? dndy->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]);\n        ImPlot::SetupAxis(ImAxis_Y1, dndy == nullptr ? \"[drop here]\" : dndy->Label, flags);\n        ImPlot::PopStyleColor(2);\n        if (dndx != nullptr && dndy != nullptr) {\n            ImVec4 mixed((dndx->Color.x + dndy->Color.x)/2,(dndx->Color.y + dndy->Color.y)/2,(dndx->Color.z + dndy->Color.z)/2,(dndx->Color.w + dndy->Color.w)/2);\n            ImPlot::SetNextLineStyle(mixed);\n            ImPlot::PlotLine(\"##dndxy\", &dndx->Data[0].y, &dndy->Data[0].y, dndx->Data.size(), 0, 0, 2 * sizeof(float));\n        }\n        // allow the x-axis to be a DND target\n        if (ImPlot::BeginDragDropTargetAxis(ImAxis_X1)) {\n            if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n                int i = *(int*)payload->Data; dndx = &dnd[i];\n            }\n            ImPlot::EndDragDropTarget();\n        }\n        // allow the x-axis to be a DND source\n        if (dndx != nullptr && ImPlot::BeginDragDropSourceAxis(ImAxis_X1)) {\n            ImGui::SetDragDropPayload(\"MY_DND\", &dndx->Idx, sizeof(int));\n            ImPlot::ItemIcon(dndx->Color); ImGui::SameLine();\n            ImGui::TextUnformatted(dndx->Label);\n            ImPlot::EndDragDropSource();\n        }\n        // allow the y-axis to be a DND target\n        if (ImPlot::BeginDragDropTargetAxis(ImAxis_Y1)) {\n            if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n                int i = *(int*)payload->Data; dndy = &dnd[i];\n            }\n            ImPlot::EndDragDropTarget();\n        }\n        // allow the y-axis to be a DND source\n        if (dndy != nullptr && ImPlot::BeginDragDropSourceAxis(ImAxis_Y1)) {\n            ImGui::SetDragDropPayload(\"MY_DND\", &dndy->Idx, sizeof(int));\n            ImPlot::ItemIcon(dndy->Color); ImGui::SameLine();\n            ImGui::TextUnformatted(dndy->Label);\n            ImPlot::EndDragDropSource();\n        }\n        // allow the plot area to be a DND target\n        if (ImPlot::BeginDragDropTargetPlot()) {\n            if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(\"MY_DND\")) {\n                int i = *(int*)payload->Data; dndx = dndy = &dnd[i];\n            }\n        }\n        // allow the plot area to be a DND source\n        if (ImPlot::BeginDragDropSourcePlot()) {\n            ImGui::TextUnformatted(\"Yes, you can\\ndrag this!\");\n            ImPlot::EndDragDropSource();\n        }\n        ImPlot::EndPlot();\n    }\n    ImGui::EndChild();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_Tables() {\n#ifdef IMGUI_HAS_TABLE\n    static ImGuiTableFlags flags = ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV |\n                                   ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable;\n    static bool anim = true;\n    static int offset = 0;\n    ImGui::BulletText(\"Plots can be used inside of ImGui tables as another means of creating subplots.\");\n    ImGui::Checkbox(\"Animate\",&anim);\n    if (anim)\n        offset = (offset + 1) % 100;\n    if (ImGui::BeginTable(\"##table\", 3, flags, ImVec2(-1,0))) {\n        ImGui::TableSetupColumn(\"Electrode\", ImGuiTableColumnFlags_WidthFixed, 75.0f);\n        ImGui::TableSetupColumn(\"Voltage\", ImGuiTableColumnFlags_WidthFixed, 75.0f);\n        ImGui::TableSetupColumn(\"EMG Signal\");\n        ImGui::TableHeadersRow();\n        ImPlot::PushColormap(ImPlotColormap_Cool);\n        for (int row = 0; row < 10; row++) {\n            ImGui::TableNextRow();\n            static float data[100];\n            srand(row);\n            for (int i = 0; i < 100; ++i)\n                data[i] = RandomRange(0.0f,10.0f);\n            ImGui::TableSetColumnIndex(0);\n            ImGui::Text(\"EMG %d\", row);\n            ImGui::TableSetColumnIndex(1);\n            ImGui::Text(\"%.3f V\", data[offset]);\n            ImGui::TableSetColumnIndex(2);\n            ImGui::PushID(row);\n            MyImPlot::Sparkline(\"##spark\",data,100,0,11.0f,offset,ImPlot::GetColormapColor(row),ImVec2(-1, 35));\n            ImGui::PopID();\n        }\n        ImPlot::PopColormap();\n        ImGui::EndTable();\n    }\n#else\n    ImGui::BulletText(\"You need to merge the ImGui 'tables' branch for this section.\");\n#endif\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_OffsetAndStride() {\n    static const int k_circles    = 11;\n    static const int k_points_per = 50;\n    static const int k_size       = 2 * k_points_per * k_circles;\n    static double interleaved_data[k_size];\n    for (int p = 0; p < k_points_per; ++p) {\n        for (int c = 0; c < k_circles; ++c) {\n            double r = (double)c / (k_circles - 1) * 0.2 + 0.2;\n            interleaved_data[p*2*k_circles + 2*c + 0] = 0.5 + r * cos((double)p/k_points_per * 6.28);\n            interleaved_data[p*2*k_circles + 2*c + 1] = 0.5 + r * sin((double)p/k_points_per * 6.28);\n        }\n    }\n    static int offset = 0;\n    ImGui::BulletText(\"Offsetting is useful for realtime plots (see above) and circular buffers.\");\n    ImGui::BulletText(\"Striding is useful for interleaved data (e.g. audio) or plotting structs.\");\n    ImGui::BulletText(\"Here, all circle data is stored in a single interleaved buffer:\");\n    ImGui::BulletText(\"[c0.x0 c0.y0 ... cn.x0 cn.y0 c0.x1 c0.y1 ... cn.x1 cn.y1 ... cn.xm cn.ym]\");\n    ImGui::BulletText(\"The offset value indicates which circle point index is considered the first.\");\n    ImGui::BulletText(\"Offsets can be negative and/or larger than the actual data count.\");\n    ImGui::SliderInt(\"Offset\", &offset, -2*k_points_per, 2*k_points_per);\n    if (ImPlot::BeginPlot(\"##strideoffset\",ImVec2(-1,0),ImPlotFlags_Equal)) {\n        ImPlot::PushColormap(ImPlotColormap_Jet);\n        char buff[32];\n        for (int c = 0; c < k_circles; ++c) {\n            snprintf(buff, sizeof(buff), \"Circle %d\", c);\n            ImPlot::PlotLine(buff, &interleaved_data[c*2 + 0], &interleaved_data[c*2 + 1], k_points_per, 0, offset, 2*k_circles*sizeof(double));\n        }\n        ImPlot::EndPlot();\n        ImPlot::PopColormap();\n    }\n    // offset++; uncomment for animation!\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_CustomDataAndGetters() {\n    ImGui::BulletText(\"You can plot custom structs using the stride feature.\");\n    ImGui::BulletText(\"Most plotters can also be passed a function pointer for getting data.\");\n    ImGui::Indent();\n        ImGui::BulletText(\"You can optionally pass user data to be given to your getter function.\");\n        ImGui::BulletText(\"C++ lambdas can be passed as function pointers as well!\");\n    ImGui::Unindent();\n\n    MyImPlot::Vector2f vec2_data[2] = { MyImPlot::Vector2f(0,0), MyImPlot::Vector2f(1,1) };\n\n    if (ImPlot::BeginPlot(\"##Custom Data\")) {\n\n        // custom structs using stride example:\n        ImPlot::PlotLine(\"Vector2f\", &vec2_data[0].x, &vec2_data[0].y, 2, 0, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */);\n\n        // custom getter example 1:\n        ImPlot::PlotLineG(\"Spiral\", MyImPlot::Spiral, nullptr, 1000);\n\n        // custom getter example 2:\n        static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75);\n        static MyImPlot::WaveData data2(0.001, 0.2, 4, 0.25);\n        ImPlot::PlotLineG(\"Waves\", MyImPlot::SineWave, &data1, 1000);\n        ImPlot::PlotLineG(\"Waves\", MyImPlot::SawWave, &data2, 1000);\n        ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);\n        ImPlot::PlotShadedG(\"Waves\", MyImPlot::SineWave, &data1, MyImPlot::SawWave, &data2, 1000);\n        ImPlot::PopStyleVar();\n\n        // you can also pass C++ lambdas:\n        // auto lamda = [](void* data, int idx) { ... return ImPlotPoint(x,y); };\n        // ImPlot::PlotLine(\"My Lambda\", lambda, data, 1000);\n\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nint MetricFormatter(double value, char* buff, int size, void* data) {\n    const char* unit = (const char*)data;\n    static double v[]      = {1000000000,1000000,1000,1,0.001,0.000001,0.000000001};\n    static const char* p[] = {\"G\",\"M\",\"k\",\"\",\"m\",\"u\",\"n\"};\n    if (value == 0) {\n        return snprintf(buff,size,\"0 %s\", unit);\n    }\n    for (int i = 0; i < 7; ++i) {\n        if (fabs(value) >= v[i]) {\n            return snprintf(buff,size,\"%g %s%s\",value/v[i],p[i],unit);\n        }\n    }\n    return snprintf(buff,size,\"%g %s%s\",value/v[6],p[6],unit);\n}\n\nvoid Demo_TickLabels()  {\n    static bool custom_fmt    = true;\n    static bool custom_ticks  = false;\n    static bool custom_labels = true;\n    ImGui::Checkbox(\"Show Custom Format\", &custom_fmt);\n    ImGui::SameLine();\n    ImGui::Checkbox(\"Show Custom Ticks\", &custom_ticks);\n    if (custom_ticks) {\n        ImGui::SameLine();\n        ImGui::Checkbox(\"Show Custom Labels\", &custom_labels);\n    }\n    const double pi = 3.14;\n    const char* pi_str[] = {\"PI\"};\n    static double yticks[] = {100,300,700,900};\n    static const char*  ylabels[] = {\"One\",\"Three\",\"Seven\",\"Nine\"};\n    static double yticks_aux[] = {0.2,0.4,0.6};\n    static const char* ylabels_aux[] = {\"A\",\"B\",\"C\",\"D\",\"E\",\"F\"};\n    if (ImPlot::BeginPlot(\"##Ticks\")) {\n        ImPlot::SetupAxesLimits(2.5,5,0,1000);\n        ImPlot::SetupAxis(ImAxis_Y2, nullptr, ImPlotAxisFlags_AuxDefault);\n        ImPlot::SetupAxis(ImAxis_Y3, nullptr, ImPlotAxisFlags_AuxDefault);\n        if (custom_fmt) {\n            ImPlot::SetupAxisFormat(ImAxis_X1, \"%g ms\");\n            ImPlot::SetupAxisFormat(ImAxis_Y1, MetricFormatter, (void*)\"Hz\");\n            ImPlot::SetupAxisFormat(ImAxis_Y2, \"%g dB\");\n            ImPlot::SetupAxisFormat(ImAxis_Y3, MetricFormatter, (void*)\"m\");\n        }\n        if (custom_ticks) {\n            ImPlot::SetupAxisTicks(ImAxis_X1, &pi,1,custom_labels ? pi_str : nullptr, true);\n            ImPlot::SetupAxisTicks(ImAxis_Y1, yticks, 4, custom_labels ? ylabels : nullptr, false);\n            ImPlot::SetupAxisTicks(ImAxis_Y2, yticks_aux, 3, custom_labels ? ylabels_aux : nullptr, false);\n            ImPlot::SetupAxisTicks(ImAxis_Y3, 0, 1, 6, custom_labels ? ylabels_aux : nullptr, false);\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_CustomStyles() {\n    ImPlot::PushColormap(ImPlotColormap_Deep);\n    // normally you wouldn't change the entire style each frame\n    ImPlotStyle backup = ImPlot::GetStyle();\n    MyImPlot::StyleSeaborn();\n    if (ImPlot::BeginPlot(\"seaborn style\")) {\n        ImPlot::SetupAxes( \"x-axis\", \"y-axis\");\n        ImPlot::SetupAxesLimits(-0.5f, 9.5f, 0, 10);\n        unsigned int lin[10] = {8,8,9,7,8,8,8,9,7,8};\n        unsigned int bar[10] = {1,2,5,3,4,1,2,5,3,4};\n        unsigned int dot[10] = {7,6,6,7,8,5,6,5,8,7};\n        ImPlot::PlotBars(\"Bars\", bar, 10, 0.5f);\n        ImPlot::PlotLine(\"Line\", lin, 10);\n        ImPlot::NextColormapColor(); // skip green\n        ImPlot::PlotScatter(\"Scatter\", dot, 10);\n        ImPlot::EndPlot();\n    }\n    ImPlot::GetStyle() = backup;\n    ImPlot::PopColormap();\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_CustomRendering() {\n    if (ImPlot::BeginPlot(\"##CustomRend\")) {\n        ImVec2 cntr = ImPlot::PlotToPixels(ImPlotPoint(0.5f,  0.5f));\n        ImVec2 rmin = ImPlot::PlotToPixels(ImPlotPoint(0.25f, 0.75f));\n        ImVec2 rmax = ImPlot::PlotToPixels(ImPlotPoint(0.75f, 0.25f));\n        ImPlot::PushPlotClipRect();\n        ImPlot::GetPlotDrawList()->AddCircleFilled(cntr,20,IM_COL32(255,255,0,255),20);\n        ImPlot::GetPlotDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255));\n        ImPlot::PopPlotClipRect();\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_LegendPopups() {\n    ImGui::BulletText(\"You can implement legend context menus to inject per-item controls and widgets.\");\n    ImGui::BulletText(\"Right click the legend label/icon to edit custom item attributes.\");\n\n    static float  frequency = 0.1f;\n    static float  amplitude = 0.5f;\n    static ImVec4 color     = ImVec4(1,1,0,1);\n    static float  alpha     = 1.0f;\n    static bool   line      = false;\n    static float  thickness = 1;\n    static bool   markers   = false;\n    static bool   shaded    = false;\n\n    static float vals[101];\n    for (int i = 0; i < 101; ++i)\n        vals[i] = amplitude * sinf(frequency * i);\n\n    if (ImPlot::BeginPlot(\"Right Click the Legend\")) {\n        ImPlot::SetupAxesLimits(0,100,-1,1);\n        // rendering logic\n        ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha);\n        if (!line) {\n            ImPlot::SetNextFillStyle(color);\n            ImPlot::PlotBars(\"Right Click Me\", vals, 101);\n        }\n        else {\n            if (markers) ImPlot::SetNextMarkerStyle(ImPlotMarker_Square);\n            ImPlot::SetNextLineStyle(color, thickness);\n            ImPlot::PlotLine(\"Right Click Me\", vals, 101);\n            if (shaded) ImPlot::PlotShaded(\"Right Click Me\",vals,101);\n        }\n        ImPlot::PopStyleVar();\n        // custom legend context menu\n        if (ImPlot::BeginLegendPopup(\"Right Click Me\")) {\n            ImGui::SliderFloat(\"Frequency\",&frequency,0,1,\"%0.2f\");\n            ImGui::SliderFloat(\"Amplitude\",&amplitude,0,1,\"%0.2f\");\n            ImGui::Separator();\n            ImGui::ColorEdit3(\"Color\",&color.x);\n            ImGui::SliderFloat(\"Transparency\",&alpha,0,1,\"%.2f\");\n            ImGui::Checkbox(\"Line Plot\", &line);\n            if (line) {\n                ImGui::SliderFloat(\"Thickness\", &thickness, 0, 5);\n                ImGui::Checkbox(\"Markers\", &markers);\n                ImGui::Checkbox(\"Shaded\",&shaded);\n            }\n            ImPlot::EndLegendPopup();\n        }\n        ImPlot::EndPlot();\n    }\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_ColormapWidgets() {\n    static int cmap = ImPlotColormap_Viridis;\n\n    if (ImPlot::ColormapButton(\"Button\",ImVec2(0,0),cmap)) {\n        cmap = (cmap + 1) % ImPlot::GetColormapCount();\n    }\n\n    static float t = 0.5f;\n    static ImVec4 col;\n    ImGui::ColorButton(\"##Display\",col,ImGuiColorEditFlags_NoInputs);\n    ImGui::SameLine();\n    ImPlot::ColormapSlider(\"Slider\", &t, &col, \"%.3f\", cmap);\n\n    ImPlot::ColormapIcon(cmap); ImGui::SameLine(); ImGui::Text(\"Icon\");\n\n    static ImPlotColormapScaleFlags flags = 0;\n    static float scale[2] = {0, 100};\n    ImPlot::ColormapScale(\"Scale\",scale[0],scale[1],ImVec2(0,0),\"%g dB\",flags,cmap);\n    ImGui::InputFloat2(\"Scale\",scale);\n    CHECKBOX_FLAG(flags, ImPlotColormapScaleFlags_NoLabel);\n    CHECKBOX_FLAG(flags, ImPlotColormapScaleFlags_Opposite);\n    CHECKBOX_FLAG(flags, ImPlotColormapScaleFlags_Invert);\n}\n\n//-----------------------------------------------------------------------------\n\nvoid Demo_CustomPlottersAndTooltips()  {\n    ImGui::BulletText(\"You can create custom plotters or extend ImPlot using implot_internal.h.\");\n    double dates[]  = {1546300800,1546387200,1546473600,1546560000,1546819200,1546905600,1546992000,1547078400,1547164800,1547424000,1547510400,1547596800,1547683200,1547769600,1547942400,1548028800,1548115200,1548201600,1548288000,1548374400,1548633600,1548720000,1548806400,1548892800,1548979200,1549238400,1549324800,1549411200,1549497600,1549584000,1549843200,1549929600,1550016000,1550102400,1550188800,1550361600,1550448000,1550534400,1550620800,1550707200,1550793600,1551052800,1551139200,1551225600,1551312000,1551398400,1551657600,1551744000,1551830400,1551916800,1552003200,1552262400,1552348800,1552435200,1552521600,1552608000,1552867200,1552953600,1553040000,1553126400,1553212800,1553472000,1553558400,1553644800,1553731200,1553817600,1554076800,1554163200,1554249600,1554336000,1554422400,1554681600,1554768000,1554854400,1554940800,1555027200,1555286400,1555372800,1555459200,1555545600,1555632000,1555891200,1555977600,1556064000,1556150400,1556236800,1556496000,1556582400,1556668800,1556755200,1556841600,1557100800,1557187200,1557273600,1557360000,1557446400,1557705600,1557792000,1557878400,1557964800,1558051200,1558310400,1558396800,1558483200,1558569600,1558656000,1558828800,1558915200,1559001600,1559088000,1559174400,1559260800,1559520000,1559606400,1559692800,1559779200,1559865600,1560124800,1560211200,1560297600,1560384000,1560470400,1560729600,1560816000,1560902400,1560988800,1561075200,1561334400,1561420800,1561507200,1561593600,1561680000,1561939200,1562025600,1562112000,1562198400,1562284800,1562544000,1562630400,1562716800,1562803200,1562889600,1563148800,1563235200,1563321600,1563408000,1563494400,1563753600,1563840000,1563926400,1564012800,1564099200,1564358400,1564444800,1564531200,1564617600,1564704000,1564963200,1565049600,1565136000,1565222400,1565308800,1565568000,1565654400,1565740800,1565827200,1565913600,1566172800,1566259200,1566345600,1566432000,1566518400,1566777600,1566864000,1566950400,1567036800,1567123200,1567296000,1567382400,1567468800,1567555200,1567641600,1567728000,1567987200,1568073600,1568160000,1568246400,1568332800,1568592000,1568678400,1568764800,1568851200,1568937600,1569196800,1569283200,1569369600,1569456000,1569542400,1569801600,1569888000,1569974400,1570060800,1570147200,1570406400,1570492800,1570579200,1570665600,1570752000,1571011200,1571097600,1571184000,1571270400,1571356800,1571616000,1571702400,1571788800,1571875200,1571961600};\n    double opens[]  = {1284.7,1319.9,1318.7,1328,1317.6,1321.6,1314.3,1325,1319.3,1323.1,1324.7,1321.3,1323.5,1322,1281.3,1281.95,1311.1,1315,1314,1313.1,1331.9,1334.2,1341.3,1350.6,1349.8,1346.4,1343.4,1344.9,1335.6,1337.9,1342.5,1337,1338.6,1337,1340.4,1324.65,1324.35,1349.5,1371.3,1367.9,1351.3,1357.8,1356.1,1356,1347.6,1339.1,1320.6,1311.8,1314,1312.4,1312.3,1323.5,1319.1,1327.2,1332.1,1320.3,1323.1,1328,1330.9,1338,1333,1335.3,1345.2,1341.1,1332.5,1314,1314.4,1310.7,1314,1313.1,1315,1313.7,1320,1326.5,1329.2,1314.2,1312.3,1309.5,1297.4,1293.7,1277.9,1295.8,1295.2,1290.3,1294.2,1298,1306.4,1299.8,1302.3,1297,1289.6,1302,1300.7,1303.5,1300.5,1303.2,1306,1318.7,1315,1314.5,1304.1,1294.7,1293.7,1291.2,1290.2,1300.4,1284.2,1284.25,1301.8,1295.9,1296.2,1304.4,1323.1,1340.9,1341,1348,1351.4,1351.4,1343.5,1342.3,1349,1357.6,1357.1,1354.7,1361.4,1375.2,1403.5,1414.7,1433.2,1438,1423.6,1424.4,1418,1399.5,1435.5,1421.25,1434.1,1412.4,1409.8,1412.2,1433.4,1418.4,1429,1428.8,1420.6,1441,1460.4,1441.7,1438.4,1431,1439.3,1427.4,1431.9,1439.5,1443.7,1425.6,1457.5,1451.2,1481.1,1486.7,1512.1,1515.9,1509.2,1522.3,1513,1526.6,1533.9,1523,1506.3,1518.4,1512.4,1508.8,1545.4,1537.3,1551.8,1549.4,1536.9,1535.25,1537.95,1535.2,1556,1561.4,1525.6,1516.4,1507,1493.9,1504.9,1506.5,1513.1,1506.5,1509.7,1502,1506.8,1521.5,1529.8,1539.8,1510.9,1511.8,1501.7,1478,1485.4,1505.6,1511.6,1518.6,1498.7,1510.9,1510.8,1498.3,1492,1497.7,1484.8,1494.2,1495.6,1495.6,1487.5,1491.1,1495.1,1506.4};\n    double highs[]  = {1284.75,1320.6,1327,1330.8,1326.8,1321.6,1326,1328,1325.8,1327.1,1326,1326,1323.5,1322.1,1282.7,1282.95,1315.8,1316.3,1314,1333.2,1334.7,1341.7,1353.2,1354.6,1352.2,1346.4,1345.7,1344.9,1340.7,1344.2,1342.7,1342.1,1345.2,1342,1350,1324.95,1330.75,1369.6,1374.3,1368.4,1359.8,1359,1357,1356,1353.4,1340.6,1322.3,1314.1,1316.1,1312.9,1325.7,1323.5,1326.3,1336,1332.1,1330.1,1330.4,1334.7,1341.1,1344.2,1338.8,1348.4,1345.6,1342.8,1334.7,1322.3,1319.3,1314.7,1316.6,1316.4,1315,1325.4,1328.3,1332.2,1329.2,1316.9,1312.3,1309.5,1299.6,1296.9,1277.9,1299.5,1296.2,1298.4,1302.5,1308.7,1306.4,1305.9,1307,1297.2,1301.7,1305,1305.3,1310.2,1307,1308,1319.8,1321.7,1318.7,1316.2,1305.9,1295.8,1293.8,1293.7,1304.2,1302,1285.15,1286.85,1304,1302,1305.2,1323,1344.1,1345.2,1360.1,1355.3,1363.8,1353,1344.7,1353.6,1358,1373.6,1358.2,1369.6,1377.6,1408.9,1425.5,1435.9,1453.7,1438,1426,1439.1,1418,1435,1452.6,1426.65,1437.5,1421.5,1414.1,1433.3,1441.3,1431.4,1433.9,1432.4,1440.8,1462.3,1467,1443.5,1444,1442.9,1447,1437.6,1440.8,1445.7,1447.8,1458.2,1461.9,1481.8,1486.8,1522.7,1521.3,1521.1,1531.5,1546.1,1534.9,1537.7,1538.6,1523.6,1518.8,1518.4,1514.6,1540.3,1565,1554.5,1556.6,1559.8,1541.9,1542.9,1540.05,1558.9,1566.2,1561.9,1536.2,1523.8,1509.1,1506.2,1532.2,1516.6,1519.7,1515,1519.5,1512.1,1524.5,1534.4,1543.3,1543.3,1542.8,1519.5,1507.2,1493.5,1511.4,1525.8,1522.2,1518.8,1515.3,1518,1522.3,1508,1501.5,1503,1495.5,1501.1,1497.9,1498.7,1492.1,1499.4,1506.9,1520.9};\n    double lows[]   = {1282.85,1315,1318.7,1309.6,1317.6,1312.9,1312.4,1319.1,1319,1321,1318.1,1321.3,1319.9,1312,1280.5,1276.15,1308,1309.9,1308.5,1312.3,1329.3,1333.1,1340.2,1347,1345.9,1338,1340.8,1335,1332,1337.9,1333,1336.8,1333.2,1329.9,1340.4,1323.85,1324.05,1349,1366.3,1351.2,1349.1,1352.4,1350.7,1344.3,1338.9,1316.3,1308.4,1306.9,1309.6,1306.7,1312.3,1315.4,1319,1327.2,1317.2,1320,1323,1328,1323,1327.8,1331.7,1335.3,1336.6,1331.8,1311.4,1310,1309.5,1308,1310.6,1302.8,1306.6,1313.7,1320,1322.8,1311,1312.1,1303.6,1293.9,1293.5,1291,1277.9,1294.1,1286,1289.1,1293.5,1296.9,1298,1299.6,1292.9,1285.1,1288.5,1296.3,1297.2,1298.4,1298.6,1302,1300.3,1312,1310.8,1301.9,1292,1291.1,1286.3,1289.2,1289.9,1297.4,1283.65,1283.25,1292.9,1295.9,1290.8,1304.2,1322.7,1336.1,1341,1343.5,1345.8,1340.3,1335.1,1341.5,1347.6,1352.8,1348.2,1353.7,1356.5,1373.3,1398,1414.7,1427,1416.4,1412.7,1420.1,1396.4,1398.8,1426.6,1412.85,1400.7,1406,1399.8,1404.4,1415.5,1417.2,1421.9,1415,1413.7,1428.1,1434,1435.7,1427.5,1429.4,1423.9,1425.6,1427.5,1434.8,1422.3,1412.1,1442.5,1448.8,1468.2,1484.3,1501.6,1506.2,1498.6,1488.9,1504.5,1518.3,1513.9,1503.3,1503,1506.5,1502.1,1503,1534.8,1535.3,1541.4,1528.6,1525.6,1535.25,1528.15,1528,1542.6,1514.3,1510.7,1505.5,1492.1,1492.9,1496.8,1493.1,1503.4,1500.9,1490.7,1496.3,1505.3,1505.3,1517.9,1507.4,1507.1,1493.3,1470.5,1465,1480.5,1501.7,1501.4,1493.3,1492.1,1505.1,1495.7,1478,1487.1,1480.8,1480.6,1487,1488.3,1484.8,1484,1490.7,1490.4,1503.1};\n    double closes[] = {1283.35,1315.3,1326.1,1317.4,1321.5,1317.4,1323.5,1319.2,1321.3,1323.3,1319.7,1325.1,1323.6,1313.8,1282.05,1279.05,1314.2,1315.2,1310.8,1329.1,1334.5,1340.2,1340.5,1350,1347.1,1344.3,1344.6,1339.7,1339.4,1343.7,1337,1338.9,1340.1,1338.7,1346.8,1324.25,1329.55,1369.6,1372.5,1352.4,1357.6,1354.2,1353.4,1346,1341,1323.8,1311.9,1309.1,1312.2,1310.7,1324.3,1315.7,1322.4,1333.8,1319.4,1327.1,1325.8,1330.9,1325.8,1331.6,1336.5,1346.7,1339.2,1334.7,1313.3,1316.5,1312.4,1313.4,1313.3,1312.2,1313.7,1319.9,1326.3,1331.9,1311.3,1313.4,1309.4,1295.2,1294.7,1294.1,1277.9,1295.8,1291.2,1297.4,1297.7,1306.8,1299.4,1303.6,1302.2,1289.9,1299.2,1301.8,1303.6,1299.5,1303.2,1305.3,1319.5,1313.6,1315.1,1303.5,1293,1294.6,1290.4,1291.4,1302.7,1301,1284.15,1284.95,1294.3,1297.9,1304.1,1322.6,1339.3,1340.1,1344.9,1354,1357.4,1340.7,1342.7,1348.2,1355.1,1355.9,1354.2,1362.1,1360.1,1408.3,1411.2,1429.5,1430.1,1426.8,1423.4,1425.1,1400.8,1419.8,1432.9,1423.55,1412.1,1412.2,1412.8,1424.9,1419.3,1424.8,1426.1,1423.6,1435.9,1440.8,1439.4,1439.7,1434.5,1436.5,1427.5,1432.2,1433.3,1441.8,1437.8,1432.4,1457.5,1476.5,1484.2,1519.6,1509.5,1508.5,1517.2,1514.1,1527.8,1531.2,1523.6,1511.6,1515.7,1515.7,1508.5,1537.6,1537.2,1551.8,1549.1,1536.9,1529.4,1538.05,1535.15,1555.9,1560.4,1525.5,1515.5,1511.1,1499.2,1503.2,1507.4,1499.5,1511.5,1513.4,1515.8,1506.2,1515.1,1531.5,1540.2,1512.3,1515.2,1506.4,1472.9,1489,1507.9,1513.8,1512.9,1504.4,1503.9,1512.8,1500.9,1488.7,1497.6,1483.5,1494,1498.3,1494.1,1488.1,1487.5,1495.7,1504.7,1505.3};\n    static bool tooltip = true;\n    ImGui::Checkbox(\"Show Tooltip\", &tooltip);\n    ImGui::SameLine();\n    static ImVec4 bullCol = ImVec4(0.000f, 1.000f, 0.441f, 1.000f);\n    static ImVec4 bearCol = ImVec4(0.853f, 0.050f, 0.310f, 1.000f);\n    ImGui::SameLine(); ImGui::ColorEdit4(\"##Bull\", &bullCol.x, ImGuiColorEditFlags_NoInputs);\n    ImGui::SameLine(); ImGui::ColorEdit4(\"##Bear\", &bearCol.x, ImGuiColorEditFlags_NoInputs);\n    ImPlot::GetStyle().UseLocalTime = false;\n\n    if (ImPlot::BeginPlot(\"Candlestick Chart\",ImVec2(-1,0))) {\n        ImPlot::SetupAxes(nullptr,nullptr,0,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_RangeFit);\n        ImPlot::SetupAxesLimits(1546300800, 1571961600, 1250, 1600);\n        ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);\n        ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 1546300800, 1571961600);\n        ImPlot::SetupAxisZoomConstraints(ImAxis_X1, 60*60*24*14, 1571961600-1546300800);\n        ImPlot::SetupAxisFormat(ImAxis_Y1, \"$%.0f\");\n        MyImPlot::PlotCandlestick(\"GOOGL\",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);\n        ImPlot::EndPlot();\n    }\n    }\n\n//-----------------------------------------------------------------------------\n// DEMO WINDOW\n//-----------------------------------------------------------------------------\n\nvoid DemoHeader(const char* label, void(*demo)()) {\n    if (ImGui::TreeNodeEx(label)) {\n        demo();\n        ImGui::TreePop();\n    }\n}\n\nvoid ShowDemoWindow(bool* p_open) {\n    static bool show_implot_metrics      = false;\n    static bool show_implot_style_editor = false;\n    static bool show_imgui_metrics       = false;\n    static bool show_imgui_style_editor  = false;\n    static bool show_imgui_demo          = false;\n\n    if (show_implot_metrics) {\n        ImPlot::ShowMetricsWindow(&show_implot_metrics);\n    }\n    if (show_implot_style_editor) {\n        ImGui::SetNextWindowSize(ImVec2(415,762), ImGuiCond_Appearing);\n        ImGui::Begin(\"Style Editor (ImPlot)\", &show_implot_style_editor);\n        ImPlot::ShowStyleEditor();\n        ImGui::End();\n    }\n    if (show_imgui_style_editor) {\n        ImGui::Begin(\"Style Editor (ImGui)\", &show_imgui_style_editor);\n        ImGui::ShowStyleEditor();\n        ImGui::End();\n    }\n    if (show_imgui_metrics) {\n        ImGui::ShowMetricsWindow(&show_imgui_metrics);\n    }\n    if (show_imgui_demo) {\n        ImGui::ShowDemoWindow(&show_imgui_demo);\n    }\n    ImGui::SetNextWindowPos(ImVec2(50, 50), ImGuiCond_FirstUseEver);\n    ImGui::SetNextWindowSize(ImVec2(600, 750), ImGuiCond_FirstUseEver);\n    ImGui::Begin(\"ImPlot Demo\", p_open, ImGuiWindowFlags_MenuBar);\n    if (ImGui::BeginMenuBar()) {\n        if (ImGui::BeginMenu(\"Tools\")) {\n            ImGui::MenuItem(\"Metrics\",      nullptr, &show_implot_metrics);\n            ImGui::MenuItem(\"Style Editor\", nullptr, &show_implot_style_editor);\n            ImGui::Separator();\n            ImGui::MenuItem(\"ImGui Metrics\",       nullptr, &show_imgui_metrics);\n            ImGui::MenuItem(\"ImGui Style Editor\",  nullptr, &show_imgui_style_editor);\n            ImGui::MenuItem(\"ImGui Demo\",          nullptr, &show_imgui_demo);\n            ImGui::EndMenu();\n        }\n        ImGui::EndMenuBar();\n    }\n    //-------------------------------------------------------------------------\n    ImGui::Text(\"ImPlot says hello. (%s)\", IMPLOT_VERSION);\n    // display warning about 16-bit indices\n    static bool showWarning = sizeof(ImDrawIdx)*8 == 16 && (ImGui::GetIO().BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) == false;\n    if (showWarning) {\n        ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,1,0,1));\n        ImGui::TextWrapped(\"WARNING: ImDrawIdx is 16-bit and ImGuiBackendFlags_RendererHasVtxOffset is false. Expect visual glitches and artifacts! See README for more information.\");\n        ImGui::PopStyleColor();\n    }\n\n    ImGui::Spacing();\n\n    if (ImGui::BeginTabBar(\"ImPlotDemoTabs\")) {\n        if (ImGui::BeginTabItem(\"Plots\")) {\n            DemoHeader(\"Line Plots\", Demo_LinePlots);\n            DemoHeader(\"Filled Line Plots\", Demo_FilledLinePlots);\n            DemoHeader(\"Shaded Plots##\", Demo_ShadedPlots);\n            DemoHeader(\"Scatter Plots\", Demo_ScatterPlots);\n            DemoHeader(\"Realtime Plots\", Demo_RealtimePlots);\n            DemoHeader(\"Stairstep Plots\", Demo_StairstepPlots);\n            DemoHeader(\"Bar Plots\", Demo_BarPlots);\n            DemoHeader(\"Bar Groups\", Demo_BarGroups);\n            DemoHeader(\"Bar Stacks\", Demo_BarStacks);\n            DemoHeader(\"Error Bars\", Demo_ErrorBars);\n            DemoHeader(\"Stem Plots##\", Demo_StemPlots);\n            DemoHeader(\"Infinite Lines\", Demo_InfiniteLines);\n            DemoHeader(\"Pie Charts\", Demo_PieCharts);\n            DemoHeader(\"Heatmaps\", Demo_Heatmaps);\n            DemoHeader(\"Histogram\", Demo_Histogram);\n            DemoHeader(\"Histogram 2D\", Demo_Histogram2D);\n            DemoHeader(\"Digital Plots\", Demo_DigitalPlots);\n            DemoHeader(\"Images\", Demo_Images);\n            DemoHeader(\"Markers and Text\", Demo_MarkersAndText);\n            DemoHeader(\"NaN Values\", Demo_NaNValues);\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Subplots\")) {\n            DemoHeader(\"Sizing\", Demo_SubplotsSizing);\n            DemoHeader(\"Item Sharing\", Demo_SubplotItemSharing);\n            DemoHeader(\"Axis Linking\", Demo_SubplotAxisLinking);\n            DemoHeader(\"Tables\", Demo_Tables);\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Axes\")) {\n            DemoHeader(\"Log Scale\", Demo_LogScale);\n            DemoHeader(\"Symmetric Log Scale\", Demo_SymmetricLogScale);\n            DemoHeader(\"Time Scale\", Demo_TimeScale);\n            DemoHeader(\"Custom Scale\", Demo_CustomScale);\n            DemoHeader(\"Multiple Axes\", Demo_MultipleAxes);\n            DemoHeader(\"Tick Labels\", Demo_TickLabels);\n            DemoHeader(\"Linked Axes\", Demo_LinkedAxes);\n            DemoHeader(\"Axis Constraints\", Demo_AxisConstraints);\n            DemoHeader(\"Equal Axes\", Demo_EqualAxes);\n            DemoHeader(\"Auto-Fitting Data\", Demo_AutoFittingData);\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Tools\")) {\n            DemoHeader(\"Offset and Stride\", Demo_OffsetAndStride);\n            DemoHeader(\"Drag Points\", Demo_DragPoints);\n            DemoHeader(\"Drag Lines\", Demo_DragLines);\n            DemoHeader(\"Drag Rects\", Demo_DragRects);\n            DemoHeader(\"Querying\", Demo_Querying);\n            DemoHeader(\"Annotations\", Demo_Annotations);\n            DemoHeader(\"Tags\", Demo_Tags);\n            DemoHeader(\"Drag and Drop\", Demo_DragAndDrop);\n            DemoHeader(\"Legend Options\", Demo_LegendOptions);\n            DemoHeader(\"Legend Popups\", Demo_LegendPopups);\n            DemoHeader(\"Colormap Widgets\", Demo_ColormapWidgets);\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Custom\")) {\n            DemoHeader(\"Custom Styles\", Demo_CustomStyles);\n            DemoHeader(\"Custom Data and Getters\", Demo_CustomDataAndGetters);\n            DemoHeader(\"Custom Rendering\", Demo_CustomRendering);\n            DemoHeader(\"Custom Plotters and Tooltips\", Demo_CustomPlottersAndTooltips);\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Config\")) {\n            Demo_Config();\n            ImGui::EndTabItem();\n        }\n        if (ImGui::BeginTabItem(\"Help\")) {\n            Demo_Help();\n            ImGui::EndTabItem();\n        }\n        ImGui::EndTabBar();\n    }\n    ImGui::End();\n}\n\n} // namespace ImPlot\n\nnamespace MyImPlot {\n\nImPlotPoint SineWave(int idx, void* data) {\n    WaveData* wd = (WaveData*)data;\n    double x = idx * wd->X;\n    return ImPlotPoint(x, wd->Offset + wd->Amp * sin(2 * 3.14 * wd->Freq * x));\n}\n\nImPlotPoint SawWave(int idx, void* data) {\n    WaveData* wd = (WaveData*)data;\n    double x = idx * wd->X;\n    return ImPlotPoint(x, wd->Offset + wd->Amp * (-2 / 3.14 * atan(cos(3.14 * wd->Freq * x) / sin(3.14 * wd->Freq * x))));\n}\n\nImPlotPoint Spiral(int idx, void*) {\n    float r = 0.9f;            // outer radius\n    float a = 0;               // inner radius\n    float b = 0.05f;           // increment per rev\n    float n = (r - a) / b;     // number  of revolutions\n    double th = 2 * n * 3.14;  // angle\n    float Th = float(th * idx / (1000 - 1));\n    return ImPlotPoint(0.5f+(a + b*Th / (2.0f * (float) 3.14))*cos(Th),\n                       0.5f + (a + b*Th / (2.0f * (float)3.14))*sin(Th));\n}\n\nvoid Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) {\n    ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0));\n    if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) {\n        ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);\n        ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always);\n        ImPlot::SetNextLineStyle(col);\n        ImPlot::SetNextFillStyle(col, 0.25);\n        ImPlot::PlotLine(id, values, count, 1, 0, ImPlotLineFlags_Shaded, offset);\n        ImPlot::EndPlot();\n    }\n    ImPlot::PopStyleVar();\n}\n\nvoid StyleSeaborn() {\n\n    ImPlotStyle& style              = ImPlot::GetStyle();\n\n    ImVec4* colors                  = style.Colors;\n    colors[ImPlotCol_Line]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_Fill]          = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_MarkerFill]    = IMPLOT_AUTO_COL;\n    colors[ImPlotCol_ErrorBar]      = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_FrameBg]       = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_PlotBg]        = ImVec4(0.92f, 0.92f, 0.95f, 1.00f);\n    colors[ImPlotCol_PlotBorder]    = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\n    colors[ImPlotCol_LegendBg]      = ImVec4(0.92f, 0.92f, 0.95f, 1.00f);\n    colors[ImPlotCol_LegendBorder]  = ImVec4(0.80f, 0.81f, 0.85f, 1.00f);\n    colors[ImPlotCol_LegendText]    = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_TitleText]     = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_InlayText]     = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_AxisText]      = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);\n    colors[ImPlotCol_AxisGrid]      = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\n    colors[ImPlotCol_AxisBgHovered]   = ImVec4(0.92f, 0.92f, 0.95f, 1.00f);\n    colors[ImPlotCol_AxisBgActive]    = ImVec4(0.92f, 0.92f, 0.95f, 0.75f);\n    colors[ImPlotCol_Selection]     = ImVec4(1.00f, 0.65f, 0.00f, 1.00f);\n    colors[ImPlotCol_Crosshairs]    = ImVec4(0.23f, 0.10f, 0.64f, 0.50f);\n\n    style.LineWeight       = 1.5;\n    style.Marker           = ImPlotMarker_None;\n    style.MarkerSize       = 4;\n    style.MarkerWeight     = 1;\n    style.FillAlpha        = 1.0f;\n    style.ErrorBarSize     = 5;\n    style.ErrorBarWeight   = 1.5f;\n    style.DigitalBitHeight = 8;\n    style.DigitalBitGap    = 4;\n    style.PlotBorderSize   = 0;\n    style.MinorAlpha       = 1.0f;\n    style.MajorTickLen     = ImVec2(0,0);\n    style.MinorTickLen     = ImVec2(0,0);\n    style.MajorTickSize    = ImVec2(0,0);\n    style.MinorTickSize    = ImVec2(0,0);\n    style.MajorGridSize    = ImVec2(1.2f,1.2f);\n    style.MinorGridSize    = ImVec2(1.2f,1.2f);\n    style.PlotPadding      = ImVec2(12,12);\n    style.LabelPadding     = ImVec2(5,5);\n    style.LegendPadding    = ImVec2(5,5);\n    style.MousePosPadding  = ImVec2(5,5);\n    style.PlotMinSize      = ImVec2(300,225);\n}\n\n} // namespaece MyImPlot\n\n// WARNING:\n//\n// You can use \"implot_internal.h\" to build custom plotting fuctions or extend ImPlot.\n// However, note that forward compatibility of this file is not guaranteed and the\n// internal API is subject to change. At some point we hope to bring more of this\n// into the public API and expose the necessary building blocks to fully support\n// custom plotters. For now, proceed at your own risk!\n\n#include \"implot_internal.h\"\n\nnamespace MyImPlot {\n\ntemplate <typename T>\nint BinarySearch(const T* arr, int l, int r, T x) {\n    if (r >= l) {\n        int mid = l + (r - l) / 2;\n        if (arr[mid] == x)\n            return mid;\n        if (arr[mid] > x)\n            return BinarySearch(arr, l, mid - 1, x);\n        return BinarySearch(arr, mid + 1, r, x);\n    }\n    return -1;\n}\n\nvoid PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip, float width_percent, ImVec4 bullCol, ImVec4 bearCol) {\n\n    // get ImGui window DrawList\n    ImDrawList* draw_list = ImPlot::GetPlotDrawList();\n    // calc real value width\n    double half_width = count > 1 ? (xs[1] - xs[0]) * width_percent : width_percent;\n\n    // custom tool\n    if (ImPlot::IsPlotHovered() && tooltip) {\n        ImPlotPoint mouse   = ImPlot::GetPlotMousePos();\n        mouse.x             = ImPlot::RoundTime(ImPlotTime::FromDouble(mouse.x), ImPlotTimeUnit_Day).ToDouble();\n        float  tool_l       = ImPlot::PlotToPixels(mouse.x - half_width * 1.5, mouse.y).x;\n        float  tool_r       = ImPlot::PlotToPixels(mouse.x + half_width * 1.5, mouse.y).x;\n        float  tool_t       = ImPlot::GetPlotPos().y;\n        float  tool_b       = tool_t + ImPlot::GetPlotSize().y;\n        ImPlot::PushPlotClipRect();\n        draw_list->AddRectFilled(ImVec2(tool_l, tool_t), ImVec2(tool_r, tool_b), IM_COL32(128,128,128,64));\n        ImPlot::PopPlotClipRect();\n        // find mouse location index\n        int idx = BinarySearch(xs, 0, count - 1, mouse.x);\n        // render tool tip (won't be affected by plot clip rect)\n        if (idx != -1) {\n            ImGui::BeginTooltip();\n            char buff[32];\n            ImPlot::FormatDate(ImPlotTime::FromDouble(xs[idx]),buff,32,ImPlotDateFmt_DayMoYr,ImPlot::GetStyle().UseISO8601);\n            ImGui::Text(\"Day:   %s\",  buff);\n            ImGui::Text(\"Open:  $%.2f\", opens[idx]);\n            ImGui::Text(\"Close: $%.2f\", closes[idx]);\n            ImGui::Text(\"Low:   $%.2f\", lows[idx]);\n            ImGui::Text(\"High:  $%.2f\", highs[idx]);\n            ImGui::EndTooltip();\n        }\n    }\n\n    // begin plot item\n    if (ImPlot::BeginItem(label_id)) {\n        // override legend icon color\n        ImPlot::GetCurrentItem()->Color = IM_COL32(64,64,64,255);\n        // fit data if requested\n        if (ImPlot::FitThisFrame()) {\n            for (int i = 0; i < count; ++i) {\n                ImPlot::FitPoint(ImPlotPoint(xs[i], lows[i]));\n                ImPlot::FitPoint(ImPlotPoint(xs[i], highs[i]));\n            }\n        }\n        // render data\n        for (int i = 0; i < count; ++i) {\n            ImVec2 open_pos  = ImPlot::PlotToPixels(xs[i] - half_width, opens[i]);\n            ImVec2 close_pos = ImPlot::PlotToPixels(xs[i] + half_width, closes[i]);\n            ImVec2 low_pos   = ImPlot::PlotToPixels(xs[i], lows[i]);\n            ImVec2 high_pos  = ImPlot::PlotToPixels(xs[i], highs[i]);\n            ImU32 color      = ImGui::GetColorU32(opens[i] > closes[i] ? bearCol : bullCol);\n            draw_list->AddLine(low_pos, high_pos, color);\n            draw_list->AddRectFilled(open_pos, close_pos, color);\n        }\n\n        // end plot item\n        ImPlot::EndItem();\n    }\n}\n\n} // namespace MyImplot\n"
  },
  {
    "path": "Source/External/imgui_tools/implot/implot_internal.h",
    "content": "// MIT License\n\n// Copyright (c) 2022 Evan Pezent\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// ImPlot v0.14\n\n// You may use this file to debug, understand or extend ImPlot features but we\n// don't provide any guarantee of forward compatibility!\n\n//-----------------------------------------------------------------------------\n// [SECTION] Header Mess\n//-----------------------------------------------------------------------------\n\n#pragma once\n\n#include <time.h>\n#include \"imgui_internal.h\"\n\n#ifndef IMPLOT_VERSION\n#error Must include implot.h before implot_internal.h\n#endif\n\n\n// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize()\n#if (IMGUI_VERSION_NUM < 18303)\n#define GetBufSize GetSize\n#endif\n\n//-----------------------------------------------------------------------------\n// [SECTION] Constants\n//-----------------------------------------------------------------------------\n\n// Constants can be changed unless stated otherwise. We may move some of these\n// to ImPlotStyleVar_ over time.\n\n// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)\n#define IMPLOT_MIN_TIME  0\n// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)\n#define IMPLOT_MAX_TIME  32503680000\n// Default label format for axis labels\n#define IMPLOT_LABEL_FORMAT \"%g\"\n// Max character size for tick labels\n#define IMPLOT_LABEL_MAX_SIZE 32\n\n//-----------------------------------------------------------------------------\n// [SECTION] Macros\n//-----------------------------------------------------------------------------\n\n#define IMPLOT_NUM_X_AXES ImAxis_Y1\n#define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES)\n\n// Split ImU32 color into RGB components [0 255]\n#define IM_COL32_SPLIT_RGB(col,r,g,b) \\\n    ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \\\n    ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \\\n    ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Forward Declarations\n//-----------------------------------------------------------------------------\n\nstruct ImPlotTick;\nstruct ImPlotAxis;\nstruct ImPlotAxisColor;\nstruct ImPlotItem;\nstruct ImPlotLegend;\nstruct ImPlotPlot;\nstruct ImPlotNextPlotData;\nstruct ImPlotTicker;\n\n//-----------------------------------------------------------------------------\n// [SECTION] Context Pointer\n//-----------------------------------------------------------------------------\n\n#ifndef GImPlot\nextern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer\n#endif\n\n//-----------------------------------------------------------------------------\n// [SECTION] Generic Helpers\n//-----------------------------------------------------------------------------\n\n// Computes the common (base-10) logarithm\nstatic inline float  ImLog10(float x)  { return log10f(x); }\nstatic inline double ImLog10(double x) { return log10(x);  }\nstatic inline float  ImSinh(float x)   { return sinhf(x);  }\nstatic inline double ImSinh(double x)  { return sinh(x);   }\nstatic inline float  ImAsinh(float x)  { return asinhf(x); }\nstatic inline double ImAsinh(double x) { return asinh(x);  }\n// Returns true if a flag is set\ntemplate <typename TSet, typename TFlag>\nstatic inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }\n// Flips a flag in a flagset\ntemplate <typename TSet, typename TFlag>\nstatic inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }\n// Linearly remaps x from [x0 x1] to [y0 y1].\ntemplate <typename T>\nstatic inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }\n// Linear rempas x from [x0 x1] to [0 1]\ntemplate <typename T>\nstatic inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }\n// Returns always positive modulo (assumes r != 0)\nstatic inline int ImPosMod(int l, int r) { return (l % r + r) % r; }\n// Returns true if val is NAN\nstatic inline bool ImNan(double val) { return isnan(val); }\n// Returns true if val is NAN or INFINITY\nstatic inline bool ImNanOrInf(double val) { return !(val >= -DBL_MAX && val <= DBL_MAX) || ImNan(val); }\n// Turns NANs to 0s\nstatic inline double ImConstrainNan(double val) { return ImNan(val) ? 0 : val; }\n// Turns infinity to floating point maximums\nstatic inline double ImConstrainInf(double val) { return val >= DBL_MAX ?  DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; }\n// Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)\nstatic inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }\n// Turns numbers less than 0 to zero\nstatic inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }\n// True if two numbers are approximately equal using units in the last place.\nstatic inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) { return ImAbs(v1-v2) < DBL_EPSILON * ImAbs(v1+v2) * ulp || ImAbs(v1-v2) < DBL_MIN; }\n// Finds min value in an unsorted array\ntemplate <typename T>\nstatic inline T ImMinArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] < m) { m = values[i]; } } return m; }\n// Finds the max value in an unsorted array\ntemplate <typename T>\nstatic inline T ImMaxArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] > m) { m = values[i]; } } return m; }\n// Finds the min and max value in an unsorted array\ntemplate <typename T>\nstatic inline void ImMinMaxArray(const T* values, int count, T* min_out, T* max_out) {\n    T Min = values[0]; T Max = values[0];\n    for (int i = 1; i < count; ++i) {\n        if (values[i] < Min) { Min = values[i]; }\n        if (values[i] > Max) { Max = values[i]; }\n    }\n    *min_out = Min; *max_out = Max;\n}\n// Finds the sim of an array\ntemplate <typename T>\nstatic inline T ImSum(const T* values, int count) {\n    T sum  = 0;\n    for (int i = 0; i < count; ++i)\n        sum += values[i];\n    return sum;\n}\n// Finds the mean of an array\ntemplate <typename T>\nstatic inline double ImMean(const T* values, int count) {\n    double den = 1.0 / count;\n    double mu  = 0;\n    for (int i = 0; i < count; ++i)\n        mu += (double)values[i] * den;\n    return mu;\n}\n// Finds the sample standard deviation of an array\ntemplate <typename T>\nstatic inline double ImStdDev(const T* values, int count) {\n    double den = 1.0 / (count - 1.0);\n    double mu  = ImMean(values, count);\n    double x   = 0;\n    for (int i = 0; i < count; ++i)\n        x += ((double)values[i] - mu) * ((double)values[i] - mu) * den;\n    return sqrt(x);\n}\n// Mix color a and b by factor s in [0 256]\nstatic inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {\n#ifdef IMPLOT_MIX64\n    const ImU32 af = 256-s;\n    const ImU32 bf = s;\n    const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24);\n    const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24);\n    const ImU64 mix = (al * af + bl * bf);\n    return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8);\n#else\n    const ImU32 af = 256-s;\n    const ImU32 bf = s;\n    const ImU32 al = (a & 0x00ff00ff);\n    const ImU32 ah = (a & 0xff00ff00) >> 8;\n    const ImU32 bl = (b & 0x00ff00ff);\n    const ImU32 bh = (b & 0xff00ff00) >> 8;\n    const ImU32 ml = (al * af + bl * bf);\n    const ImU32 mh = (ah * af + bh * bf);\n    return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8);\n#endif\n}\n\n// Lerp across an array of 32-bit collors given t in [0.0 1.0]\nstatic inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) {\n    int i1 = (int)((size - 1 ) * t);\n    int i2 = i1 + 1;\n    if (i2 == size || size == 1)\n        return colors[i1];\n    float den = 1.0f / (size - 1);\n    float t1 = i1 * den;\n    float t2 = i2 * den;\n    float tr = ImRemap01(t, t1, t2);\n    return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));\n}\n\n// Set alpha channel of 32-bit color from float in range [0.0 1.0]\nstatic inline ImU32 ImAlphaU32(ImU32 col, float alpha) {\n    return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);\n}\n\n// Returns true of two ranges overlap\ntemplate <typename T>\nstatic inline bool ImOverlaps(T min_a, T max_a, T min_b, T max_b) {\n    return min_a <= max_b && min_b <= max_a;\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] ImPlot Enums\n//-----------------------------------------------------------------------------\n\ntypedef int ImPlotTimeUnit;    // -> enum ImPlotTimeUnit_\ntypedef int ImPlotDateFmt;     // -> enum ImPlotDateFmt_\ntypedef int ImPlotTimeFmt;     // -> enum ImPlotTimeFmt_\n\nenum ImPlotTimeUnit_ {\n    ImPlotTimeUnit_Us,  // microsecond\n    ImPlotTimeUnit_Ms,  // millisecond\n    ImPlotTimeUnit_S,   // second\n    ImPlotTimeUnit_Min, // minute\n    ImPlotTimeUnit_Hr,  // hour\n    ImPlotTimeUnit_Day, // day\n    ImPlotTimeUnit_Mo,  // month\n    ImPlotTimeUnit_Yr,  // year\n    ImPlotTimeUnit_COUNT\n};\n\nenum ImPlotDateFmt_ {              // default        [ ISO 8601     ]\n    ImPlotDateFmt_None = 0,\n    ImPlotDateFmt_DayMo,           // 10/3           [ --10-03      ]\n    ImPlotDateFmt_DayMoYr,         // 10/3/91        [ 1991-10-03   ]\n    ImPlotDateFmt_MoYr,            // Oct 1991       [ 1991-10      ]\n    ImPlotDateFmt_Mo,              // Oct            [ --10         ]\n    ImPlotDateFmt_Yr               // 1991           [ 1991         ]\n};\n\nenum ImPlotTimeFmt_ {              // default        [ 24 Hour Clock ]\n    ImPlotTimeFmt_None = 0,\n    ImPlotTimeFmt_Us,              // .428 552       [ .428 552     ]\n    ImPlotTimeFmt_SUs,             // :29.428 552    [ :29.428 552  ]\n    ImPlotTimeFmt_SMs,             // :29.428        [ :29.428      ]\n    ImPlotTimeFmt_S,               // :29            [ :29          ]\n    ImPlotTimeFmt_MinSMs,          // 21:29.428      [ 21:29.428    ]\n    ImPlotTimeFmt_HrMinSMs,        // 7:21:29.428pm  [ 19:21:29.428 ]\n    ImPlotTimeFmt_HrMinS,          // 7:21:29pm      [ 19:21:29     ]\n    ImPlotTimeFmt_HrMin,           // 7:21pm         [ 19:21        ]\n    ImPlotTimeFmt_Hr               // 7pm            [ 19:00        ]\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Callbacks\n//-----------------------------------------------------------------------------\n\ntypedef void (*ImPlotLocator)(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Structs\n//-----------------------------------------------------------------------------\n\n// Combined date/time format spec\nstruct ImPlotDateTimeSpec {\n    ImPlotDateTimeSpec() {}\n    ImPlotDateTimeSpec(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt, bool use_24_hr_clk = false, bool use_iso_8601 = false) {\n        Date           = date_fmt;\n        Time           = time_fmt;\n        UseISO8601     = use_iso_8601;\n        Use24HourClock = use_24_hr_clk;\n    }\n    ImPlotDateFmt Date;\n    ImPlotTimeFmt Time;\n    bool UseISO8601;\n    bool Use24HourClock;\n};\n\n// Two part timestamp struct.\nstruct ImPlotTime {\n    time_t S;  // second part\n    int    Us; // microsecond part\n    ImPlotTime() { S = 0; Us = 0; }\n    ImPlotTime(time_t s, int us = 0) { S  = s + us / 1000000; Us = us % 1000000; }\n    void RollOver() { S  = S + Us / 1000000;  Us = Us % 1000000; }\n    double ToDouble() const { return (double)S + (double)Us / 1000000.0; }\n    static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); }\n};\n\nstatic inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }\nstatic inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }\nstatic inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return lhs.S == rhs.S && lhs.Us == rhs.Us; }\nstatic inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }\nstatic inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return rhs < lhs; }\nstatic inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return lhs < rhs || lhs == rhs; }\nstatic inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)\n{ return lhs > rhs || lhs == rhs; }\n\n// Colormap data storage\nstruct ImPlotColormapData {\n    ImVector<ImU32> Keys;\n    ImVector<int>   KeyCounts;\n    ImVector<int>   KeyOffsets;\n    ImVector<ImU32> Tables;\n    ImVector<int>   TableSizes;\n    ImVector<int>   TableOffsets;\n    ImGuiTextBuffer Text;\n    ImVector<int>   TextOffsets;\n    ImVector<bool>  Quals;\n    ImGuiStorage    Map;\n    int             Count;\n\n    ImPlotColormapData() { Count = 0; }\n\n    int Append(const char* name, const ImU32* keys, int count, bool qual) {\n        if (GetIndex(name) != -1)\n            return -1;\n        KeyOffsets.push_back(Keys.size());\n        KeyCounts.push_back(count);\n        Keys.reserve(Keys.size()+count);\n        for (int i = 0; i < count; ++i)\n            Keys.push_back(keys[i]);\n        TextOffsets.push_back(Text.size());\n        Text.append(name, name + strlen(name) + 1);\n        Quals.push_back(qual);\n        ImGuiID id = ImHashStr(name);\n        int idx = Count++;\n        Map.SetInt(id,idx);\n        _AppendTable(idx);\n        return idx;\n    }\n\n    void _AppendTable(ImPlotColormap cmap) {\n        int key_count     = GetKeyCount(cmap);\n        const ImU32* keys = GetKeys(cmap);\n        int off = Tables.size();\n        TableOffsets.push_back(off);\n        if (IsQual(cmap)) {\n            Tables.reserve(key_count);\n            for (int i = 0; i < key_count; ++i)\n                Tables.push_back(keys[i]);\n            TableSizes.push_back(key_count);\n        }\n        else {\n            int max_size = 255 * (key_count-1) + 1;\n            Tables.reserve(off + max_size);\n            // ImU32 last = keys[0];\n            // Tables.push_back(last);\n            // int n = 1;\n            for (int i = 0; i < key_count-1; ++i) {\n                for (int s = 0; s < 255; ++s) {\n                    ImU32 a = keys[i];\n                    ImU32 b = keys[i+1];\n                    ImU32 c = ImMixU32(a,b,s);\n                    // if (c != last) {\n                        Tables.push_back(c);\n                        // last = c;\n                        // n++;\n                    // }\n                }\n            }\n            ImU32 c = keys[key_count-1];\n            // if (c != last) {\n                Tables.push_back(c);\n                // n++;\n            // }\n            // TableSizes.push_back(n);\n            TableSizes.push_back(max_size);\n        }\n    }\n\n    void RebuildTables() {\n        Tables.resize(0);\n        TableSizes.resize(0);\n        TableOffsets.resize(0);\n        for (int i = 0; i < Count; ++i)\n            _AppendTable(i);\n    }\n\n    inline bool           IsQual(ImPlotColormap cmap) const                      { return Quals[cmap];                                                }\n    inline const char*    GetName(ImPlotColormap cmap) const                     { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : nullptr; }\n    inline ImPlotColormap GetIndex(const char* name) const                       { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1);          }\n\n    inline const ImU32*   GetKeys(ImPlotColormap cmap) const                     { return &Keys[KeyOffsets[cmap]];                                    }\n    inline int            GetKeyCount(ImPlotColormap cmap) const                 { return KeyCounts[cmap];                                            }\n    inline ImU32          GetKeyColor(ImPlotColormap cmap, int idx) const        { return Keys[KeyOffsets[cmap]+idx];                                 }\n    inline void           SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables();               }\n\n    inline const ImU32*   GetTable(ImPlotColormap cmap) const                    { return &Tables[TableOffsets[cmap]];                                }\n    inline int            GetTableSize(ImPlotColormap cmap) const                { return TableSizes[cmap];                                           }\n    inline ImU32          GetTableColor(ImPlotColormap cmap, int idx) const      { return Tables[TableOffsets[cmap]+idx];                             }\n\n    inline ImU32 LerpTable(ImPlotColormap cmap, float t) const {\n        int off = TableOffsets[cmap];\n        int siz = TableSizes[cmap];\n        int idx = Quals[cmap] ? ImClamp((int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f);\n        return Tables[off + idx];\n    }\n};\n\n// ImPlotPoint with positive/negative error values\nstruct ImPlotPointError {\n    double X, Y, Neg, Pos;\n    ImPlotPointError(double x, double y, double neg, double pos) {\n        X = x; Y = y; Neg = neg; Pos = pos;\n    }\n};\n\n// Interior plot label/annotation\nstruct ImPlotAnnotation {\n    ImVec2 Pos;\n    ImVec2 Offset;\n    ImU32  ColorBg;\n    ImU32  ColorFg;\n    int    TextOffset;\n    bool   Clamp;\n    ImPlotAnnotation() {\n        ColorBg = ColorFg = 0;\n        TextOffset = 0;\n        Clamp = false;\n    }\n};\n\n// Collection of plot labels\nstruct ImPlotAnnotationCollection {\n\n    ImVector<ImPlotAnnotation> Annotations;\n    ImGuiTextBuffer            TextBuffer;\n    int                        Size;\n\n    ImPlotAnnotationCollection() { Reset(); }\n\n    void AppendV(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt,  va_list args) IM_FMTLIST(7) {\n        ImPlotAnnotation an;\n        an.Pos = pos; an.Offset = off;\n        an.ColorBg = bg; an.ColorFg = fg;\n        an.TextOffset = TextBuffer.size();\n        an.Clamp = clamp;\n        Annotations.push_back(an);\n        TextBuffer.appendfv(fmt, args);\n        const char nul[] = \"\";\n        TextBuffer.append(nul,nul+1);\n        Size++;\n    }\n\n    void Append(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt,  ...) IM_FMTARGS(7) {\n        va_list args;\n        va_start(args, fmt);\n        AppendV(pos, off, bg, fg, clamp, fmt, args);\n        va_end(args);\n    }\n\n    const char* GetText(int idx) {\n        return TextBuffer.Buf.Data + Annotations[idx].TextOffset;\n    }\n\n    void Reset() {\n        Annotations.shrink(0);\n        TextBuffer.Buf.shrink(0);\n        Size = 0;\n    }\n};\n\nstruct ImPlotTag {\n    ImAxis Axis;\n    double Value;\n    ImU32  ColorBg;\n    ImU32  ColorFg;\n    int    TextOffset;\n};\n\nstruct ImPlotTagCollection {\n\n    ImVector<ImPlotTag> Tags;\n    ImGuiTextBuffer     TextBuffer;\n    int                 Size;\n\n    ImPlotTagCollection() { Reset(); }\n\n    void AppendV(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, va_list args) IM_FMTLIST(6) {\n        ImPlotTag tag;\n        tag.Axis = axis;\n        tag.Value = value;\n        tag.ColorBg = bg;\n        tag.ColorFg = fg;\n        tag.TextOffset = TextBuffer.size();\n        Tags.push_back(tag);\n        TextBuffer.appendfv(fmt, args);\n        const char nul[] = \"\";\n        TextBuffer.append(nul,nul+1);\n        Size++;\n    }\n\n    void Append(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, ...) IM_FMTARGS(6) {\n        va_list args;\n        va_start(args, fmt);\n        AppendV(axis, value, bg, fg, fmt, args);\n        va_end(args);\n    }\n\n    const char* GetText(int idx) {\n        return TextBuffer.Buf.Data + Tags[idx].TextOffset;\n    }\n\n    void Reset() {\n        Tags.shrink(0);\n        TextBuffer.Buf.shrink(0);\n        Size = 0;\n    }\n};\n\n// Tick mark info\nstruct ImPlotTick\n{\n    double PlotPos;\n    float  PixelPos;\n    ImVec2 LabelSize;\n    int    TextOffset;\n    bool   Major;\n    bool   ShowLabel;\n    int    Level;\n    int    Idx;\n\n    ImPlotTick(double value, bool major, int level, bool show_label) {\n        PixelPos     = 0;\n        PlotPos      = value;\n        Major        = major;\n        ShowLabel    = show_label;\n        Level        = level;\n        TextOffset   = -1;\n    }\n};\n\n// Collection of ticks\nstruct ImPlotTicker {\n    ImVector<ImPlotTick> Ticks;\n    ImGuiTextBuffer      TextBuffer;\n    ImVec2               MaxSize;\n    ImVec2               LateSize;\n    int                  Levels;\n\n    ImPlotTicker() {\n        Reset();\n    }\n\n    ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) {\n        ImPlotTick tick(value, major, level, show_label);\n        if (show_label && label != nullptr) {\n            tick.TextOffset = TextBuffer.size();\n            TextBuffer.append(label, label + strlen(label) + 1);\n            tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);\n        }\n        return AddTick(tick);\n    }\n\n    ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) {\n        ImPlotTick tick(value, major, level, show_label);\n        if (show_label && formatter != nullptr) {\n            char buff[IMPLOT_LABEL_MAX_SIZE];\n            tick.TextOffset = TextBuffer.size();\n            formatter(tick.PlotPos, buff, sizeof(buff), data);\n            TextBuffer.append(buff, buff + strlen(buff) + 1);\n            tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);\n        }\n        return AddTick(tick);\n    }\n\n    inline ImPlotTick& AddTick(ImPlotTick tick) {\n        if (tick.ShowLabel) {\n            MaxSize.x     =  tick.LabelSize.x > MaxSize.x ? tick.LabelSize.x : MaxSize.x;\n            MaxSize.y     =  tick.LabelSize.y > MaxSize.y ? tick.LabelSize.y : MaxSize.y;\n        }\n        tick.Idx = Ticks.size();\n        Ticks.push_back(tick);\n        return Ticks.back();\n    }\n\n    const char* GetText(int idx) const {\n        return TextBuffer.Buf.Data + Ticks[idx].TextOffset;\n    }\n\n    const char* GetText(const ImPlotTick& tick) {\n        return GetText(tick.Idx);\n    }\n\n    void OverrideSizeLate(const ImVec2& size) {\n        LateSize.x = size.x > LateSize.x ? size.x : LateSize.x;\n        LateSize.y = size.y > LateSize.y ? size.y : LateSize.y;\n    }\n\n    void Reset() {\n        Ticks.shrink(0);\n        TextBuffer.Buf.shrink(0);\n        MaxSize = LateSize;\n        LateSize = ImVec2(0,0);\n        Levels = 1;\n    }\n\n    int TickCount() const {\n        return Ticks.Size;\n    }\n};\n\n// Axis state information that must persist after EndPlot\nstruct ImPlotAxis\n{\n    ImGuiID              ID;\n    ImPlotAxisFlags      Flags;\n    ImPlotAxisFlags      PreviousFlags;\n    ImPlotRange          Range;\n    ImPlotCond           RangeCond;\n    ImPlotScale          Scale;\n    ImPlotRange          FitExtents;\n    ImPlotAxis*          OrthoAxis;\n    ImPlotRange          ConstraintRange;\n    ImPlotRange          ConstraintZoom;\n\n    ImPlotTicker         Ticker;\n    ImPlotFormatter      Formatter;\n    void*                FormatterData;\n    char                 FormatSpec[16];\n    ImPlotLocator        Locator;\n\n    double*              LinkedMin;\n    double*              LinkedMax;\n\n    int                  PickerLevel;\n    ImPlotTime           PickerTimeMin, PickerTimeMax;\n\n    ImPlotTransform      TransformForward;\n    ImPlotTransform      TransformInverse;\n    void*                TransformData;\n    float                PixelMin, PixelMax;\n    double               ScaleMin, ScaleMax;\n    double               ScaleToPixel;\n    float                Datum1, Datum2;\n\n    ImRect               HoverRect;\n    int                  LabelOffset;\n    ImU32                ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi;\n\n    bool                 Enabled;\n    bool                 Vertical;\n    bool                 FitThisFrame;\n    bool                 HasRange;\n    bool                 HasFormatSpec;\n    bool                 ShowDefaultTicks;\n    bool                 Hovered;\n    bool                 Held;\n\n    ImPlotAxis() {\n        ID               = 0;\n        Flags            = PreviousFlags = ImPlotAxisFlags_None;\n        Range.Min        = 0;\n        Range.Max        = 1;\n        Scale            = ImPlotScale_Linear;\n        TransformForward = TransformInverse = nullptr;\n        TransformData    = nullptr;\n        FitExtents.Min   = HUGE_VAL;\n        FitExtents.Max   = -HUGE_VAL;\n        OrthoAxis        = nullptr;\n        ConstraintRange  = ImPlotRange(-INFINITY,INFINITY);\n        ConstraintZoom   = ImPlotRange(DBL_MIN,INFINITY);\n        LinkedMin        = LinkedMax = nullptr;\n        PickerLevel      = 0;\n        Datum1           = Datum2 = 0;\n        PixelMin         = PixelMax = 0;\n        LabelOffset      = -1;\n        ColorMaj         = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;\n        ColorHiLi        = IM_COL32_BLACK_TRANS;\n        Formatter        = nullptr;\n        FormatterData    = nullptr;\n        Locator          = nullptr;\n        Enabled          = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;\n        ShowDefaultTicks = true;\n    }\n\n    inline void Reset() {\n        Enabled          = false;\n        Scale            = ImPlotScale_Linear;\n        TransformForward = TransformInverse = nullptr;\n        TransformData    = nullptr;\n        LabelOffset      = -1;\n        HasFormatSpec    = false;\n        Formatter        = nullptr;\n        FormatterData    = nullptr;\n        Locator          = nullptr;\n        ShowDefaultTicks = true;\n        FitThisFrame     = false;\n        FitExtents.Min   = HUGE_VAL;\n        FitExtents.Max   = -HUGE_VAL;\n        OrthoAxis        = nullptr;\n        ConstraintRange  = ImPlotRange(-INFINITY,INFINITY);\n        ConstraintZoom   = ImPlotRange(DBL_MIN,INFINITY);\n        Ticker.Reset();\n    }\n\n    inline bool SetMin(double _min, bool force=false) {\n        if (!force && IsLockedMin())\n            return false;\n        _min = ImConstrainNan(ImConstrainInf(_min));\n        if (_min < ConstraintRange.Min)\n            _min = ConstraintRange.Min;\n        double z = Range.Max - _min;\n        if (z < ConstraintZoom.Min)\n            _min = Range.Max - ConstraintZoom.Min;\n        if (z > ConstraintZoom.Max)\n            _min = Range.Max - ConstraintZoom.Max;\n        if (_min >= Range.Max)\n            return false;\n        Range.Min = _min;\n        PickerTimeMin = ImPlotTime::FromDouble(Range.Min);\n        UpdateTransformCache();\n        return true;\n    };\n\n    inline bool SetMax(double _max, bool force=false) {\n        if (!force && IsLockedMax())\n            return false;\n        _max = ImConstrainNan(ImConstrainInf(_max));\n        if (_max > ConstraintRange.Max)\n            _max = ConstraintRange.Max;\n        double z = _max - Range.Min;\n        if (z < ConstraintZoom.Min)\n            _max = Range.Min + ConstraintZoom.Min;\n        if (z > ConstraintZoom.Max)\n            _max = Range.Min + ConstraintZoom.Max;\n        if (_max <= Range.Min)\n            return false;\n        Range.Max = _max;\n        PickerTimeMax = ImPlotTime::FromDouble(Range.Max);\n        UpdateTransformCache();\n        return true;\n    };\n\n    inline void SetRange(double v1, double v2) {\n        Range.Min = ImMin(v1,v2);\n        Range.Max = ImMax(v1,v2);\n        Constrain();\n        PickerTimeMin = ImPlotTime::FromDouble(Range.Min);\n        PickerTimeMax = ImPlotTime::FromDouble(Range.Max);\n        UpdateTransformCache();\n    }\n\n    inline void SetRange(const ImPlotRange& range) {\n        SetRange(range.Min, range.Max);\n    }\n\n    inline void SetAspect(double unit_per_pix) {\n        double new_size = unit_per_pix * PixelSize();\n        double delta    = (new_size - Range.Size()) * 0.5;\n        if (IsLocked())\n            return;\n        else if (IsLockedMin() && !IsLockedMax())\n            SetRange(Range.Min, Range.Max  + 2*delta);\n        else if (!IsLockedMin() && IsLockedMax())\n            SetRange(Range.Min - 2*delta, Range.Max);\n        else\n            SetRange(Range.Min - delta, Range.Max + delta);\n    }\n\n    inline float PixelSize() const { return ImAbs(PixelMax - PixelMin); }\n\n    inline double GetAspect() const { return Range.Size() / PixelSize(); }\n\n    inline void Constrain() {\n        Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));\n        Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));\n        if (Range.Min < ConstraintRange.Min)\n            Range.Min = ConstraintRange.Min;\n        if (Range.Max > ConstraintRange.Max)\n            Range.Max = ConstraintRange.Max;\n        double z = Range.Size();\n        if (z < ConstraintZoom.Min) {\n            double delta = (ConstraintZoom.Min - z) * 0.5;\n            Range.Min -= delta;\n            Range.Max += delta;\n        }\n        if (z > ConstraintZoom.Max) {\n            double delta = (z - ConstraintZoom.Max) * 0.5;\n            Range.Min += delta;\n            Range.Max -= delta;\n        }\n        if (Range.Max <= Range.Min)\n            Range.Max = Range.Min + DBL_EPSILON;\n    }\n\n    inline void UpdateTransformCache() {\n        ScaleToPixel = (PixelMax - PixelMin) / Range.Size();\n        if (TransformForward != nullptr) {\n            ScaleMin = TransformForward(Range.Min, TransformData);\n            ScaleMax = TransformForward(Range.Max, TransformData);\n        }\n        else {\n            ScaleMin = Range.Min;\n            ScaleMax = Range.Max;\n        }\n    }\n\n    inline float PlotToPixels(double plt) const {\n        if (TransformForward != nullptr) {\n            double s = TransformForward(plt, TransformData);\n            double t = (s - ScaleMin) / (ScaleMax - ScaleMin);\n            plt      = Range.Min + Range.Size() * t;\n        }\n        return (float)(PixelMin + ScaleToPixel * (plt - Range.Min));\n    }\n\n\n    inline double PixelsToPlot(float pix) const {\n        double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;\n        if (TransformInverse != nullptr) {\n            double t = (plt - Range.Min) / Range.Size();\n            double s = t * (ScaleMax - ScaleMin) + ScaleMin;\n            plt = TransformInverse(s, TransformData);\n        }\n        return plt;\n    }\n\n    inline void ExtendFit(double v) {\n        if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {\n            FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;\n            FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;\n        }\n    }\n\n    inline void ExtendFitWith(ImPlotAxis& alt, double v, double v_alt) {\n        if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))\n            return;\n        if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {\n            FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;\n            FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;\n        }\n    }\n\n    inline void ApplyFit(float padding) {\n        const double ext_size = FitExtents.Size() * 0.5;\n        FitExtents.Min -= ext_size * padding;\n        FitExtents.Max += ext_size * padding;\n        if (!IsLockedMin() && !ImNanOrInf(FitExtents.Min))\n            Range.Min = FitExtents.Min;\n        if (!IsLockedMax() && !ImNanOrInf(FitExtents.Max))\n            Range.Max = FitExtents.Max;\n        if (ImAlmostEqual(Range.Min, Range.Max))  {\n            Range.Max += 0.5;\n            Range.Min -= 0.5;\n        }\n        Constrain();\n        UpdateTransformCache();\n    }\n\n    inline bool HasLabel()          const { return LabelOffset != -1 && !ImHasFlag(Flags, ImPlotAxisFlags_NoLabel);                          }\n    inline bool HasGridLines()      const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoGridLines);                                           }\n    inline bool HasTickLabels()     const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels);                                          }\n    inline bool HasTickMarks()      const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickMarks);                                           }\n    inline bool WillRender()        const { return Enabled && (HasGridLines() || HasTickLabels() || HasTickMarks());                         }\n    inline bool IsOpposite()        const { return ImHasFlag(Flags, ImPlotAxisFlags_Opposite);                                               }\n    inline bool IsInverted()        const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert);                                                 }\n    inline bool IsForeground()      const { return ImHasFlag(Flags, ImPlotAxisFlags_Foreground);                                             }\n    inline bool IsAutoFitting()     const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit);                                                }\n    inline bool CanInitFit()        const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoInitialFit) && !HasRange && !LinkedMin && !LinkedMax; }\n    inline bool IsRangeLocked()     const { return HasRange && RangeCond == ImPlotCond_Always;                                               }\n    inline bool IsLockedMin()       const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin);                 }\n    inline bool IsLockedMax()       const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax);                 }\n    inline bool IsLocked()          const { return IsLockedMin() && IsLockedMax();                                                           }\n    inline bool IsInputLockedMin()  const { return IsLockedMin() || IsAutoFitting();                                                         }\n    inline bool IsInputLockedMax()  const { return IsLockedMax() || IsAutoFitting();                                                         }\n    inline bool IsInputLocked()     const { return IsLocked()    || IsAutoFitting();                                                         }\n    inline bool HasMenus()          const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoMenus);                                               }\n\n    inline bool IsPanLocked(bool increasing) {\n        if (ImHasFlag(Flags, ImPlotAxisFlags_PanStretch)) {\n            return IsInputLocked();\n        }\n        else {\n            if (IsLockedMin() || IsLockedMax() || IsAutoFitting())\n                return false;\n            if (increasing)\n                return Range.Max == ConstraintRange.Max;\n            else\n                return Range.Min == ConstraintRange.Min;\n        }\n    }\n\n    void PushLinks() {\n        if (LinkedMin) { *LinkedMin = Range.Min; }\n        if (LinkedMax) { *LinkedMax = Range.Max; }\n    }\n\n    void PullLinks() {\n        if (LinkedMin) { SetMin(*LinkedMin,true); }\n        if (LinkedMax) { SetMax(*LinkedMax,true); }\n    }\n};\n\n// Align plots group data\nstruct ImPlotAlignmentData {\n    bool  Vertical;\n    float PadA;\n    float PadB;\n    float PadAMax;\n    float PadBMax;\n    ImPlotAlignmentData() {\n        Vertical    = true;\n        PadA = PadB = PadAMax = PadBMax = 0;\n    }\n    void Begin() { PadAMax = PadBMax = 0; }\n    void Update(float& pad_a, float& pad_b, float& delta_a, float& delta_b) {\n        float bak_a = pad_a; float bak_b = pad_b;\n        if (PadAMax < pad_a) { PadAMax = pad_a; }\n        if (PadBMax < pad_b) { PadBMax = pad_b; }\n        if (pad_a < PadA)    { pad_a = PadA; delta_a = pad_a - bak_a; } else { delta_a = 0; }\n        if (pad_b < PadB)    { pad_b = PadB; delta_b = pad_b - bak_b; } else { delta_b = 0; }\n    }\n    void End()   { PadA = PadAMax; PadB = PadBMax;      }\n    void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }\n};\n\n// State information for Plot items\nstruct ImPlotItem\n{\n    ImGuiID      ID;\n    ImU32        Color;\n    ImRect       LegendHoverRect;\n    int          NameOffset;\n    bool         Show;\n    bool         LegendHovered;\n    bool         SeenThisFrame;\n\n    ImPlotItem() {\n        ID            = 0;\n        Color         = IM_COL32_WHITE;\n        NameOffset    = -1;\n        Show          = true;\n        SeenThisFrame = false;\n        LegendHovered = false;\n    }\n\n    ~ImPlotItem() { ID = 0; }\n};\n\n// Holds Legend state\nstruct ImPlotLegend\n{\n    ImPlotLegendFlags Flags;\n    ImPlotLegendFlags PreviousFlags;\n    ImPlotLocation    Location;\n    ImPlotLocation    PreviousLocation;\n    ImVector<int>     Indices;\n    ImGuiTextBuffer   Labels;\n    ImRect            Rect;\n    bool              Hovered;\n    bool              Held;\n    bool              CanGoInside;\n\n    ImPlotLegend() {\n        Flags        = PreviousFlags = ImPlotLegendFlags_None;\n        CanGoInside  = true;\n        Hovered      = Held = false;\n        Location     = PreviousLocation = ImPlotLocation_NorthWest;\n    }\n\n    void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }\n};\n\n// Holds Items and Legend data\nstruct ImPlotItemGroup\n{\n    ImGuiID            ID;\n    ImPlotLegend       Legend;\n    ImPool<ImPlotItem> ItemPool;\n    int                ColormapIdx;\n\n    ImPlotItemGroup() { ID = 0; ColormapIdx = 0; }\n\n    int         GetItemCount() const             { return ItemPool.GetBufSize();                                 }\n    ImGuiID     GetItemID(const char*  label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */            }\n    ImPlotItem* GetItem(ImGuiID id)              { return ItemPool.GetByKey(id);                                 }\n    ImPlotItem* GetItem(const char* label_id)    { return GetItem(GetItemID(label_id));                          }\n    ImPlotItem* GetOrAddItem(ImGuiID id)         { return ItemPool.GetOrAddByKey(id);                            }\n    ImPlotItem* GetItemByIndex(int i)            { return ItemPool.GetByIndex(i);                                }\n    int         GetItemIndex(ImPlotItem* item)   { return ItemPool.GetIndex(item);                               }\n    int         GetLegendCount() const           { return Legend.Indices.size();                                 }\n    ImPlotItem* GetLegendItem(int i)             { return ItemPool.GetByIndex(Legend.Indices[i]);                }\n    const char* GetLegendLabel(int i)            { return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; }\n    void        Reset()                          { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0;            }\n};\n\n// Holds Plot state information that must persist after EndPlot\nstruct ImPlotPlot\n{\n    ImGuiID              ID;\n    ImPlotFlags          Flags;\n    ImPlotFlags          PreviousFlags;\n    ImPlotLocation       MouseTextLocation;\n    ImPlotMouseTextFlags MouseTextFlags;\n    ImPlotAxis           Axes[ImAxis_COUNT];\n    ImGuiTextBuffer      TextBuffer;\n    ImPlotItemGroup      Items;\n    ImAxis               CurrentX;\n    ImAxis               CurrentY;\n    ImRect               FrameRect;\n    ImRect               CanvasRect;\n    ImRect               PlotRect;\n    ImRect               AxesRect;\n    ImRect               SelectRect;\n    ImVec2               SelectStart;\n    int                  TitleOffset;\n    bool                 JustCreated;\n    bool                 Initialized;\n    bool                 SetupLocked;\n    bool                 FitThisFrame;\n    bool                 Hovered;\n    bool                 Held;\n    bool                 Selecting;\n    bool                 Selected;\n    bool                 ContextLocked;\n\n    ImPlotPlot() {\n        Flags             = PreviousFlags = ImPlotFlags_None;\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)\n            XAxis(i).Vertical = false;\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)\n            YAxis(i).Vertical = true;\n        SelectStart       = ImVec2(0,0);\n        CurrentX          = ImAxis_X1;\n        CurrentY          = ImAxis_Y1;\n        MouseTextLocation  = ImPlotLocation_South | ImPlotLocation_East;\n        MouseTextFlags     = ImPlotMouseTextFlags_None;\n        TitleOffset       = -1;\n        JustCreated       = true;\n        Initialized = SetupLocked = FitThisFrame = false;\n        Hovered = Held = Selected = Selecting = ContextLocked = false;\n    }\n\n    inline bool IsInputLocked() const {\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {\n            if (!XAxis(i).IsInputLocked())\n                return false;\n        }\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {\n            if (!YAxis(i).IsInputLocked())\n                return false;\n        }\n        return true;\n    }\n\n    inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }\n\n    inline void SetTitle(const char* title) {\n        if (title && ImGui::FindRenderedTextEnd(title, nullptr) != title) {\n            TitleOffset = TextBuffer.size();\n            TextBuffer.append(title, title + strlen(title) + 1);\n        }\n        else {\n            TitleOffset = -1;\n        }\n    }\n    inline bool HasTitle() const { return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); }\n    inline const char* GetTitle() const { return TextBuffer.Buf.Data + TitleOffset; }\n\n    inline       ImPlotAxis& XAxis(int i)       { return Axes[ImAxis_X1 + i]; }\n    inline const ImPlotAxis& XAxis(int i) const { return Axes[ImAxis_X1 + i]; }\n    inline       ImPlotAxis& YAxis(int i)       { return Axes[ImAxis_Y1 + i]; }\n    inline const ImPlotAxis& YAxis(int i) const { return Axes[ImAxis_Y1 + i]; }\n\n    inline int EnabledAxesX() {\n        int cnt = 0;\n        for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)\n            cnt += XAxis(i).Enabled;\n        return cnt;\n    }\n\n    inline int EnabledAxesY() {\n        int cnt = 0;\n        for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)\n            cnt += YAxis(i).Enabled;\n        return cnt;\n    }\n\n    inline void SetAxisLabel(ImPlotAxis& axis, const char* label) {\n        if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label) {\n            axis.LabelOffset = TextBuffer.size();\n            TextBuffer.append(label, label + strlen(label) + 1);\n        }\n        else {\n            axis.LabelOffset = -1;\n        }\n    }\n\n    inline const char* GetAxisLabel(const ImPlotAxis& axis) const { return TextBuffer.Buf.Data + axis.LabelOffset; }\n};\n\n// Holds subplot data that must persist after EndSubplot\nstruct ImPlotSubplot {\n    ImGuiID                       ID;\n    ImPlotSubplotFlags            Flags;\n    ImPlotSubplotFlags            PreviousFlags;\n    ImPlotItemGroup               Items;\n    int                           Rows;\n    int                           Cols;\n    int                           CurrentIdx;\n    ImRect                        FrameRect;\n    ImRect                        GridRect;\n    ImVec2                        CellSize;\n    ImVector<ImPlotAlignmentData> RowAlignmentData;\n    ImVector<ImPlotAlignmentData> ColAlignmentData;\n    ImVector<float>               RowRatios;\n    ImVector<float>               ColRatios;\n    ImVector<ImPlotRange>         RowLinkData;\n    ImVector<ImPlotRange>         ColLinkData;\n    float                         TempSizes[2];\n    bool                          FrameHovered;\n    bool                          HasTitle;\n\n    ImPlotSubplot() {\n        ID                          = 0;\n        Flags = PreviousFlags       = ImPlotSubplotFlags_None;\n        Rows = Cols = CurrentIdx    = 0;\n        FrameHovered                = false;\n        Items.Legend.Location       = ImPlotLocation_North;\n        Items.Legend.Flags          = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;\n        Items.Legend.CanGoInside    = false;\n        TempSizes[0] = TempSizes[1] = 0;\n        FrameHovered                = false;\n        HasTitle                    = false;\n    }\n};\n\n// Temporary data storage for upcoming plot\nstruct ImPlotNextPlotData\n{\n    ImPlotCond  RangeCond[ImAxis_COUNT];\n    ImPlotRange Range[ImAxis_COUNT];\n    bool        HasRange[ImAxis_COUNT];\n    bool        Fit[ImAxis_COUNT];\n    double*     LinkedMin[ImAxis_COUNT];\n    double*     LinkedMax[ImAxis_COUNT];\n\n    ImPlotNextPlotData() { Reset(); }\n\n    void Reset() {\n        for (int i = 0; i < ImAxis_COUNT; ++i) {\n            HasRange[i]                 = false;\n            Fit[i]                      = false;\n            LinkedMin[i] = LinkedMax[i] = nullptr;\n        }\n    }\n\n};\n\n// Temporary data storage for upcoming item\nstruct ImPlotNextItemData {\n    ImVec4          Colors[5]; // ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar\n    float           LineWeight;\n    ImPlotMarker    Marker;\n    float           MarkerSize;\n    float           MarkerWeight;\n    float           FillAlpha;\n    float           ErrorBarSize;\n    float           ErrorBarWeight;\n    float           DigitalBitHeight;\n    float           DigitalBitGap;\n    bool            RenderLine;\n    bool            RenderFill;\n    bool            RenderMarkerLine;\n    bool            RenderMarkerFill;\n    bool            HasHidden;\n    bool            Hidden;\n    ImPlotCond      HiddenCond;\n    ImPlotNextItemData() { Reset(); }\n    void Reset() {\n        for (int i = 0; i < 5; ++i)\n            Colors[i] = IMPLOT_AUTO_COL;\n        LineWeight    = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;\n        Marker        = IMPLOT_AUTO;\n        HasHidden     = Hidden = false;\n    }\n};\n\n// Holds state information that must persist between calls to BeginPlot()/EndPlot()\nstruct ImPlotContext {\n    // Plot States\n    ImPool<ImPlotPlot>    Plots;\n    ImPool<ImPlotSubplot> Subplots;\n    ImPlotPlot*           CurrentPlot;\n    ImPlotSubplot*        CurrentSubplot;\n    ImPlotItemGroup*      CurrentItems;\n    ImPlotItem*           CurrentItem;\n    ImPlotItem*           PreviousItem;\n\n    // Tick Marks and Labels\n    ImPlotTicker CTicker;\n\n    // Annotation and Tabs\n    ImPlotAnnotationCollection Annotations;\n    ImPlotTagCollection        Tags;\n\n    // Flags\n    bool ChildWindowMade;\n\n    // Style and Colormaps\n    ImPlotStyle                 Style;\n    ImVector<ImGuiColorMod>     ColorModifiers;\n    ImVector<ImGuiStyleMod>     StyleModifiers;\n    ImPlotColormapData          ColormapData;\n    ImVector<ImPlotColormap>    ColormapModifiers;\n\n    // Time\n    tm Tm;\n\n    // Temp data for general use\n    ImVector<double>   TempDouble1, TempDouble2;\n    ImVector<int>      TempInt1;\n\n    // Misc\n    int                DigitalPlotItemCnt;\n    int                DigitalPlotOffset;\n    ImPlotNextPlotData NextPlotData;\n    ImPlotNextItemData NextItemData;\n    ImPlotInputMap     InputMap;\n    bool               OpenContextThisFrame;\n    ImGuiTextBuffer    MousePosStringBuilder;\n    ImPlotItemGroup*   SortItems;\n\n    // Align plots\n    ImPool<ImPlotAlignmentData> AlignmentData;\n    ImPlotAlignmentData*        CurrentAlignmentH;\n    ImPlotAlignmentData*        CurrentAlignmentV;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Internal API\n// No guarantee of forward compatibility here!\n//-----------------------------------------------------------------------------\n\nnamespace ImPlot {\n\n//-----------------------------------------------------------------------------\n// [SECTION] Context Utils\n//-----------------------------------------------------------------------------\n\n// Initializes an ImPlotContext\nIMPLOT_API void Initialize(ImPlotContext* ctx);\n// Resets an ImPlot context for the next call to BeginPlot\nIMPLOT_API void ResetCtxForNextPlot(ImPlotContext* ctx);\n// Resets an ImPlot context for the next call to BeginAlignedPlots\nIMPLOT_API void ResetCtxForNextAlignedPlots(ImPlotContext* ctx);\n// Resets an ImPlot context for the next call to BeginSubplot\nIMPLOT_API void ResetCtxForNextSubplot(ImPlotContext* ctx);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Plot Utils\n//-----------------------------------------------------------------------------\n\n// Gets a plot from the current ImPlotContext\nIMPLOT_API ImPlotPlot* GetPlot(const char* title);\n// Gets the current plot from the current ImPlotContext\nIMPLOT_API ImPlotPlot* GetCurrentPlot();\n// Busts the cache for every plot in the current context\nIMPLOT_API void BustPlotCache();\n\n// Shows a plot's context menu.\nIMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Setup Utils\n//-----------------------------------------------------------------------------\n\n// Lock Setup and call SetupFinish if necessary.\nstatic inline void SetupLock() {\n    ImPlotContext& gp = *GImPlot;\n    if (!gp.CurrentPlot->SetupLocked)\n        SetupFinish();\n    gp.CurrentPlot->SetupLocked = true;\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Subplot Utils\n//-----------------------------------------------------------------------------\n\n// Advances to next subplot\nIMPLOT_API void SubplotNextCell();\n\n// Shows a subplot's context menu.\nIMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Item Utils\n//-----------------------------------------------------------------------------\n\n// Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect.\nIMPLOT_API bool BeginItem(const char* label_id, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO);\n\n// Same as above but with fitting functionality.\ntemplate <typename _Fitter>\nbool BeginItemEx(const char* label_id, const _Fitter& fitter, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO) {\n    if (BeginItem(label_id, flags, recolor_from)) {\n        ImPlotPlot& plot = *GetCurrentPlot();\n        if (plot.FitThisFrame && !ImHasFlag(flags, ImPlotItemFlags_NoFit))\n            fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]);\n        return true;\n    }\n    return false;\n}\n\n// Ends an item (call only if BeginItem returns true). Pops PlotClipRect.\nIMPLOT_API void EndItem();\n\n// Register or get an existing item from the current plot.\nIMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr);\n// Get a plot item from the current plot.\nIMPLOT_API ImPlotItem* GetItem(const char* label_id);\n// Gets the current item.\nIMPLOT_API ImPlotItem* GetCurrentItem();\n// Busts the cache for every item for every plot in the current context.\nIMPLOT_API void BustItemCache();\n\n//-----------------------------------------------------------------------------\n// [SECTION] Axis Utils\n//-----------------------------------------------------------------------------\n\n// Returns true if any enabled axis is locked from user input.\nstatic inline bool AnyAxesInputLocked(ImPlotAxis* axes, int count) {\n    for (int i = 0; i < count; ++i) {\n        if (axes[i].Enabled && axes[i].IsInputLocked())\n            return true;\n    }\n    return false;\n}\n\n// Returns true if all enabled axes are locked from user input.\nstatic inline bool AllAxesInputLocked(ImPlotAxis* axes, int count) {\n    for (int i = 0; i < count; ++i) {\n        if (axes[i].Enabled && !axes[i].IsInputLocked())\n            return false;\n    }\n    return true;\n}\n\nstatic inline bool AnyAxesHeld(ImPlotAxis* axes, int count) {\n    for (int i = 0; i < count; ++i) {\n        if (axes[i].Enabled && axes[i].Held)\n            return true;\n    }\n    return false;\n}\n\nstatic inline bool AnyAxesHovered(ImPlotAxis* axes, int count) {\n    for (int i = 0; i < count; ++i) {\n        if (axes[i].Enabled && axes[i].Hovered)\n            return true;\n    }\n    return false;\n}\n\n// Returns true if the user has requested data to be fit.\nstatic inline bool FitThisFrame() {\n    return GImPlot->CurrentPlot->FitThisFrame;\n}\n\n// Extends the current plot's axes so that it encompasses a vertical line at x\nstatic inline void FitPointX(double x) {\n    ImPlotPlot& plot   = *GetCurrentPlot();\n    ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];\n    x_axis.ExtendFit(x);\n}\n\n// Extends the current plot's axes so that it encompasses a horizontal line at y\nstatic inline void FitPointY(double y) {\n    ImPlotPlot& plot   = *GetCurrentPlot();\n    ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];\n    y_axis.ExtendFit(y);\n}\n\n// Extends the current plot's axes so that it encompasses point p\nstatic inline void FitPoint(const ImPlotPoint& p) {\n    ImPlotPlot& plot   = *GetCurrentPlot();\n    ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];\n    ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];\n    x_axis.ExtendFitWith(y_axis, p.x, p.y);\n    y_axis.ExtendFitWith(x_axis, p.y, p.x);\n}\n\n// Returns true if two ranges overlap\nstatic inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)\n{ return r1.Min <= r2.Max && r2.Min <= r1.Max; }\n\n// Shows an axis's context menu.\nIMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Legend Utils\n//-----------------------------------------------------------------------------\n\n// Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.\nIMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));\n// Calculates the bounding box size of a legend\nIMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);\n// Renders legend entries into a bounding box\nIMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);\n// Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window!).\nIMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true);\n// Shows an legends's context menu.\nIMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Label Utils\n//-----------------------------------------------------------------------------\n\n// Create a a string label for a an axis value\nIMPLOT_API void LabelAxisValue(const ImPlotAxis& axis, double value, char* buff, int size, bool round = false);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Styling Utils\n//-----------------------------------------------------------------------------\n\n// Get styling data for next item (call between Begin/EndItem)\nstatic inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItemData; }\n\n// Returns true if a color is set to be automatically determined\nstatic inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }\n// Returns true if a style color is set to be automatically determined\nstatic inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }\n// Returns the automatically deduced style color\nIMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);\n\n// Returns the style color whether it is automatic or custom set\nstatic inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }\nstatic inline ImU32  GetStyleColorU32(ImPlotCol idx)  { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }\n\n// Draws vertical text. The position is the bottom left of the text rect.\nIMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr);\n// Draws multiline horizontal text centered.\nIMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr);\n// Calculates the size of vertical text\nstatic inline ImVec2 CalcTextSizeVertical(const char *text) {\n    ImVec2 sz = ImGui::CalcTextSize(text);\n    return ImVec2(sz.y, sz.x);\n}\n// Returns white or black text given background color\nstatic inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE; }\nstatic inline ImU32 CalcTextColor(ImU32 bg)         { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }\n// Lightens or darkens a color for hover\nstatic inline ImU32 CalcHoverColor(ImU32 col)       {  return ImMixU32(col, CalcTextColor(col), 32); }\n\n// Clamps a label position so that it fits a rect defined by Min/Max\nstatic inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {\n    if (pos.x < Min.x)              pos.x = Min.x;\n    if (pos.y < Min.y)              pos.y = Min.y;\n    if ((pos.x + size.x) > Max.x)   pos.x = Max.x - size.x;\n    if ((pos.y + size.y) > Max.y)   pos.y = Max.y - size.y;\n    return pos;\n}\n\n// Returns a color from the Color map given an index >= 0 (modulo will be performed).\nIMPLOT_API ImU32  GetColormapColorU32(int idx, ImPlotColormap cmap);\n// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.\nIMPLOT_API ImU32  NextColormapColorU32();\n// Linearly interpolates a color from the current colormap given t between 0 and 1.\nIMPLOT_API ImU32  SampleColormapU32(float t, ImPlotColormap cmap);\n\n// Render a colormap bar\nIMPLOT_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Math and Misc Utils\n//-----------------------------------------------------------------------------\n\n// Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2)\nIMPLOT_API double NiceNum(double x, bool round);\n// Computes order of magnitude of double.\nstatic inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }\n// Returns the precision required for a order of magnitude.\nstatic inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }\n// Returns a floating point precision to use given a value\nstatic inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }\n// Round a value to a given precision\nstatic inline double RoundTo(double val, int prec) { double p = pow(10,(double)prec); return floor(val*p+0.5)/p; }\n\n// Returns the intersection point of two lines A and B (assumes they are not parallel!)\nstatic inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {\n    float v1 = (a1.x * a2.y - a1.y * a2.x);  float v2 = (b1.x * b2.y - b1.y * b2.x);\n    float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x));\n    return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3);\n}\n\n// Fills a buffer with n samples linear interpolated from vmin to vmax\ntemplate <typename T>\nvoid FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {\n    buffer.resize(n);\n    T step = (vmax - vmin) / (n - 1);\n    for (int i = 0; i < n; ++i) {\n        buffer[i] = vmin + i * step;\n    }\n}\n\n// Calculate histogram bin counts and widths\ntemplate <typename T>\nstatic inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {\n    switch (meth) {\n        case ImPlotBin_Sqrt:\n            bins_out  = (int)ceil(sqrt(count));\n            break;\n        case ImPlotBin_Sturges:\n            bins_out  = (int)ceil(1.0 + log2(count));\n            break;\n        case ImPlotBin_Rice:\n            bins_out  = (int)ceil(2 * cbrt(count));\n            break;\n        case ImPlotBin_Scott:\n            width_out = 3.49 * ImStdDev(values, count) / cbrt(count);\n            bins_out  = (int)round(range.Size() / width_out);\n            break;\n    }\n    width_out = range.Size() / bins_out;\n}\n\n//-----------------------------------------------------------------------------\n// Time Utils\n//-----------------------------------------------------------------------------\n\n// Returns true if year is leap year (366 days long)\nstatic inline bool IsLeapYear(int year) {\n    return  year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);\n}\n// Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed.\nstatic inline int GetDaysInMonth(int year, int month) {\n    static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};\n    return  days[month] + (int)(month == 1 && IsLeapYear(year));\n}\n\n// Make a UNIX timestamp from a tm struct expressed in UTC time (i.e. GMT timezone).\nIMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm);\n// Make a tm struct expressed in UTC time (i.e. GMT timezone) from a UNIX timestamp.\nIMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm);\n\n// Make a UNIX timestamp from a tm struct expressed in local time.\nIMPLOT_API ImPlotTime MkLocTime(struct tm *ptm);\n// Make a tm struct expressed in local time from a UNIX timestamp.\nIMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);\n\n// NB: The following functions only work if there is a current ImPlotContext because the\n// internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime.\n\n// Make a timestamp from time components.\n// year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999]\nIMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);\n// Get year component from timestamp [1970-3000]\nIMPLOT_API int GetYear(const ImPlotTime& t);\n\n// Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract.\nIMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);\n// Rounds a timestamp down to nearest unit.\nIMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);\n// Rounds a timestamp up to the nearest unit.\nIMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);\n// Rounds a timestamp up or down to the nearest unit.\nIMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);\n// Combines the date of one timestamp with the time-of-day of another timestamp.\nIMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);\n\n// Formats the time part of timestamp t into a buffer according to #fmt\nIMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk);\n// Formats the date part of timestamp t into a buffer according to #fmt\nIMPLOT_API int FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601);\n// Formats the time and/or date parts of a timestamp t into a buffer according to #fmt\nIMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeSpec fmt);\n\n// Shows a date picker widget block (year/month/day).\n// #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.\n// #t will be set when a day is clicked and the function will return true.\n// #t1 and #t2 are optional dates to highlight.\nIMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr);\n// Shows a time picker widget block (hour/min/sec).\n// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.\nIMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);\n\n//-----------------------------------------------------------------------------\n// [SECTION] Transforms\n//-----------------------------------------------------------------------------\n\nstatic inline double TransformForward_Log10(double v, void*) {\n    v = v <= 0.0 ? DBL_MIN : v;\n    return ImLog10(v);\n}\n\nstatic inline double TransformInverse_Log10(double v, void*) {\n    return ImPow(10, v);\n}\n\nstatic inline double TransformForward_SymLog(double v, void*) {\n    return 2.0 * ImAsinh(v / 2.0);\n}\n\nstatic inline double TransformInverse_SymLog(double v, void*) {\n    return 2.0 * ImSinh(v / 2.0);\n}\n\nstatic inline double TransformForward_Logit(double v, void*) {\n    v = ImClamp(v, DBL_MIN, 1.0 - DBL_EPSILON);\n    return ImLog10(v / (1 - v));\n}\n\nstatic inline double TransformInverse_Logit(double v, void*) {\n    return 1.0 / (1.0 + ImPow(10,-v));\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Formatters\n//-----------------------------------------------------------------------------\n\nstatic inline int Formatter_Default(double value, char* buff, int size, void* data) {\n    char* fmt = (char*)data;\n    return ImFormatString(buff, size, fmt, value);\n}\n\nstatic inline int Formatter_Logit(double value, char* buff, int size, void*) {\n    if (value == 0.5)\n        return ImFormatString(buff,size,\"1/2\");\n    else if (value < 0.5)\n        return ImFormatString(buff,size,\"%g\", value);\n    else\n        return ImFormatString(buff,size,\"1 - %g\", 1 - value);\n}\n\nstruct Formatter_Time_Data {\n    ImPlotTime Time;\n    ImPlotDateTimeSpec Spec;\n    ImPlotFormatter UserFormatter;\n    void* UserFormatterData;\n};\n\nstatic inline int Formatter_Time(double, char* buff, int size, void* data) {\n    Formatter_Time_Data* ftd = (Formatter_Time_Data*)data;\n    return FormatDateTime(ftd->Time, buff, size, ftd->Spec);\n}\n\n//------------------------------------------------------------------------------\n// [SECTION] Locator\n//------------------------------------------------------------------------------\n\nvoid Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);\nvoid Locator_Time(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);\nvoid Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);\nvoid Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);\n\n} // namespace ImPlot\n"
  },
  {
    "path": "Source/External/imgui_tools/implot/implot_items.cpp",
    "content": "// MIT License\n\n// Copyright (c) 2020 Evan Pezent\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// ImPlot v0.14\n\n#define IMGUI_DEFINE_MATH_OPERATORS\n#include \"implot.h\"\n#include \"implot_internal.h\"\n\n//-----------------------------------------------------------------------------\n// [SECTION] Macros and Defines\n//-----------------------------------------------------------------------------\n\n#define SQRT_1_2 0.70710678118f\n#define SQRT_3_2 0.86602540378f\n\n#ifndef IMPLOT_NO_FORCE_INLINE\n    #ifdef _MSC_VER\n        #define IMPLOT_INLINE __forceinline\n    #elif defined(__GNUC__)\n        #define IMPLOT_INLINE inline __attribute__((__always_inline__))\n    #elif defined(__CLANG__)\n        #if __has_attribute(__always_inline__)\n            #define IMPLOT_INLINE inline __attribute__((__always_inline__))\n        #else\n            #define IMPLOT_INLINE inline\n        #endif\n    #else\n        #define IMPLOT_INLINE inline\n    #endif\n#else\n    #define IMPLOT_INLINE inline\n#endif\n\n#if defined __SSE__ || defined __x86_64__ || defined _M_X64\n#ifndef IMGUI_ENABLE_SSE\n#include <immintrin.h>\n#endif\nstatic IMPLOT_INLINE float  ImInvSqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }\n#else\nstatic IMPLOT_INLINE float  ImInvSqrt(float x) { return 1.0f / sqrtf(x); }\n#endif\n\n#define IMPLOT_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImInvSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)\n\n// Support for pre-1.82 versions. Users on 1.82+ can use 0 (default) flags to mean \"all corners\" but in order to support older versions we are more explicit.\n#if (IMGUI_VERSION_NUM < 18102) && !defined(ImDrawFlags_RoundCornersAll)\n#define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All\n#endif\n\n//-----------------------------------------------------------------------------\n// [SECTION] Template instantiation utility\n//-----------------------------------------------------------------------------\n\n// By default, templates are instantiated for `float`, `double`, and for the following integer types, which are defined in imgui.h:\n//     signed char         ImS8;   // 8-bit signed integer\n//     unsigned char       ImU8;   // 8-bit unsigned integer\n//     signed short        ImS16;  // 16-bit signed integer\n//     unsigned short      ImU16;  // 16-bit unsigned integer\n//     signed int          ImS32;  // 32-bit signed integer == int\n//     unsigned int        ImU32;  // 32-bit unsigned integer\n//     signed   long long  ImS64;  // 64-bit signed integer\n//     unsigned long long  ImU64;  // 64-bit unsigned integer\n// (note: this list does *not* include `long`, `unsigned long` and `long double`)\n//\n// You can customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list.\n//    As an example, you could use the compile time define given by the line below in order to support only float and double.\n//        -DIMPLOT_CUSTOM_NUMERIC_TYPES=\"(float)(double)\"\n//    In order to support all known C++ types, use:\n//        -DIMPLOT_CUSTOM_NUMERIC_TYPES=\"(signed char)(unsigned char)(signed short)(unsigned short)(signed int)(unsigned int)(signed long)(unsigned long)(signed long long)(unsigned long long)(float)(double)(long double)\"\n\n#ifdef IMPLOT_CUSTOM_NUMERIC_TYPES\n    #define IMPLOT_NUMERIC_TYPES IMPLOT_CUSTOM_NUMERIC_TYPES\n#else\n    #define IMPLOT_NUMERIC_TYPES (ImS8)(ImU8)(ImS16)(ImU16)(ImS32)(ImU32)(ImS64)(ImU64)(float)(double)\n#endif\n\n// CALL_INSTANTIATE_FOR_NUMERIC_TYPES will duplicate the template instantion code `INSTANTIATE_MACRO(T)` on supported types.\n#define _CAT(x, y) _CAT_(x, y)\n#define _CAT_(x,y) x ## y\n#define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END)\n#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_2\n#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_1\n#define _INSTANTIATE_FOR_NUMERIC_TYPES_1_END\n#define _INSTANTIATE_FOR_NUMERIC_TYPES_2_END\n#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES);\n\nnamespace ImPlot {\n\n//-----------------------------------------------------------------------------\n// [SECTION] Utils\n//-----------------------------------------------------------------------------\n\n// Calc maximum index size of ImDrawIdx\ntemplate <typename T>\nstruct MaxIdx { static const unsigned int Value; };\ntemplate <> const unsigned int MaxIdx<unsigned short>::Value = 65535;\ntemplate <> const unsigned int MaxIdx<unsigned int>::Value   = 4294967295;\n\nIMPLOT_INLINE void GetLineRenderProps(const ImDrawList& draw_list, float& half_weight, ImVec2& tex_uv0, ImVec2& tex_uv1) {\n    const bool aa = ImHasFlag(draw_list.Flags, ImDrawListFlags_AntiAliasedLines) &&\n                    ImHasFlag(draw_list.Flags, ImDrawListFlags_AntiAliasedLinesUseTex);\n    if (aa) {\n        ImVec4 tex_uvs = draw_list._Data->TexUvLines[(int)(half_weight*2)];\n        tex_uv0 = ImVec2(tex_uvs.x, tex_uvs.y);\n        tex_uv1 = ImVec2(tex_uvs.z, tex_uvs.w);\n        half_weight += 1;\n    }\n    else {\n        tex_uv0 = tex_uv1 = draw_list._Data->TexUvWhitePixel;\n    }\n}\n\nIMPLOT_INLINE void PrimLine(ImDrawList& draw_list, const ImVec2& P1, const ImVec2& P2, float half_weight, ImU32 col, const ImVec2& tex_uv0, const ImVec2 tex_uv1) {\n    float dx = P2.x - P1.x;\n    float dy = P2.y - P1.y;\n    IMPLOT_NORMALIZE2F_OVER_ZERO(dx, dy);\n    dx *= half_weight;\n    dy *= half_weight;\n    draw_list._VtxWritePtr[0].pos.x = P1.x + dy;\n    draw_list._VtxWritePtr[0].pos.y = P1.y - dx;\n    draw_list._VtxWritePtr[0].uv    = tex_uv0;\n    draw_list._VtxWritePtr[0].col   = col;\n    draw_list._VtxWritePtr[1].pos.x = P2.x + dy;\n    draw_list._VtxWritePtr[1].pos.y = P2.y - dx;\n    draw_list._VtxWritePtr[1].uv    = tex_uv0;\n    draw_list._VtxWritePtr[1].col   = col;\n    draw_list._VtxWritePtr[2].pos.x = P2.x - dy;\n    draw_list._VtxWritePtr[2].pos.y = P2.y + dx;\n    draw_list._VtxWritePtr[2].uv    = tex_uv1;\n    draw_list._VtxWritePtr[2].col   = col;\n    draw_list._VtxWritePtr[3].pos.x = P1.x - dy;\n    draw_list._VtxWritePtr[3].pos.y = P1.y + dx;\n    draw_list._VtxWritePtr[3].uv    = tex_uv1;\n    draw_list._VtxWritePtr[3].col   = col;\n    draw_list._VtxWritePtr += 4;\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2);\n    draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx);\n    draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2);\n    draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3);\n    draw_list._IdxWritePtr += 6;\n    draw_list._VtxCurrentIdx += 4;\n}\n\nIMPLOT_INLINE void PrimRectFill(ImDrawList& draw_list, const ImVec2& Pmin, const ImVec2& Pmax, ImU32 col, const ImVec2& uv) {\n    draw_list._VtxWritePtr[0].pos   = Pmin;\n    draw_list._VtxWritePtr[0].uv    = uv;\n    draw_list._VtxWritePtr[0].col   = col;\n    draw_list._VtxWritePtr[1].pos   = Pmax;\n    draw_list._VtxWritePtr[1].uv    = uv;\n    draw_list._VtxWritePtr[1].col   = col;\n    draw_list._VtxWritePtr[2].pos.x = Pmin.x;\n    draw_list._VtxWritePtr[2].pos.y = Pmax.y;\n    draw_list._VtxWritePtr[2].uv    = uv;\n    draw_list._VtxWritePtr[2].col   = col;\n    draw_list._VtxWritePtr[3].pos.x = Pmax.x;\n    draw_list._VtxWritePtr[3].pos.y = Pmin.y;\n    draw_list._VtxWritePtr[3].uv    = uv;\n    draw_list._VtxWritePtr[3].col   = col;\n    draw_list._VtxWritePtr += 4;\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2);\n    draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx);\n    draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n    draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3);\n    draw_list._IdxWritePtr += 6;\n    draw_list._VtxCurrentIdx += 4;\n}\n\nIMPLOT_INLINE void PrimRectLine(ImDrawList& draw_list, const ImVec2& Pmin, const ImVec2& Pmax, float weight, ImU32 col, const ImVec2& uv) {\n\n    draw_list._VtxWritePtr[0].pos.x = Pmin.x;\n    draw_list._VtxWritePtr[0].pos.y = Pmin.y;\n    draw_list._VtxWritePtr[0].uv    = uv;\n    draw_list._VtxWritePtr[0].col   = col;\n\n    draw_list._VtxWritePtr[1].pos.x = Pmin.x;\n    draw_list._VtxWritePtr[1].pos.y = Pmax.y;\n    draw_list._VtxWritePtr[1].uv    = uv;\n    draw_list._VtxWritePtr[1].col   = col;\n\n    draw_list._VtxWritePtr[2].pos.x = Pmax.x;\n    draw_list._VtxWritePtr[2].pos.y = Pmax.y;\n    draw_list._VtxWritePtr[2].uv    = uv;\n    draw_list._VtxWritePtr[2].col   = col;\n\n    draw_list._VtxWritePtr[3].pos.x = Pmax.x;\n    draw_list._VtxWritePtr[3].pos.y = Pmin.y;\n    draw_list._VtxWritePtr[3].uv    = uv;\n    draw_list._VtxWritePtr[3].col   = col;\n\n    draw_list._VtxWritePtr[4].pos.x = Pmin.x + weight;\n    draw_list._VtxWritePtr[4].pos.y = Pmin.y + weight;\n    draw_list._VtxWritePtr[4].uv    = uv;\n    draw_list._VtxWritePtr[4].col   = col;\n\n    draw_list._VtxWritePtr[5].pos.x = Pmin.x + weight;\n    draw_list._VtxWritePtr[5].pos.y = Pmax.y - weight;\n    draw_list._VtxWritePtr[5].uv    = uv;\n    draw_list._VtxWritePtr[5].col   = col;\n\n    draw_list._VtxWritePtr[6].pos.x = Pmax.x - weight;\n    draw_list._VtxWritePtr[6].pos.y = Pmax.y - weight;\n    draw_list._VtxWritePtr[6].uv    = uv;\n    draw_list._VtxWritePtr[6].col   = col;\n\n    draw_list._VtxWritePtr[7].pos.x = Pmax.x - weight;\n    draw_list._VtxWritePtr[7].pos.y = Pmin.y + weight;\n    draw_list._VtxWritePtr[7].uv    = uv;\n    draw_list._VtxWritePtr[7].col   = col;\n\n    draw_list._VtxWritePtr += 8;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 5);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 5);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 6);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 6);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 5);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 7);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 7);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 6);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3);\n    draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4);\n    draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 7);\n    draw_list._IdxWritePtr += 3;\n\n    draw_list._VtxCurrentIdx += 8;\n}\n\n\n//-----------------------------------------------------------------------------\n// [SECTION] Item Utils\n//-----------------------------------------------------------------------------\n\nImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created) {\n    ImPlotContext& gp = *GImPlot;\n    ImPlotItemGroup& Items = *gp.CurrentItems;\n    ImGuiID id = Items.GetItemID(label_id);\n    if (just_created != nullptr)\n        *just_created = Items.GetItem(id) == nullptr;\n    ImPlotItem* item = Items.GetOrAddItem(id);\n    if (item->SeenThisFrame)\n        return item;\n    item->SeenThisFrame = true;\n    int idx = Items.GetItemIndex(item);\n    item->ID = id;\n    if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, nullptr) != label_id) {\n        Items.Legend.Indices.push_back(idx);\n        item->NameOffset = Items.Legend.Labels.size();\n        Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1);\n    }\n    else {\n        item->Show = true;\n    }\n    return item;\n}\n\nImPlotItem* GetItem(const char* label_id) {\n    ImPlotContext& gp = *GImPlot;\n    return gp.CurrentItems->GetItem(label_id);\n}\n\nbool IsItemHidden(const char* label_id) {\n    ImPlotItem* item = GetItem(label_id);\n    return item != nullptr && !item->Show;\n}\n\nImPlotItem* GetCurrentItem() {\n    ImPlotContext& gp = *GImPlot;\n    return gp.CurrentItem;\n}\n\nvoid SetNextLineStyle(const ImVec4& col, float weight) {\n    ImPlotContext& gp = *GImPlot;\n    gp.NextItemData.Colors[ImPlotCol_Line] = col;\n    gp.NextItemData.LineWeight             = weight;\n}\n\nvoid SetNextFillStyle(const ImVec4& col, float alpha) {\n    ImPlotContext& gp = *GImPlot;\n    gp.NextItemData.Colors[ImPlotCol_Fill] = col;\n    gp.NextItemData.FillAlpha              = alpha;\n}\n\nvoid SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) {\n    ImPlotContext& gp = *GImPlot;\n    gp.NextItemData.Marker                          = marker;\n    gp.NextItemData.Colors[ImPlotCol_MarkerFill]    = fill;\n    gp.NextItemData.MarkerSize                      = size;\n    gp.NextItemData.Colors[ImPlotCol_MarkerOutline] = outline;\n    gp.NextItemData.MarkerWeight                    = weight;\n}\n\nvoid SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {\n    ImPlotContext& gp = *GImPlot;\n    gp.NextItemData.Colors[ImPlotCol_ErrorBar] = col;\n    gp.NextItemData.ErrorBarSize               = size;\n    gp.NextItemData.ErrorBarWeight             = weight;\n}\n\nImVec4 GetLastItemColor() {\n    ImPlotContext& gp = *GImPlot;\n    if (gp.PreviousItem)\n        return ImGui::ColorConvertU32ToFloat4(gp.PreviousItem->Color);\n    return ImVec4();\n}\n\nvoid BustItemCache() {\n    ImPlotContext& gp = *GImPlot;\n    for (int p = 0; p < gp.Plots.GetBufSize(); ++p) {\n        ImPlotPlot& plot = *gp.Plots.GetByIndex(p);\n        plot.Items.Reset();\n    }\n    for (int p = 0; p < gp.Subplots.GetBufSize(); ++p) {\n        ImPlotSubplot& subplot = *gp.Subplots.GetByIndex(p);\n        subplot.Items.Reset();\n    }\n}\n\nvoid BustColorCache(const char* plot_title_id) {\n    ImPlotContext& gp = *GImPlot;\n    if (plot_title_id == nullptr) {\n        BustItemCache();\n    }\n    else {\n        ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id);\n        ImPlotPlot* plot = gp.Plots.GetByKey(id);\n        if (plot != nullptr)\n            plot->Items.Reset();\n        else {\n            ImPlotSubplot* subplot = gp.Subplots.GetByKey(id);\n            if (subplot != nullptr)\n                subplot->Items.Reset();\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] BeginItem / EndItem\n//-----------------------------------------------------------------------------\n\nstatic const float ITEM_HIGHLIGHT_LINE_SCALE = 2.0f;\nstatic const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f;\n\n// Begins a new item. Returns false if the item should not be plotted.\nbool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) {\n    ImPlotContext& gp = *GImPlot;\n    IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, \"PlotX() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    bool just_created;\n    ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created);\n    // set current item\n    gp.CurrentItem = item;\n    ImPlotNextItemData& s = gp.NextItemData;\n    // set/override item color\n    if (recolor_from != -1) {\n        if (!IsColorAuto(s.Colors[recolor_from]))\n            item->Color = ImGui::ColorConvertFloat4ToU32(s.Colors[recolor_from]);\n        else if (!IsColorAuto(gp.Style.Colors[recolor_from]))\n            item->Color = ImGui::ColorConvertFloat4ToU32(gp.Style.Colors[recolor_from]);\n        else if (just_created)\n            item->Color = NextColormapColorU32();\n    }\n    else if (just_created) {\n        item->Color = NextColormapColorU32();\n    }\n    // hide/show item\n    if (gp.NextItemData.HasHidden) {\n        if (just_created || gp.NextItemData.HiddenCond == ImGuiCond_Always)\n            item->Show = !gp.NextItemData.Hidden;\n    }\n    if (!item->Show) {\n        // reset next item data\n        gp.NextItemData.Reset();\n        gp.PreviousItem = item;\n        gp.CurrentItem  = nullptr;\n        return false;\n    }\n    else {\n        ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color);\n        // stage next item colors\n        s.Colors[ImPlotCol_Line]           = IsColorAuto(s.Colors[ImPlotCol_Line])          ? ( IsColorAuto(ImPlotCol_Line)           ? item_color                 : gp.Style.Colors[ImPlotCol_Line]          ) : s.Colors[ImPlotCol_Line];\n        s.Colors[ImPlotCol_Fill]           = IsColorAuto(s.Colors[ImPlotCol_Fill])          ? ( IsColorAuto(ImPlotCol_Fill)           ? item_color                 : gp.Style.Colors[ImPlotCol_Fill]          ) : s.Colors[ImPlotCol_Fill];\n        s.Colors[ImPlotCol_MarkerOutline]  = IsColorAuto(s.Colors[ImPlotCol_MarkerOutline]) ? ( IsColorAuto(ImPlotCol_MarkerOutline)  ? s.Colors[ImPlotCol_Line]   : gp.Style.Colors[ImPlotCol_MarkerOutline] ) : s.Colors[ImPlotCol_MarkerOutline];\n        s.Colors[ImPlotCol_MarkerFill]     = IsColorAuto(s.Colors[ImPlotCol_MarkerFill])    ? ( IsColorAuto(ImPlotCol_MarkerFill)     ? s.Colors[ImPlotCol_Line]   : gp.Style.Colors[ImPlotCol_MarkerFill]    ) : s.Colors[ImPlotCol_MarkerFill];\n        s.Colors[ImPlotCol_ErrorBar]       = IsColorAuto(s.Colors[ImPlotCol_ErrorBar])      ? ( GetStyleColorVec4(ImPlotCol_ErrorBar)                                                                         ) : s.Colors[ImPlotCol_ErrorBar];\n        // stage next item style vars\n        s.LineWeight         = s.LineWeight       < 0 ? gp.Style.LineWeight       : s.LineWeight;\n        s.Marker             = s.Marker           < 0 ? gp.Style.Marker           : s.Marker;\n        s.MarkerSize         = s.MarkerSize       < 0 ? gp.Style.MarkerSize       : s.MarkerSize;\n        s.MarkerWeight       = s.MarkerWeight     < 0 ? gp.Style.MarkerWeight     : s.MarkerWeight;\n        s.FillAlpha          = s.FillAlpha        < 0 ? gp.Style.FillAlpha        : s.FillAlpha;\n        s.ErrorBarSize       = s.ErrorBarSize     < 0 ? gp.Style.ErrorBarSize     : s.ErrorBarSize;\n        s.ErrorBarWeight     = s.ErrorBarWeight   < 0 ? gp.Style.ErrorBarWeight   : s.ErrorBarWeight;\n        s.DigitalBitHeight   = s.DigitalBitHeight < 0 ? gp.Style.DigitalBitHeight : s.DigitalBitHeight;\n        s.DigitalBitGap      = s.DigitalBitGap    < 0 ? gp.Style.DigitalBitGap    : s.DigitalBitGap;\n        // apply alpha modifier(s)\n        s.Colors[ImPlotCol_Fill].w       *= s.FillAlpha;\n        s.Colors[ImPlotCol_MarkerFill].w *= s.FillAlpha; // TODO: this should be separate, if it at all\n        // apply highlight mods\n        if (item->LegendHovered) {\n            if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlotLegendFlags_NoHighlightItem)) {\n                s.LineWeight   *= ITEM_HIGHLIGHT_LINE_SCALE;\n                s.MarkerSize   *= ITEM_HIGHLIGHT_MARK_SCALE;\n                s.MarkerWeight *= ITEM_HIGHLIGHT_LINE_SCALE;\n                // TODO: how to highlight fills?\n            }\n            if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlotLegendFlags_NoHighlightAxis)) {\n                if (gp.CurrentPlot->EnabledAxesX() > 1)\n                    gp.CurrentPlot->Axes[gp.CurrentPlot->CurrentX].ColorHiLi = item->Color;\n                if (gp.CurrentPlot->EnabledAxesY() > 1)\n                    gp.CurrentPlot->Axes[gp.CurrentPlot->CurrentY].ColorHiLi = item->Color;\n            }\n        }\n        // set render flags\n        s.RenderLine       = s.Colors[ImPlotCol_Line].w          > 0 && s.LineWeight > 0;\n        s.RenderFill       = s.Colors[ImPlotCol_Fill].w          > 0;\n        s.RenderMarkerFill = s.Colors[ImPlotCol_MarkerFill].w    > 0;\n        s.RenderMarkerLine = s.Colors[ImPlotCol_MarkerOutline].w > 0 && s.MarkerWeight > 0;\n        // push rendering clip rect\n        PushPlotClipRect();\n        return true;\n    }\n}\n\n// Ends an item (call only if BeginItem returns true)\nvoid EndItem() {\n    ImPlotContext& gp = *GImPlot;\n    // pop rendering clip rect\n    PopPlotClipRect();\n    // reset next item data\n    gp.NextItemData.Reset();\n    // set current item\n    gp.PreviousItem = gp.CurrentItem;\n    gp.CurrentItem  = nullptr;\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Indexers\n//-----------------------------------------------------------------------------\n\ntemplate <typename T>\nIMPLOT_INLINE T IndexData(const T* data, int idx, int count, int offset, int stride) {\n    const int s = ((offset == 0) << 0) | ((stride == sizeof(T)) << 1);\n    switch (s) {\n        case 3 : return data[idx];\n        case 2 : return data[(offset + idx) % count];\n        case 1 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx) ) * stride);\n        case 0 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((offset + idx) % count) * stride);\n        default: return T(0);\n    }\n}\n\ntemplate <typename T>\nstruct IndexerIdx {\n    IndexerIdx(const T* data, int count, int offset = 0, int stride = sizeof(T)) :\n        Data(data),\n        Count(count),\n        Offset(count ? ImPosMod(offset, count) : 0),\n        Stride(stride)\n    { }\n    template <typename I> IMPLOT_INLINE double operator()(I idx) const {\n        return (double)IndexData(Data, idx, Count, Offset, Stride);\n    }\n    const T* Data;\n    int Count;\n    int Offset;\n    int Stride;\n};\n\ntemplate <typename _Indexer1, typename _Indexer2>\nstruct IndexerAdd {\n    IndexerAdd(const _Indexer1& indexer1, const _Indexer2& indexer2, double scale1 = 1, double scale2 = 1)\n        : Indexer1(indexer1),\n          Indexer2(indexer2),\n          Scale1(scale1),\n          Scale2(scale2),\n          Count(ImMin(Indexer1.Count, Indexer2.Count))\n    { }\n    template <typename I> IMPLOT_INLINE double operator()(I idx) const {\n        return Scale1 * Indexer1(idx) + Scale2 * Indexer2(idx);\n    }\n    const _Indexer1& Indexer1;\n    const _Indexer2& Indexer2;\n    double Scale1;\n    double Scale2;\n    int Count;\n};\n\nstruct IndexerLin {\n    IndexerLin(double m, double b) : M(m), B(b) { }\n    template <typename I> IMPLOT_INLINE double operator()(I idx) const {\n        return M * idx + B;\n    }\n    const double M;\n    const double B;\n};\n\nstruct IndexerConst {\n    IndexerConst(double ref) : Ref(ref) { }\n    template <typename I> IMPLOT_INLINE double operator()(I) const { return Ref; }\n    const double Ref;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Getters\n//-----------------------------------------------------------------------------\n\ntemplate <typename _IndexerX, typename _IndexerY>\nstruct GetterXY {\n    GetterXY(_IndexerX x, _IndexerY y, int count) : IndxerX(x), IndxerY(y), Count(count) { }\n    template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {\n        return ImPlotPoint(IndxerX(idx),IndxerY(idx));\n    }\n    const _IndexerX IndxerX;\n    const _IndexerY IndxerY;\n    const int Count;\n};\n\n/// Interprets a user's function pointer as ImPlotPoints\nstruct GetterFuncPtr {\n    GetterFuncPtr(ImPlotGetter getter, void* data, int count) :\n        Getter(getter),\n        Data(data),\n        Count(count)\n    { }\n    template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {\n        return Getter(idx, Data);\n    }\n    ImPlotGetter Getter;\n    void* const Data;\n    const int Count;\n};\n\ntemplate <typename _Getter>\nstruct GetterOverrideX {\n    GetterOverrideX(_Getter getter, double x) : Getter(getter), X(x), Count(getter.Count) { }\n    template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {\n        ImPlotPoint p = Getter(idx);\n        p.x = X;\n        return p;\n    }\n    const _Getter Getter;\n    const double X;\n    const int Count;\n};\n\ntemplate <typename _Getter>\nstruct GetterOverrideY {\n    GetterOverrideY(_Getter getter, double y) : Getter(getter), Y(y), Count(getter.Count) { }\n    template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {\n        ImPlotPoint p = Getter(idx);\n        p.y = Y;\n        return p;\n    }\n    const _Getter Getter;\n    const double Y;\n    const int Count;\n};\n\ntemplate <typename _Getter>\nstruct GetterLoop {\n    GetterLoop(_Getter getter) : Getter(getter), Count(getter.Count + 1) { }\n    template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {\n        idx = idx % (Count - 1);\n        return Getter(idx);\n    }\n    const _Getter Getter;\n    const int Count;\n};\n\ntemplate <typename T>\nstruct GetterError {\n    GetterError(const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) :\n        Xs(xs),\n        Ys(ys),\n        Neg(neg),\n        Pos(pos),\n        Count(count),\n        Offset(count ? ImPosMod(offset, count) : 0),\n        Stride(stride)\n    { }\n    template <typename I> IMPLOT_INLINE ImPlotPointError operator()(I idx) const {\n        return ImPlotPointError((double)IndexData(Xs,  idx, Count, Offset, Stride),\n                                (double)IndexData(Ys,  idx, Count, Offset, Stride),\n                                (double)IndexData(Neg, idx, Count, Offset, Stride),\n                                (double)IndexData(Pos, idx, Count, Offset, Stride));\n    }\n    const T* const Xs;\n    const T* const Ys;\n    const T* const Neg;\n    const T* const Pos;\n    const int Count;\n    const int Offset;\n    const int Stride;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Fitters\n//-----------------------------------------------------------------------------\n\ntemplate <typename _Getter1>\nstruct Fitter1 {\n    Fitter1(const _Getter1& getter) : Getter(getter) { }\n    void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const {\n        for (int i = 0; i < Getter.Count; ++i) {\n            ImPlotPoint p = Getter(i);\n            x_axis.ExtendFitWith(y_axis, p.x, p.y);\n            y_axis.ExtendFitWith(x_axis, p.y, p.x);\n        }\n    }\n    const _Getter1& Getter;\n};\n\ntemplate <typename _Getter1>\nstruct FitterX {\n    FitterX(const _Getter1& getter) : Getter(getter) { }\n    void Fit(ImPlotAxis& x_axis, ImPlotAxis&) const {\n        for (int i = 0; i < Getter.Count; ++i) {\n            ImPlotPoint p = Getter(i);\n            x_axis.ExtendFit(p.x);\n        }\n    }\n    const _Getter1& Getter;\n};\n\ntemplate <typename _Getter1>\nstruct FitterY {\n    FitterY(const _Getter1& getter) : Getter(getter) { }\n    void Fit(ImPlotAxis&, ImPlotAxis& y_axis) const {\n        for (int i = 0; i < Getter.Count; ++i) {\n            ImPlotPoint p = Getter(i);\n            y_axis.ExtendFit(p.y);\n        }\n    }\n    const _Getter1& Getter;\n};\n\ntemplate <typename _Getter1, typename _Getter2>\nstruct Fitter2 {\n    Fitter2(const _Getter1& getter1, const _Getter2& getter2) : Getter1(getter1), Getter2(getter2) { }\n    void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const {\n        for (int i = 0; i < Getter1.Count; ++i) {\n            ImPlotPoint p = Getter1(i);\n            x_axis.ExtendFitWith(y_axis, p.x, p.y);\n            y_axis.ExtendFitWith(x_axis, p.y, p.x);\n        }\n        for (int i = 0; i < Getter2.Count; ++i) {\n            ImPlotPoint p = Getter2(i);\n            x_axis.ExtendFitWith(y_axis, p.x, p.y);\n            y_axis.ExtendFitWith(x_axis, p.y, p.x);\n        }\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n};\n\ntemplate <typename _Getter1, typename _Getter2>\nstruct FitterBarV {\n    FitterBarV(const _Getter1& getter1, const _Getter2& getter2, double width) :\n        Getter1(getter1),\n        Getter2(getter2),\n        HalfWidth(width*0.5)\n    { }\n    void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const {\n        int count = ImMin(Getter1.Count, Getter2.Count);\n        for (int i = 0; i < count; ++i) {\n            ImPlotPoint p1 = Getter1(i); p1.x -= HalfWidth;\n            ImPlotPoint p2 = Getter2(i); p2.x += HalfWidth;\n            x_axis.ExtendFitWith(y_axis, p1.x, p1.y);\n            y_axis.ExtendFitWith(x_axis, p1.y, p1.x);\n            x_axis.ExtendFitWith(y_axis, p2.x, p2.y);\n            y_axis.ExtendFitWith(x_axis, p2.y, p2.x);\n        }\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const double    HalfWidth;\n};\n\ntemplate <typename _Getter1, typename _Getter2>\nstruct FitterBarH {\n    FitterBarH(const _Getter1& getter1, const _Getter2& getter2, double height) :\n        Getter1(getter1),\n        Getter2(getter2),\n        HalfHeight(height*0.5)\n    { }\n    void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const {\n        int count = ImMin(Getter1.Count, Getter2.Count);\n        for (int i = 0; i < count; ++i) {\n            ImPlotPoint p1 = Getter1(i); p1.y -= HalfHeight;\n            ImPlotPoint p2 = Getter2(i); p2.y += HalfHeight;\n            x_axis.ExtendFitWith(y_axis, p1.x, p1.y);\n            y_axis.ExtendFitWith(x_axis, p1.y, p1.x);\n            x_axis.ExtendFitWith(y_axis, p2.x, p2.y);\n            y_axis.ExtendFitWith(x_axis, p2.y, p2.x);\n        }\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const double    HalfHeight;\n};\n\nstruct FitterRect {\n    FitterRect(const ImPlotPoint& pmin, const ImPlotPoint& pmax) :\n        Pmin(pmin),\n        Pmax(pmax)\n    { }\n    FitterRect(const ImPlotRect& rect) :\n        FitterRect(rect.Min(), rect.Max())\n    { }\n    void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const {\n        x_axis.ExtendFitWith(y_axis, Pmin.x, Pmin.y);\n        y_axis.ExtendFitWith(x_axis, Pmin.y, Pmin.x);\n        x_axis.ExtendFitWith(y_axis, Pmax.x, Pmax.y);\n        y_axis.ExtendFitWith(x_axis, Pmax.y, Pmax.x);\n    }\n    const ImPlotPoint Pmin;\n    const ImPlotPoint Pmax;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Transformers\n//-----------------------------------------------------------------------------\n\nstruct Transformer1 {\n    Transformer1(double pixMin, double pltMin, double pltMax, double m, double scaMin, double scaMax, ImPlotTransform fwd, void* data) :\n        ScaMin(scaMin),\n        ScaMax(scaMax),\n        PltMin(pltMin),\n        PltMax(pltMax),\n        PixMin(pixMin),\n        M(m),\n        TransformFwd(fwd),\n        TransformData(data)\n    { }\n\n    template <typename T> IMPLOT_INLINE float operator()(T p) const {\n        if (TransformFwd != nullptr) {\n            double s = TransformFwd(p, TransformData);\n            double t = (s - ScaMin) / (ScaMax - ScaMin);\n            p = PltMin + (PltMax - PltMin) * t;\n        }\n        return (float)(PixMin + M * (p - PltMin));\n    }\n\n    double ScaMin, ScaMax, PltMin, PltMax, PixMin, M;\n    ImPlotTransform TransformFwd;\n    void*           TransformData;\n};\n\nstruct Transformer2 {\n    Transformer2(const ImPlotAxis& x_axis, const ImPlotAxis& y_axis) :\n        Tx(x_axis.PixelMin,\n           x_axis.Range.Min,\n           x_axis.Range.Max,\n           x_axis.ScaleToPixel,\n           x_axis.ScaleMin,\n           x_axis.ScaleMax,\n           x_axis.TransformForward,\n           x_axis.TransformData),\n        Ty(y_axis.PixelMin,\n           y_axis.Range.Min,\n           y_axis.Range.Max,\n           y_axis.ScaleToPixel,\n           y_axis.ScaleMin,\n           y_axis.ScaleMax,\n           y_axis.TransformForward,\n           y_axis.TransformData)\n    { }\n\n    Transformer2(const ImPlotPlot& plot) :\n        Transformer2(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY])\n    { }\n\n    Transformer2() :\n        Transformer2(*GImPlot->CurrentPlot)\n    { }\n\n    template <typename P> IMPLOT_INLINE ImVec2 operator()(const P& plt) const {\n        ImVec2 out;\n        out.x = Tx(plt.x);\n        out.y = Ty(plt.y);\n        return out;\n    }\n\n    template <typename T> IMPLOT_INLINE ImVec2 operator()(T x, T y) const {\n        ImVec2 out;\n        out.x = Tx(x);\n        out.y = Ty(y);\n        return out;\n    }\n\n    Transformer1 Tx;\n    Transformer1 Ty;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] Renderers\n//-----------------------------------------------------------------------------\n\nstruct RendererBase {\n    RendererBase(int prims, int idx_consumed, int vtx_consumed) :\n        Prims(prims),\n        IdxConsumed(idx_consumed),\n        VtxConsumed(vtx_consumed)\n    { }\n    const int Prims;\n    Transformer2 Transformer;\n    const int IdxConsumed;\n    const int VtxConsumed;\n};\n\ntemplate <class _Getter>\nstruct RendererLineStrip : RendererBase {\n    RendererLineStrip(const _Getter& getter, ImU32 col, float weight) :\n        RendererBase(getter.Count - 1, 6, 4),\n        Getter(getter),\n        Col(col),\n        HalfWeight(ImMax(1.0f,weight)*0.5f)\n    {\n        P1 = this->Transformer(Getter(0));\n    }\n    void Init(ImDrawList& draw_list) const {\n        GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P2 = this->Transformer(Getter(prim + 1));\n        if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {\n            P1 = P2;\n            return false;\n        }\n        PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1);\n        P1 = P2;\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    mutable float HalfWeight;\n    mutable ImVec2 P1;\n    mutable ImVec2 UV0;\n    mutable ImVec2 UV1;\n};\n\ntemplate <class _Getter>\nstruct RendererLineStripSkip : RendererBase {\n    RendererLineStripSkip(const _Getter& getter, ImU32 col, float weight) :\n        RendererBase(getter.Count - 1, 6, 4),\n        Getter(getter),\n        Col(col),\n        HalfWeight(ImMax(1.0f,weight)*0.5f)\n    {\n        P1 = this->Transformer(Getter(0));\n    }\n    void Init(ImDrawList& draw_list) const {\n        GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P2 = this->Transformer(Getter(prim + 1));\n        if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {\n            if (!ImNan(P2.x) && !ImNan(P2.y))\n                P1 = P2;\n            return false;\n        }\n        PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1);\n        if (!ImNan(P2.x) && !ImNan(P2.y))\n            P1 = P2;\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    mutable float HalfWeight;\n    mutable ImVec2 P1;\n    mutable ImVec2 UV0;\n    mutable ImVec2 UV1;\n};\n\ntemplate <class _Getter>\nstruct RendererLineSegments1 : RendererBase {\n    RendererLineSegments1(const _Getter& getter, ImU32 col, float weight) :\n        RendererBase(getter.Count / 2, 6, 4),\n        Getter(getter),\n        Col(col),\n        HalfWeight(ImMax(1.0f,weight)*0.5f)\n    { }\n    void Init(ImDrawList& draw_list) const {\n        GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P1 = this->Transformer(Getter(prim*2+0));\n        ImVec2 P2 = this->Transformer(Getter(prim*2+1));\n        if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))\n            return false;\n        PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1);\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    mutable float HalfWeight;\n    mutable ImVec2 UV0;\n    mutable ImVec2 UV1;\n};\n\ntemplate <class _Getter1, class _Getter2>\nstruct RendererLineSegments2 : RendererBase {\n    RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, float weight) :\n        RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4),\n        Getter1(getter1),\n        Getter2(getter2),\n        Col(col),\n        HalfWeight(ImMax(1.0f,weight)*0.5f)\n    {}\n    void Init(ImDrawList& draw_list) const {\n        GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P1 = this->Transformer(Getter1(prim));\n        ImVec2 P2 = this->Transformer(Getter2(prim));\n        if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))\n            return false;\n        PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1);\n        return true;\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const ImU32 Col;\n    mutable float HalfWeight;\n    mutable ImVec2 UV0;\n    mutable ImVec2 UV1;\n};\n\ntemplate <class _Getter1, class _Getter2>\nstruct RendererBarsFillV : RendererBase {\n    RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width) :\n        RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4),\n        Getter1(getter1),\n        Getter2(getter2),\n        Col(col),\n        HalfWidth(width/2)\n    {}\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImPlotPoint p1 = Getter1(prim);\n        ImPlotPoint p2 = Getter2(prim);\n        p1.x += HalfWidth;\n        p2.x -= HalfWidth;\n        ImVec2 P1 = this->Transformer(p1);\n        ImVec2 P2 = this->Transformer(p2);\n        float width_px = ImAbs(P1.x-P2.x);\n        if (width_px < 1.0f) {\n            P1.x += P1.x > P2.x ? (1-width_px) / 2 : (width_px-1) / 2;\n            P2.x += P2.x > P1.x ? (1-width_px) / 2 : (width_px-1) / 2;\n        }\n        ImVec2 PMin = ImMin(P1, P2);\n        ImVec2 PMax = ImMax(P1, P2);\n        if (!cull_rect.Overlaps(ImRect(PMin, PMax)))\n            return false;\n        PrimRectFill(draw_list,PMin,PMax,Col,UV);\n        return true;\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const ImU32 Col;\n    const double HalfWidth;\n    mutable ImVec2 UV;\n};\n\ntemplate <class _Getter1, class _Getter2>\nstruct RendererBarsFillH : RendererBase {\n    RendererBarsFillH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height) :\n        RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4),\n        Getter1(getter1),\n        Getter2(getter2),\n        Col(col),\n        HalfHeight(height/2)\n    {}\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImPlotPoint p1 = Getter1(prim);\n        ImPlotPoint p2 = Getter2(prim);\n        p1.y += HalfHeight;\n        p2.y -= HalfHeight;\n        ImVec2 P1 = this->Transformer(p1);\n        ImVec2 P2 = this->Transformer(p2);\n        float height_px = ImAbs(P1.y-P2.y);\n        if (height_px < 1.0f) {\n            P1.y += P1.y > P2.y ? (1-height_px) / 2 : (height_px-1) / 2;\n            P2.y += P2.y > P1.y ? (1-height_px) / 2 : (height_px-1) / 2;\n        }\n        ImVec2 PMin = ImMin(P1, P2);\n        ImVec2 PMax = ImMax(P1, P2);\n        if (!cull_rect.Overlaps(ImRect(PMin, PMax)))\n            return false;\n        PrimRectFill(draw_list,PMin,PMax,Col,UV);\n        return true;\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const ImU32 Col;\n    const double HalfHeight;\n    mutable ImVec2 UV;\n};\n\ntemplate <class _Getter1, class _Getter2>\nstruct RendererBarsLineV : RendererBase {\n    RendererBarsLineV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width, float weight) :\n        RendererBase(ImMin(getter1.Count, getter1.Count), 24, 8),\n        Getter1(getter1),\n        Getter2(getter2),\n        Col(col),\n        HalfWidth(width/2),\n        Weight(weight)\n    {}\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImPlotPoint p1 = Getter1(prim);\n        ImPlotPoint p2 = Getter2(prim);\n        p1.x += HalfWidth;\n        p2.x -= HalfWidth;\n        ImVec2 P1 = this->Transformer(p1);\n        ImVec2 P2 = this->Transformer(p2);\n        float width_px = ImAbs(P1.x-P2.x);\n        if (width_px < 1.0f) {\n            P1.x += P1.x > P2.x ? (1-width_px) / 2 : (width_px-1) / 2;\n            P2.x += P2.x > P1.x ? (1-width_px) / 2 : (width_px-1) / 2;\n        }\n        ImVec2 PMin = ImMin(P1, P2);\n        ImVec2 PMax = ImMax(P1, P2);\n        if (!cull_rect.Overlaps(ImRect(PMin, PMax)))\n            return false;\n        PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV);\n        return true;\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const ImU32 Col;\n    const double HalfWidth;\n    const float Weight;\n    mutable ImVec2 UV;\n};\n\ntemplate <class _Getter1, class _Getter2>\nstruct RendererBarsLineH : RendererBase {\n    RendererBarsLineH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height, float weight) :\n        RendererBase(ImMin(getter1.Count, getter1.Count), 24, 8),\n        Getter1(getter1),\n        Getter2(getter2),\n        Col(col),\n        HalfHeight(height/2),\n        Weight(weight)\n    {}\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImPlotPoint p1 = Getter1(prim);\n        ImPlotPoint p2 = Getter2(prim);\n        p1.y += HalfHeight;\n        p2.y -= HalfHeight;\n        ImVec2 P1 = this->Transformer(p1);\n        ImVec2 P2 = this->Transformer(p2);\n        float height_px = ImAbs(P1.y-P2.y);\n        if (height_px < 1.0f) {\n            P1.y += P1.y > P2.y ? (1-height_px) / 2 : (height_px-1) / 2;\n            P2.y += P2.y > P1.y ? (1-height_px) / 2 : (height_px-1) / 2;\n        }\n        ImVec2 PMin = ImMin(P1, P2);\n        ImVec2 PMax = ImMax(P1, P2);\n        if (!cull_rect.Overlaps(ImRect(PMin, PMax)))\n            return false;\n        PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV);\n        return true;\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const ImU32 Col;\n    const double HalfHeight;\n    const float Weight;\n    mutable ImVec2 UV;\n};\n\n\ntemplate <class _Getter>\nstruct RendererStairsPre : RendererBase {\n    RendererStairsPre(const _Getter& getter, ImU32 col, float weight) :\n        RendererBase(getter.Count - 1, 12, 8),\n        Getter(getter),\n        Col(col),\n        HalfWeight(ImMax(1.0f,weight)*0.5f)\n    {\n        P1 = this->Transformer(Getter(0));\n    }\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P2 = this->Transformer(Getter(prim + 1));\n        if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {\n            P1 = P2;\n            return false;\n        }\n        PrimRectFill(draw_list, ImVec2(P1.x - HalfWeight, P1.y), ImVec2(P1.x + HalfWeight, P2.y), Col, UV);\n        PrimRectFill(draw_list, ImVec2(P1.x, P2.y + HalfWeight), ImVec2(P2.x, P2.y - HalfWeight), Col, UV);\n        P1 = P2;\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    mutable float HalfWeight;\n    mutable ImVec2 P1;\n    mutable ImVec2 UV;\n};\n\ntemplate <class _Getter>\nstruct RendererStairsPost : RendererBase {\n    RendererStairsPost(const _Getter& getter, ImU32 col, float weight) :\n        RendererBase(getter.Count - 1, 12, 8),\n        Getter(getter),\n        Col(col),\n        HalfWeight(ImMax(1.0f,weight) * 0.5f)\n    {\n        P1 = this->Transformer(Getter(0));\n    }\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P2 = this->Transformer(Getter(prim + 1));\n        if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {\n            P1 = P2;\n            return false;\n        }\n        PrimRectFill(draw_list, ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, UV);\n        PrimRectFill(draw_list, ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, UV);\n        P1 = P2;\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    mutable float HalfWeight;\n    mutable ImVec2 P1;\n    mutable ImVec2 UV;\n};\n\ntemplate <class _Getter>\nstruct RendererStairsPreShaded : RendererBase {\n    RendererStairsPreShaded(const _Getter& getter, ImU32 col) :\n        RendererBase(getter.Count - 1, 6, 4),\n        Getter(getter),\n        Col(col)\n    {\n        P1 = this->Transformer(Getter(0));\n        Y0 = this->Transformer(ImPlotPoint(0,0)).y;\n    }\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P2 = this->Transformer(Getter(prim + 1));\n        ImVec2 PMin(ImMin(P1.x, P2.x), ImMin(Y0, P2.y));\n        ImVec2 PMax(ImMax(P1.x, P2.x), ImMax(Y0, P2.y));\n        if (!cull_rect.Overlaps(ImRect(PMin, PMax))) {\n            P1 = P2;\n            return false;\n        }\n        PrimRectFill(draw_list, PMin, PMax, Col, UV);\n        P1 = P2;\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    float Y0;\n    mutable ImVec2 P1;\n    mutable ImVec2 UV;\n};\n\ntemplate <class _Getter>\nstruct RendererStairsPostShaded : RendererBase {\n    RendererStairsPostShaded(const _Getter& getter, ImU32 col) :\n        RendererBase(getter.Count - 1, 6, 4),\n        Getter(getter),\n        Col(col)\n    {\n        P1 = this->Transformer(Getter(0));\n        Y0 = this->Transformer(ImPlotPoint(0,0)).y;\n    }\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P2 = this->Transformer(Getter(prim + 1));\n        ImVec2 PMin(ImMin(P1.x, P2.x), ImMin(P1.y, Y0));\n        ImVec2 PMax(ImMax(P1.x, P2.x), ImMax(P1.y, Y0));\n        if (!cull_rect.Overlaps(ImRect(PMin, PMax))) {\n            P1 = P2;\n            return false;\n        }\n        PrimRectFill(draw_list, PMin, PMax, Col, UV);\n        P1 = P2;\n        return true;\n    }\n    const _Getter& Getter;\n    const ImU32 Col;\n    float Y0;\n    mutable ImVec2 P1;\n    mutable ImVec2 UV;\n};\n\n\n\ntemplate <class _Getter1, class _Getter2>\nstruct RendererShaded : RendererBase {\n    RendererShaded(const _Getter1& getter1, const _Getter2& getter2, ImU32 col) :\n        RendererBase(ImMin(getter1.Count, getter2.Count) - 1, 6, 5),\n        Getter1(getter1),\n        Getter2(getter2),\n        Col(col)\n    {\n        P11 = this->Transformer(Getter1(0));\n        P12 = this->Transformer(Getter2(0));\n    }\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 P21 = this->Transformer(Getter1(prim+1));\n        ImVec2 P22 = this->Transformer(Getter2(prim+1));\n        ImRect rect(ImMin(ImMin(ImMin(P11,P12),P21),P22), ImMax(ImMax(ImMax(P11,P12),P21),P22));\n        if (!cull_rect.Overlaps(rect)) {\n            P11 = P21;\n            P12 = P22;\n            return false;\n        }\n        const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y);\n        ImVec2 intersection = Intersection(P11,P21,P12,P22);\n        draw_list._VtxWritePtr[0].pos = P11;\n        draw_list._VtxWritePtr[0].uv  = UV;\n        draw_list._VtxWritePtr[0].col = Col;\n        draw_list._VtxWritePtr[1].pos = P21;\n        draw_list._VtxWritePtr[1].uv  = UV;\n        draw_list._VtxWritePtr[1].col = Col;\n        draw_list._VtxWritePtr[2].pos = intersection;\n        draw_list._VtxWritePtr[2].uv  = UV;\n        draw_list._VtxWritePtr[2].col = Col;\n        draw_list._VtxWritePtr[3].pos = P12;\n        draw_list._VtxWritePtr[3].uv  = UV;\n        draw_list._VtxWritePtr[3].col = Col;\n        draw_list._VtxWritePtr[4].pos = P22;\n        draw_list._VtxWritePtr[4].uv  = UV;\n        draw_list._VtxWritePtr[4].col = Col;\n        draw_list._VtxWritePtr += 5;\n        draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx);\n        draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + intersect);\n        draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3);\n        draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);\n        draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4);\n        draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3 - intersect);\n        draw_list._IdxWritePtr += 6;\n        draw_list._VtxCurrentIdx += 5;\n        P11 = P21;\n        P12 = P22;\n        return true;\n    }\n    const _Getter1& Getter1;\n    const _Getter2& Getter2;\n    const ImU32 Col;\n    mutable ImVec2 P11;\n    mutable ImVec2 P12;\n    mutable ImVec2 UV;\n};\n\nstruct RectC {\n    ImPlotPoint Pos;\n    ImPlotPoint HalfSize;\n    ImU32 Color;\n};\n\ntemplate <typename _Getter>\nstruct RendererRectC : RendererBase {\n    RendererRectC(const _Getter& getter) :\n        RendererBase(getter.Count, 6, 4),\n        Getter(getter)\n    {}\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        RectC rect = Getter(prim);\n        ImVec2 P1 = this->Transformer(rect.Pos.x - rect.HalfSize.x , rect.Pos.y - rect.HalfSize.y);\n        ImVec2 P2 = this->Transformer(rect.Pos.x + rect.HalfSize.x , rect.Pos.y + rect.HalfSize.y);\n        if ((rect.Color & IM_COL32_A_MASK) == 0 || !cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))\n            return false;\n        PrimRectFill(draw_list,P1,P2,rect.Color,UV);\n        return true;\n    }\n    const _Getter& Getter;\n    mutable ImVec2 UV;\n};\n\n//-----------------------------------------------------------------------------\n// [SECTION] RenderPrimitives\n//-----------------------------------------------------------------------------\n\n/// Renders primitive shapes in bulk as efficiently as possible.\ntemplate <class _Renderer>\nvoid RenderPrimitivesEx(const _Renderer& renderer, ImDrawList& draw_list, const ImRect& cull_rect) {\n    unsigned int prims        = renderer.Prims;\n    unsigned int prims_culled = 0;\n    unsigned int idx          = 0;\n    renderer.Init(draw_list);\n    while (prims) {\n        // find how many can be reserved up to end of current draw command's limit\n        unsigned int cnt = ImMin(prims, (MaxIdx<ImDrawIdx>::Value - draw_list._VtxCurrentIdx) / renderer.VtxConsumed);\n        // make sure at least this many elements can be rendered to avoid situations where at the end of buffer this slow path is not taken all the time\n        if (cnt >= ImMin(64u, prims)) {\n            if (prims_culled >= cnt)\n                prims_culled -= cnt; // reuse previous reservation\n            else {\n                // add more elements to previous reservation\n                draw_list.PrimReserve((cnt - prims_culled) * renderer.IdxConsumed, (cnt - prims_culled) * renderer.VtxConsumed);\n                prims_culled = 0;\n            }\n        }\n        else\n        {\n            if (prims_culled > 0) {\n                draw_list.PrimUnreserve(prims_culled * renderer.IdxConsumed, prims_culled * renderer.VtxConsumed);\n                prims_culled = 0;\n            }\n            cnt = ImMin(prims, (MaxIdx<ImDrawIdx>::Value - 0/*draw_list._VtxCurrentIdx*/) / renderer.VtxConsumed);\n            // reserve new draw command\n            draw_list.PrimReserve(cnt * renderer.IdxConsumed, cnt * renderer.VtxConsumed);\n        }\n        prims -= cnt;\n        for (unsigned int ie = idx + cnt; idx != ie; ++idx) {\n            if (!renderer.Render(draw_list, cull_rect, idx))\n                prims_culled++;\n        }\n    }\n    if (prims_culled > 0)\n        draw_list.PrimUnreserve(prims_culled * renderer.IdxConsumed, prims_culled * renderer.VtxConsumed);\n}\n\ntemplate <template <class> class _Renderer, class _Getter, typename ...Args>\nvoid RenderPrimitives1(const _Getter& getter, Args... args) {\n    ImDrawList& draw_list = *GetPlotDrawList();\n    const ImRect& cull_rect = GetCurrentPlot()->PlotRect;\n    RenderPrimitivesEx(_Renderer<_Getter>(getter,args...), draw_list, cull_rect);\n}\n\ntemplate <template <class,class> class _Renderer, class _Getter1, class _Getter2, typename ...Args>\nvoid RenderPrimitives2(const _Getter1& getter1, const _Getter2& getter2, Args... args) {\n    ImDrawList& draw_list = *GetPlotDrawList();\n    const ImRect& cull_rect = GetCurrentPlot()->PlotRect;\n    RenderPrimitivesEx(_Renderer<_Getter1,_Getter2>(getter1,getter2,args...), draw_list, cull_rect);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] Markers\n//-----------------------------------------------------------------------------\n\ntemplate <class _Getter>\nstruct RendererMarkersFill : RendererBase {\n    RendererMarkersFill(const _Getter& getter, const ImVec2* marker, int count, float size, ImU32 col) :\n        RendererBase(getter.Count, (count-2)*3, count),\n        Getter(getter),\n        Marker(marker),\n        Count(count),\n        Size(size),\n        Col(col)\n    { }\n    void Init(ImDrawList& draw_list) const {\n        UV = draw_list._Data->TexUvWhitePixel;\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 p = this->Transformer(Getter(prim));\n        if (p.x >= cull_rect.Min.x && p.y >= cull_rect.Min.y && p.x <= cull_rect.Max.x && p.y <= cull_rect.Max.y) {\n            for (int i = 0; i < Count; i++) {\n                draw_list._VtxWritePtr[0].pos.x = p.x + Marker[i].x * Size;\n                draw_list._VtxWritePtr[0].pos.y = p.y + Marker[i].y * Size;\n                draw_list._VtxWritePtr[0].uv = UV;\n                draw_list._VtxWritePtr[0].col = Col;\n                draw_list._VtxWritePtr++;\n            }\n            for (int i = 2; i < Count; i++) {\n                draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx);\n                draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + i - 1);\n                draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + i);\n                draw_list._IdxWritePtr += 3;\n            }\n            draw_list._VtxCurrentIdx += (ImDrawIdx)Count;\n            return true;\n        }\n        return false;\n    }\n    const _Getter& Getter;\n    const ImVec2* Marker;\n    const int Count;\n    const float Size;\n    const ImU32 Col;\n    mutable ImVec2 UV;\n};\n\n\ntemplate <class _Getter>\nstruct RendererMarkersLine : RendererBase {\n    RendererMarkersLine(const _Getter& getter, const ImVec2* marker, int count, float size, float weight, ImU32 col) :\n        RendererBase(getter.Count, count/2*6, count/2*4),\n        Getter(getter),\n        Marker(marker),\n        Count(count),\n        HalfWeight(ImMax(1.0f,weight)*0.5f),\n        Size(size),\n        Col(col)\n    { }\n    void Init(ImDrawList& draw_list) const {\n        GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);\n    }\n    IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {\n        ImVec2 p = this->Transformer(Getter(prim));\n        if (p.x >= cull_rect.Min.x && p.y >= cull_rect.Min.y && p.x <= cull_rect.Max.x && p.y <= cull_rect.Max.y) {\n            for (int i = 0; i < Count; i = i + 2) {\n                ImVec2 p1(p.x + Marker[i].x * Size, p.y + Marker[i].y * Size);\n                ImVec2 p2(p.x + Marker[i+1].x * Size, p.y + Marker[i+1].y * Size);\n                PrimLine(draw_list, p1, p2, HalfWeight, Col, UV0, UV1);\n            }\n            return true;\n        }\n        return false;\n    }\n    const _Getter& Getter;\n    const ImVec2* Marker;\n    const int Count;\n    mutable float HalfWeight;\n    const float Size;\n    const ImU32 Col;\n    mutable ImVec2 UV0;\n    mutable ImVec2 UV1;\n};\n\nstatic const ImVec2 MARKER_FILL_CIRCLE[10]  = {ImVec2(1.0f, 0.0f), ImVec2(0.809017f, 0.58778524f),ImVec2(0.30901697f, 0.95105654f),ImVec2(-0.30901703f, 0.9510565f),ImVec2(-0.80901706f, 0.5877852f),ImVec2(-1.0f, 0.0f),ImVec2(-0.80901694f, -0.58778536f),ImVec2(-0.3090171f, -0.9510565f),ImVec2(0.30901712f, -0.9510565f),ImVec2(0.80901694f, -0.5877853f)};\nstatic const ImVec2 MARKER_FILL_SQUARE[4]   = {ImVec2(SQRT_1_2,SQRT_1_2), ImVec2(SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,SQRT_1_2)};\nstatic const ImVec2 MARKER_FILL_DIAMOND[4]  = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};\nstatic const ImVec2 MARKER_FILL_UP[3]       = {ImVec2(SQRT_3_2,0.5f),ImVec2(0,-1),ImVec2(-SQRT_3_2,0.5f)};\nstatic const ImVec2 MARKER_FILL_DOWN[3]     = {ImVec2(SQRT_3_2,-0.5f),ImVec2(0,1),ImVec2(-SQRT_3_2,-0.5f)};\nstatic const ImVec2 MARKER_FILL_LEFT[3]     = {ImVec2(-1,0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2)};\nstatic const ImVec2 MARKER_FILL_RIGHT[3]    = {ImVec2(1,0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2)};\n\nstatic const ImVec2 MARKER_LINE_CIRCLE[20]  = {\n    ImVec2(1.0f, 0.0f),\n    ImVec2(0.809017f, 0.58778524f),\n    ImVec2(0.809017f, 0.58778524f),\n    ImVec2(0.30901697f, 0.95105654f),\n    ImVec2(0.30901697f, 0.95105654f),\n    ImVec2(-0.30901703f, 0.9510565f),\n    ImVec2(-0.30901703f, 0.9510565f),\n    ImVec2(-0.80901706f, 0.5877852f),\n    ImVec2(-0.80901706f, 0.5877852f),\n    ImVec2(-1.0f, 0.0f),\n    ImVec2(-1.0f, 0.0f),\n    ImVec2(-0.80901694f, -0.58778536f),\n    ImVec2(-0.80901694f, -0.58778536f),\n    ImVec2(-0.3090171f, -0.9510565f),\n    ImVec2(-0.3090171f, -0.9510565f),\n    ImVec2(0.30901712f, -0.9510565f),\n    ImVec2(0.30901712f, -0.9510565f),\n    ImVec2(0.80901694f, -0.5877853f),\n    ImVec2(0.80901694f, -0.5877853f),\n    ImVec2(1.0f, 0.0f)\n};\nstatic const ImVec2 MARKER_LINE_SQUARE[8]   = {ImVec2(SQRT_1_2,SQRT_1_2), ImVec2(SQRT_1_2,-SQRT_1_2), ImVec2(SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,SQRT_1_2), ImVec2(-SQRT_1_2,SQRT_1_2), ImVec2(SQRT_1_2,SQRT_1_2)};\nstatic const ImVec2 MARKER_LINE_DIAMOND[8]  = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(-1, 0), ImVec2(0, 1), ImVec2(0, 1), ImVec2(1, 0)};\nstatic const ImVec2 MARKER_LINE_UP[6]       = {ImVec2(SQRT_3_2,0.5f), ImVec2(0,-1),ImVec2(0,-1),ImVec2(-SQRT_3_2,0.5f),ImVec2(-SQRT_3_2,0.5f),ImVec2(SQRT_3_2,0.5f)};\nstatic const ImVec2 MARKER_LINE_DOWN[6]     = {ImVec2(SQRT_3_2,-0.5f),ImVec2(0,1),ImVec2(0,1),ImVec2(-SQRT_3_2,-0.5f), ImVec2(-SQRT_3_2,-0.5f), ImVec2(SQRT_3_2,-0.5f)};\nstatic const ImVec2 MARKER_LINE_LEFT[6]     = {ImVec2(-1,0), ImVec2(0.5, SQRT_3_2),  ImVec2(0.5, SQRT_3_2),  ImVec2(0.5, -SQRT_3_2) , ImVec2(0.5, -SQRT_3_2) , ImVec2(-1,0) };\nstatic const ImVec2 MARKER_LINE_RIGHT[6]    = {ImVec2(1,0),  ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(1,0) };\nstatic const ImVec2 MARKER_LINE_ASTERISK[6] = {ImVec2(-SQRT_3_2, -0.5f), ImVec2(SQRT_3_2, 0.5f),  ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, -0.5f), ImVec2(0, -1), ImVec2(0, 1)};\nstatic const ImVec2 MARKER_LINE_PLUS[4]     = {ImVec2(-1, 0), ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, 1)};\nstatic const ImVec2 MARKER_LINE_CROSS[4]    = {ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)};\n\ntemplate <typename _Getter>\nvoid RenderMarkers(const _Getter& getter, ImPlotMarker marker, float size, bool rend_fill, ImU32 col_fill, bool rend_line, ImU32 col_line, float weight) {\n    if (rend_fill) {\n        switch (marker) {\n            case ImPlotMarker_Circle  : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_CIRCLE,10,size,col_fill); break;\n            case ImPlotMarker_Square  : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_SQUARE, 4,size,col_fill); break;\n            case ImPlotMarker_Diamond : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_DIAMOND,4,size,col_fill); break;\n            case ImPlotMarker_Up      : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_UP,     3,size,col_fill); break;\n            case ImPlotMarker_Down    : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_DOWN,   3,size,col_fill); break;\n            case ImPlotMarker_Left    : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_LEFT,   3,size,col_fill); break;\n            case ImPlotMarker_Right   : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_RIGHT,  3,size,col_fill); break;\n        }\n    }\n    if (rend_line) {\n        switch (marker) {\n            case ImPlotMarker_Circle    : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_CIRCLE, 20,size,weight,col_line); break;\n            case ImPlotMarker_Square    : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_SQUARE,  8,size,weight,col_line); break;\n            case ImPlotMarker_Diamond   : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_DIAMOND, 8,size,weight,col_line); break;\n            case ImPlotMarker_Up        : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_UP,      6,size,weight,col_line); break;\n            case ImPlotMarker_Down      : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_DOWN,    6,size,weight,col_line); break;\n            case ImPlotMarker_Left      : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_LEFT,    6,size,weight,col_line); break;\n            case ImPlotMarker_Right     : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_RIGHT,   6,size,weight,col_line); break;\n            case ImPlotMarker_Asterisk  : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_ASTERISK,6,size,weight,col_line); break;\n            case ImPlotMarker_Plus      : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_PLUS,    4,size,weight,col_line); break;\n            case ImPlotMarker_Cross     : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_CROSS,   4,size,weight,col_line); break;\n        }\n    }\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotLine\n//-----------------------------------------------------------------------------\n\ntemplate <typename _Getter>\nvoid PlotLineEx(const char* label_id, const _Getter& getter, ImPlotLineFlags flags) {\n    if (BeginItemEx(label_id, Fitter1<_Getter>(getter), flags, ImPlotCol_Line)) {\n        const ImPlotNextItemData& s = GetItemData();\n        if (getter.Count > 1) {\n            if (ImHasFlag(flags, ImPlotLineFlags_Shaded) && s.RenderFill) {\n                const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);\n                GetterOverrideY<_Getter> getter2(getter, 0);\n                RenderPrimitives2<RendererShaded>(getter,getter2,col_fill);\n            }\n            if (s.RenderLine) {\n                const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n                if (ImHasFlag(flags,ImPlotLineFlags_Segments)) {\n                    RenderPrimitives1<RendererLineSegments1>(getter,col_line,s.LineWeight);\n                }\n                else if (ImHasFlag(flags, ImPlotLineFlags_Loop)) {\n                    if (ImHasFlag(flags, ImPlotLineFlags_SkipNaN))\n                        RenderPrimitives1<RendererLineStripSkip>(GetterLoop<_Getter>(getter),col_line,s.LineWeight);\n                    else\n                        RenderPrimitives1<RendererLineStrip>(GetterLoop<_Getter>(getter),col_line,s.LineWeight);\n                }\n                else {\n                    if (ImHasFlag(flags, ImPlotLineFlags_SkipNaN))\n                        RenderPrimitives1<RendererLineStripSkip>(getter,col_line,s.LineWeight);\n                    else\n                        RenderPrimitives1<RendererLineStrip>(getter,col_line,s.LineWeight);\n                }\n            }\n        }\n        // render markers\n        if (s.Marker != ImPlotMarker_None) {\n            if (ImHasFlag(flags, ImPlotLineFlags_NoClip)) {\n                PopPlotClipRect();\n                PushPlotClipRect(s.MarkerSize);\n            }\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);\n            const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);\n            RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotLine(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotLineFlags flags, int offset, int stride) {\n    GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count);\n    PlotLineEx(label_id, getter, flags);\n}\n\ntemplate <typename T>\nvoid PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags, int offset, int stride) {\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n    PlotLineEx(label_id, getter, flags);\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotLine<T> (const char* label_id, const T* values, int count, double xscale, double x0, ImPlotLineFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotLine<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n// custom\nvoid PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotLineFlags flags) {\n    GetterFuncPtr getter(getter_func,data, count);\n    PlotLineEx(label_id, getter, flags);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotScatter\n//-----------------------------------------------------------------------------\n\ntemplate <typename Getter>\nvoid PlotScatterEx(const char* label_id, const Getter& getter, ImPlotScatterFlags flags) {\n    if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_MarkerOutline)) {\n        const ImPlotNextItemData& s = GetItemData();\n        ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle: s.Marker;\n        if (marker != ImPlotMarker_None) {\n            if (ImHasFlag(flags,ImPlotScatterFlags_NoClip)) {\n                PopPlotClipRect();\n                PushPlotClipRect(s.MarkerSize);\n            }\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);\n            const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);\n            RenderMarkers<Getter>(getter, marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotScatter(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotScatterFlags flags, int offset, int stride) {\n    GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count);\n    PlotScatterEx(label_id, getter, flags);\n}\n\ntemplate <typename T>\nvoid PlotScatter(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags, int offset, int stride) {\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n    return PlotScatterEx(label_id, getter, flags);\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotScatter<T>(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotScatterFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotScatter<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n// custom\nvoid PlotScatterG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotScatterFlags flags) {\n    GetterFuncPtr getter(getter_func,data, count);\n    return PlotScatterEx(label_id, getter, flags);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotStairs\n//-----------------------------------------------------------------------------\n\ntemplate <typename Getter>\nvoid PlotStairsEx(const char* label_id, const Getter& getter, ImPlotStairsFlags flags) {\n    if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_Line)) {\n        const ImPlotNextItemData& s = GetItemData();\n        if (getter.Count > 1 ) {\n            if (s.RenderFill && ImHasFlag(flags,ImPlotStairsFlags_Shaded)) {\n                const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);\n                if (ImHasFlag(flags, ImPlotStairsFlags_PreStep))\n                    RenderPrimitives1<RendererStairsPreShaded>(getter,col_fill);\n                else\n                    RenderPrimitives1<RendererStairsPostShaded>(getter,col_fill);\n            }\n            if (s.RenderLine) {\n                const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n                if (ImHasFlag(flags, ImPlotStairsFlags_PreStep))\n                    RenderPrimitives1<RendererStairsPre>(getter,col_line,s.LineWeight);\n                else\n                    RenderPrimitives1<RendererStairsPost>(getter,col_line,s.LineWeight);\n            }\n        }\n        // render markers\n        if (s.Marker != ImPlotMarker_None) {\n            PopPlotClipRect();\n            PushPlotClipRect(s.MarkerSize);\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);\n            const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);\n            RenderMarkers<Getter>(getter, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotStairs(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotStairsFlags flags, int offset, int stride) {\n    GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count);\n    PlotStairsEx(label_id, getter, flags);\n}\n\ntemplate <typename T>\nvoid PlotStairs(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags, int offset, int stride) {\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n    return PlotStairsEx(label_id, getter, flags);\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotStairs<T> (const char* label_id, const T* values, int count, double xscale, double x0, ImPlotStairsFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotStairs<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n// custom\nvoid PlotStairsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotStairsFlags flags) {\n    GetterFuncPtr getter(getter_func,data, count);\n    return PlotStairsEx(label_id, getter, flags);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotShaded\n//-----------------------------------------------------------------------------\n\ntemplate <typename Getter1, typename Getter2>\nvoid PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) {\n    if (BeginItemEx(label_id, Fitter2<Getter1,Getter2>(getter1,getter2), flags, ImPlotCol_Fill)) {\n        const ImPlotNextItemData& s = GetItemData();\n        if (s.RenderFill) {\n            const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);\n            RenderPrimitives2<RendererShaded>(getter1,getter2,col);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotShaded(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride) {\n    if (!(y_ref > -DBL_MAX))\n        y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min;\n    if (!(y_ref < DBL_MAX))\n        y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max;\n    GetterXY<IndexerLin,IndexerIdx<T>> getter1(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count);\n    GetterXY<IndexerLin,IndexerConst>  getter2(IndexerLin(xscale,x0),IndexerConst(y_ref),count);\n    PlotShadedEx(label_id, getter1, getter2, flags);\n}\n\ntemplate <typename T>\nvoid PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride) {\n    if (y_ref == -HUGE_VAL)\n        y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min;\n    if (y_ref == HUGE_VAL)\n        y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max;\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n    GetterXY<IndexerIdx<T>,IndexerConst>  getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(y_ref),count);\n    PlotShadedEx(label_id, getter1, getter2, flags);\n}\n\n\ntemplate <typename T>\nvoid PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride) {\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys1,count,offset,stride),count);\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys2,count,offset,stride),count);\n    PlotShadedEx(label_id, getter1, getter2, flags);\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotShaded<T>(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotShaded<T>(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotShaded<T>(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n// custom\nvoid PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, ImPlotGetter getter_func2, void* data2, int count, ImPlotShadedFlags flags) {\n    GetterFuncPtr getter1(getter_func1, data1, count);\n    GetterFuncPtr getter2(getter_func2, data2, count);\n    PlotShadedEx(label_id, getter1, getter2, flags);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotBars\n//-----------------------------------------------------------------------------\n\ntemplate <typename Getter1, typename Getter2>\nvoid PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 getter2, double width, ImPlotBarsFlags flags) {\n    if (BeginItemEx(label_id, FitterBarV<Getter1,Getter2>(getter1,getter2,width), flags, ImPlotCol_Fill)) {\n        const ImPlotNextItemData& s = GetItemData();\n        const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);\n        const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n        bool rend_fill = s.RenderFill;\n        bool rend_line = s.RenderLine;\n        if (rend_fill) {\n            RenderPrimitives2<RendererBarsFillV>(getter1,getter2,col_fill,width);\n            if (rend_line && col_fill == col_line)\n                rend_line = false;\n        }\n        if (rend_line) {\n            RenderPrimitives2<RendererBarsLineV>(getter1,getter2,col_line,width,s.LineWeight);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename Getter1, typename Getter2>\nvoid PlotBarsHEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, double height, ImPlotBarsFlags flags) {\n    if (BeginItemEx(label_id, FitterBarH<Getter1,Getter2>(getter1,getter2,height), flags, ImPlotCol_Fill)) {\n        const ImPlotNextItemData& s = GetItemData();\n        const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);\n        const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n        bool rend_fill = s.RenderFill;\n        bool rend_line = s.RenderLine;\n        if (rend_fill) {\n            RenderPrimitives2<RendererBarsFillH>(getter1,getter2,col_fill,height);\n            if (rend_line && col_fill == col_line)\n                rend_line = false;\n        }\n        if (rend_line) {\n            RenderPrimitives2<RendererBarsLineH>(getter1,getter2,col_line,height,s.LineWeight);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotBars(const char* label_id, const T* values, int count, double bar_size, double shift, ImPlotBarsFlags flags, int offset, int stride) {\n    if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) {\n        GetterXY<IndexerIdx<T>,IndexerLin> getter1(IndexerIdx<T>(values,count,offset,stride),IndexerLin(1.0,shift),count);\n        GetterXY<IndexerConst,IndexerLin>  getter2(IndexerConst(0),IndexerLin(1.0,shift),count);\n        PlotBarsHEx(label_id, getter1, getter2, bar_size, flags);\n    }\n    else {\n        GetterXY<IndexerLin,IndexerIdx<T>> getter1(IndexerLin(1.0,shift),IndexerIdx<T>(values,count,offset,stride),count);\n        GetterXY<IndexerLin,IndexerConst>  getter2(IndexerLin(1.0,shift),IndexerConst(0),count);\n        PlotBarsVEx(label_id, getter1, getter2, bar_size, flags);\n    }\n}\n\ntemplate <typename T>\nvoid PlotBars(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags, int offset, int stride) {\n    if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) {\n        GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n        GetterXY<IndexerConst, IndexerIdx<T>> getter2(IndexerConst(0),IndexerIdx<T>(ys,count,offset,stride),count);\n        PlotBarsHEx(label_id, getter1, getter2, bar_size, flags);\n    }\n    else {\n        GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n        GetterXY<IndexerIdx<T>,IndexerConst>  getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(0),count);\n        PlotBarsVEx(label_id, getter1, getter2, bar_size, flags);\n    }\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotBars<T>(const char* label_id, const T* values, int count, double bar_size, double shift, ImPlotBarsFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotBars<T>(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\nvoid PlotBarsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, double bar_size, ImPlotBarsFlags flags) {\n    if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) {\n        GetterFuncPtr getter1(getter_func, data, count);\n        GetterOverrideX<GetterFuncPtr> getter2(getter1,0);\n        PlotBarsHEx(label_id, getter1, getter2, bar_size, flags);\n    }\n    else {\n        GetterFuncPtr getter1(getter_func, data, count);\n        GetterOverrideY<GetterFuncPtr> getter2(getter1,0);\n        PlotBarsVEx(label_id, getter1, getter2, bar_size, flags);\n    }\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotBarGroups\n//-----------------------------------------------------------------------------\n\ntemplate <typename T>\nvoid PlotBarGroups(const char* const label_ids[], const T* values, int item_count, int group_count, double group_size, double shift, ImPlotBarGroupsFlags flags) {\n    const bool horz = ImHasFlag(flags, ImPlotBarGroupsFlags_Horizontal);\n    const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked);\n    if (stack) {\n        SetupLock();\n        ImPlotContext& gp = *GImPlot;\n        gp.TempDouble1.resize(4*group_count);\n        double* temp = gp.TempDouble1.Data;\n        double* neg =      &temp[0];\n        double* pos =      &temp[group_count];\n        double* curr_min = &temp[group_count*2];\n        double* curr_max = &temp[group_count*3];\n        for (int g = 0; g < group_count*2; ++g)\n            temp[g] = 0;\n        if (horz) {\n            for (int i = 0; i < item_count; ++i) {\n                if (!IsItemHidden(label_ids[i])) {\n                    for (int g = 0; g < group_count; ++g) {\n                        double v = (double)values[i*group_count+g];\n                        if (v > 0) {\n                            curr_min[g] = pos[g];\n                            curr_max[g] = curr_min[g] + v;\n                            pos[g]      += v;\n                        }\n                        else {\n                            curr_max[g] = neg[g];\n                            curr_min[g] = curr_max[g] + v;\n                            neg[g]      += v;\n                        }\n                    }\n                }\n                GetterXY<IndexerIdx<double>,IndexerLin> getter1(IndexerIdx<double>(curr_min,group_count),IndexerLin(1.0,shift),group_count);\n                GetterXY<IndexerIdx<double>,IndexerLin> getter2(IndexerIdx<double>(curr_max,group_count),IndexerLin(1.0,shift),group_count);\n                PlotBarsHEx(label_ids[i],getter1,getter2,group_size,0);\n            }\n        }\n        else {\n            for (int i = 0; i < item_count; ++i) {\n                if (!IsItemHidden(label_ids[i])) {\n                    for (int g = 0; g < group_count; ++g) {\n                        double v = (double)values[i*group_count+g];\n                        if (v > 0) {\n                            curr_min[g] = pos[g];\n                            curr_max[g] = curr_min[g] + v;\n                            pos[g]      += v;\n                        }\n                        else {\n                            curr_max[g] = neg[g];\n                            curr_min[g] = curr_max[g] + v;\n                            neg[g]      += v;\n                        }\n                    }\n                }\n                GetterXY<IndexerLin,IndexerIdx<double>> getter1(IndexerLin(1.0,shift),IndexerIdx<double>(curr_min,group_count),group_count);\n                GetterXY<IndexerLin,IndexerIdx<double>> getter2(IndexerLin(1.0,shift),IndexerIdx<double>(curr_max,group_count),group_count);\n                PlotBarsVEx(label_ids[i],getter1,getter2,group_size,0);\n            }\n        }\n    }\n    else {\n        const double subsize = group_size / item_count;\n        if (horz) {\n            for (int i = 0; i < item_count; ++i) {\n                const double subshift = (i+0.5)*subsize - group_size/2;\n                PlotBars(label_ids[i],&values[i*group_count],group_count,subsize,subshift+shift,ImPlotBarsFlags_Horizontal);\n            }\n        }\n        else {\n            for (int i = 0; i < item_count; ++i) {\n                const double subshift = (i+0.5)*subsize - group_size/2;\n                PlotBars(label_ids[i],&values[i*group_count],group_count,subsize,subshift+shift);\n            }\n        }\n    }\n}\n\n#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotBarGroups<T>(const char* const label_ids[], const T* values, int items, int groups, double width, double shift, ImPlotBarGroupsFlags flags);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotErrorBars\n//-----------------------------------------------------------------------------\n\ntemplate <typename _GetterPos, typename _GetterNeg>\nvoid PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) {\n    if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) {\n        const ImPlotNextItemData& s = GetItemData();\n        ImDrawList& draw_list = *GetPlotDrawList();\n        const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);\n        const bool rend_whisker  = s.ErrorBarSize > 0;\n        const float half_whisker = s.ErrorBarSize * 0.5f;\n        for (int i = 0; i < getter_pos.Count; ++i) {\n            ImVec2 p1 = PlotToPixels(getter_neg(i),IMPLOT_AUTO,IMPLOT_AUTO);\n            ImVec2 p2 = PlotToPixels(getter_pos(i),IMPLOT_AUTO,IMPLOT_AUTO);\n            draw_list.AddLine(p1,p2,col, s.ErrorBarWeight);\n            if (rend_whisker) {\n                draw_list.AddLine(p1 - ImVec2(half_whisker, 0), p1 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight);\n                draw_list.AddLine(p2 - ImVec2(half_whisker, 0), p2 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight);\n            }\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename _GetterPos, typename _GetterNeg>\nvoid PlotErrorBarsHEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) {\n    if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) {\n        const ImPlotNextItemData& s = GetItemData();\n        ImDrawList& draw_list = *GetPlotDrawList();\n        const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);\n        const bool rend_whisker  = s.ErrorBarSize > 0;\n        const float half_whisker = s.ErrorBarSize * 0.5f;\n        for (int i = 0; i < getter_pos.Count; ++i) {\n            ImVec2 p1 = PlotToPixels(getter_neg(i),IMPLOT_AUTO,IMPLOT_AUTO);\n            ImVec2 p2 = PlotToPixels(getter_pos(i),IMPLOT_AUTO,IMPLOT_AUTO);\n            draw_list.AddLine(p1, p2, col, s.ErrorBarWeight);\n            if (rend_whisker) {\n                draw_list.AddLine(p1 - ImVec2(0, half_whisker), p1 + ImVec2(0, half_whisker), col, s.ErrorBarWeight);\n                draw_list.AddLine(p2 - ImVec2(0, half_whisker), p2 + ImVec2(0, half_whisker), col, s.ErrorBarWeight);\n            }\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, ImPlotErrorBarsFlags flags, int offset, int stride) {\n    PlotErrorBars(label_id, xs, ys, err, err, count, flags, offset, stride);\n}\n\ntemplate <typename T>\nvoid PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, ImPlotErrorBarsFlags flags, int offset, int stride) {\n    IndexerIdx<T> indexer_x(xs, count,offset,stride);\n    IndexerIdx<T> indexer_y(ys, count,offset,stride);\n    IndexerIdx<T> indexer_n(neg,count,offset,stride);\n    IndexerIdx<T> indexer_p(pos,count,offset,stride);\n    GetterError<T> getter(xs, ys, neg, pos, count, offset, stride);\n    if (ImHasFlag(flags, ImPlotErrorBarsFlags_Horizontal)) {\n        IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_xp(indexer_x, indexer_p, 1,  1);\n        IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_xn(indexer_x, indexer_n, 1, -1);\n        GetterXY<IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>,IndexerIdx<T>> getter_p(indexer_xp, indexer_y, count);\n        GetterXY<IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>,IndexerIdx<T>> getter_n(indexer_xn, indexer_y, count);\n        PlotErrorBarsHEx(label_id, getter_p, getter_n, flags);\n    }\n    else {\n        IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_yp(indexer_y, indexer_p, 1,  1);\n        IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_yn(indexer_y, indexer_n, 1, -1);\n        GetterXY<IndexerIdx<T>,IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>> getter_p(indexer_x, indexer_yp, count);\n        GetterXY<IndexerIdx<T>,IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>> getter_n(indexer_x, indexer_yn, count);\n        PlotErrorBarsVEx(label_id, getter_p, getter_n, flags);\n    }\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotErrorBars<T>(const char* label_id, const T* xs, const T* ys, const T* err, int count, ImPlotErrorBarsFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotErrorBars<T>(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, ImPlotErrorBarsFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotStems\n//-----------------------------------------------------------------------------\n\ntemplate <typename _GetterM, typename _GetterB>\nvoid PlotStemsEx(const char* label_id, const _GetterM& get_mark, const _GetterB& get_base, ImPlotStemsFlags flags) {\n    if (BeginItemEx(label_id, Fitter2<_GetterM,_GetterB>(get_mark,get_base), flags, ImPlotCol_Line)) {\n        const ImPlotNextItemData& s = GetItemData();\n        // render stems\n        if (s.RenderLine) {\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n            RenderPrimitives2<RendererLineSegments2>(get_mark, get_base, col_line, s.LineWeight);\n        }\n        // render markers\n        if (s.Marker != ImPlotMarker_None) {\n            PopPlotClipRect();\n            PushPlotClipRect(s.MarkerSize);\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);\n            const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);\n            RenderMarkers<_GetterM>(get_mark, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);\n        }\n        EndItem();\n    }\n}\n\ntemplate <typename T>\nvoid PlotStems(const char* label_id, const T* values, int count, double ref, double scale, double start, ImPlotStemsFlags flags, int offset, int stride) {\n    if (ImHasFlag(flags, ImPlotStemsFlags_Horizontal)) {\n        GetterXY<IndexerIdx<T>,IndexerLin> get_mark(IndexerIdx<T>(values,count,offset,stride),IndexerLin(scale,start),count);\n        GetterXY<IndexerConst,IndexerLin>  get_base(IndexerConst(ref),IndexerLin(scale,start),count);\n        PlotStemsEx(label_id, get_mark, get_base, flags);\n    }\n    else {\n        GetterXY<IndexerLin,IndexerIdx<T>> get_mark(IndexerLin(scale,start),IndexerIdx<T>(values,count,offset,stride),count);\n        GetterXY<IndexerLin,IndexerConst>  get_base(IndexerLin(scale,start),IndexerConst(ref),count);\n        PlotStemsEx(label_id, get_mark, get_base, flags);\n    }\n}\n\ntemplate <typename T>\nvoid PlotStems(const char* label_id, const T* xs, const T* ys, int count, double ref, ImPlotStemsFlags flags, int offset, int stride) {\n    if (ImHasFlag(flags, ImPlotStemsFlags_Horizontal)) {\n        GetterXY<IndexerIdx<T>,IndexerIdx<T>> get_mark(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n        GetterXY<IndexerConst,IndexerIdx<T>>  get_base(IndexerConst(ref),IndexerIdx<T>(ys,count,offset,stride),count);\n        PlotStemsEx(label_id, get_mark, get_base, flags);\n    }\n    else {\n        GetterXY<IndexerIdx<T>,IndexerIdx<T>> get_mark(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n        GetterXY<IndexerIdx<T>,IndexerConst>  get_base(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(ref),count);\n        PlotStemsEx(label_id, get_mark, get_base, flags);\n    }\n}\n\n#define INSTANTIATE_MACRO(T) \\\n    template IMPLOT_API void PlotStems<T>(const char* label_id, const T* values, int count, double ref, double scale, double start, ImPlotStemsFlags flags, int offset, int stride); \\\n    template IMPLOT_API void PlotStems<T>(const char* label_id, const T* xs, const T* ys, int count, double ref, ImPlotStemsFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotInfLines\n//-----------------------------------------------------------------------------\n\ntemplate <typename T>\nvoid PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags, int offset, int stride) {\n    const ImPlotRect lims = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO);\n    if (ImHasFlag(flags, ImPlotInfLinesFlags_Horizontal)) {\n        GetterXY<IndexerConst,IndexerIdx<T>> get_min(IndexerConst(lims.X.Min),IndexerIdx<T>(values,count,offset,stride),count);\n        GetterXY<IndexerConst,IndexerIdx<T>> get_max(IndexerConst(lims.X.Max),IndexerIdx<T>(values,count,offset,stride),count);\n        if (BeginItemEx(label_id, FitterY<GetterXY<IndexerConst,IndexerIdx<T>>>(get_min), flags, ImPlotCol_Line)) {\n            const ImPlotNextItemData& s = GetItemData();\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n            if (s.RenderLine)\n                RenderPrimitives2<RendererLineSegments2>(get_min, get_max, col_line, s.LineWeight);\n            EndItem();\n        }\n    }\n    else {\n        GetterXY<IndexerIdx<T>,IndexerConst> get_min(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Min),count);\n        GetterXY<IndexerIdx<T>,IndexerConst> get_max(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Max),count);\n        if (BeginItemEx(label_id, FitterX<GetterXY<IndexerIdx<T>,IndexerConst>>(get_min), flags, ImPlotCol_Line)) {\n            const ImPlotNextItemData& s = GetItemData();\n            const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);\n            if (s.RenderLine)\n                RenderPrimitives2<RendererLineSegments2>(get_min, get_max, col_line, s.LineWeight);\n            EndItem();\n        }\n    }\n}\n#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotInfLines<T>(const char* label_id, const T* xs, int count, ImPlotInfLinesFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotPieChart\n//-----------------------------------------------------------------------------\n\nIMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) {\n    const float resolution = 50 / (2 * IM_PI);\n    ImVec2 buffer[52];\n    buffer[0] = PlotToPixels(center,IMPLOT_AUTO,IMPLOT_AUTO);\n    int n = ImMax(3, (int)((a1 - a0) * resolution));\n    double da = (a1 - a0) / (n - 1);\n    int i = 0;\n    for (; i < n; ++i) {\n        double a = a0 + i * da;\n        buffer[i + 1] = PlotToPixels(center.x + radius * cos(a), center.y + radius * sin(a),IMPLOT_AUTO,IMPLOT_AUTO);\n    }\n    buffer[i+1] = buffer[0];\n    // fill\n    draw_list.AddConvexPolyFilled(buffer, n + 1, col);\n    // border (for AA)\n    draw_list.AddPolyline(buffer, n + 2, col, 0, 2.0f);\n}\n\ntemplate <typename T>\nvoid PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {\n    IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, \"PlotPieChart() needs to be called between BeginPlot() and EndPlot()!\");\n    ImDrawList & draw_list = *GetPlotDrawList();\n    double sum = 0;\n    for (int i = 0; i < count; ++i)\n        sum += (double)values[i];\n    const bool normalize = ImHasFlag(flags,ImPlotPieChartFlags_Normalize) || sum > 1.0;\n    ImPlotPoint center(x,y);\n    PushPlotClipRect();\n    double a0 = angle0 * 2 * IM_PI / 360.0;\n    double a1 = angle0 * 2 * IM_PI / 360.0;\n    ImPlotPoint Pmin = ImPlotPoint(x-radius,y-radius);\n    ImPlotPoint Pmax = ImPlotPoint(x+radius,y+radius);\n    for (int i = 0; i < count; ++i) {\n        double percent = normalize ? (double)values[i] / sum : (double)values[i];\n        a1 = a0 + 2 * IM_PI * percent;\n        if (BeginItemEx(label_ids[i], FitterRect(Pmin,Pmax))) {\n            ImU32 col = GetCurrentItem()->Color;\n            if (percent < 0.5) {\n                RenderPieSlice(draw_list, center, radius, a0, a1, col);\n            }\n            else  {\n                RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col);\n                RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col);\n            }\n            EndItem();\n        }\n        a0 = a1;\n    }\n    if (fmt != nullptr) {\n        a0 = angle0 * 2 * IM_PI / 360.0;\n        a1 = angle0 * 2 * IM_PI / 360.0;\n        char buffer[32];\n        for (int i = 0; i < count; ++i) {\n            ImPlotItem* item = GetItem(label_ids[i]);\n            double percent = normalize ? (double)values[i] / sum : (double)values[i];\n            a1 = a0 + 2 * IM_PI * percent;\n            if (item->Show) {\n                ImFormatString(buffer, 32, fmt, (double)values[i]);\n                ImVec2 size = ImGui::CalcTextSize(buffer);\n                double angle = a0 + (a1 - a0) * 0.5;\n                ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle),IMPLOT_AUTO,IMPLOT_AUTO);\n                ImU32 col  = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));\n                draw_list.AddText(pos - size * 0.5f, col, buffer);\n            }\n            a0 = a1;\n        }\n    }\n    PopPlotClipRect();\n}\n#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotHeatmap\n//-----------------------------------------------------------------------------\n\ntemplate <typename T>\nstruct GetterHeatmapRowMaj {\n    GetterHeatmapRowMaj(const T* values, int rows, int cols, double scale_min, double scale_max, double width, double height, double xref, double yref, double ydir) :\n        Values(values),\n        Count(rows*cols),\n        Rows(rows),\n        Cols(cols),\n        ScaleMin(scale_min),\n        ScaleMax(scale_max),\n        Width(width),\n        Height(height),\n        XRef(xref),\n        YRef(yref),\n        YDir(ydir),\n        HalfSize(Width*0.5, Height*0.5)\n    { }\n    template <typename I> IMPLOT_INLINE RectC operator()(I idx) const {\n        double val = (double)Values[idx];\n        const int r = idx / Cols;\n        const int c = idx % Cols;\n        const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));\n        RectC rect;\n        rect.Pos = p;\n        rect.HalfSize = HalfSize;\n        const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);\n        ImPlotContext& gp = *GImPlot;\n        rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);\n        return rect;\n    }\n    const T* const Values;\n    const int Count, Rows, Cols;\n    const double ScaleMin, ScaleMax, Width, Height, XRef, YRef, YDir;\n    const ImPlotPoint HalfSize;\n};\n\ntemplate <typename T>\nstruct GetterHeatmapColMaj {\n    GetterHeatmapColMaj(const T* values, int rows, int cols, double scale_min, double scale_max, double width, double height, double xref, double yref, double ydir) :\n        Values(values),\n        Count(rows*cols),\n        Rows(rows),\n        Cols(cols),\n        ScaleMin(scale_min),\n        ScaleMax(scale_max),\n        Width(width),\n        Height(height),\n        XRef(xref),\n        YRef(yref),\n        YDir(ydir),\n        HalfSize(Width*0.5, Height*0.5)\n    { }\n    template <typename I> IMPLOT_INLINE RectC operator()(I idx) const {\n        double val = (double)Values[idx];\n        const int r = idx % Cols;\n        const int c = idx / Cols;\n        const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));\n        RectC rect;\n        rect.Pos = p;\n        rect.HalfSize = HalfSize;\n        const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);\n        ImPlotContext& gp = *GImPlot;\n        rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);\n        return rect;\n    }\n    const T* const Values;\n    const int Count, Rows, Cols;\n    const double ScaleMin, ScaleMax, Width, Height, XRef, YRef, YDir;\n    const ImPlotPoint HalfSize;\n};\n\ntemplate <typename T>\nvoid RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, bool reverse_y, bool col_maj) {\n    ImPlotContext& gp = *GImPlot;\n    Transformer2 transformer;\n    if (scale_min == 0 && scale_max == 0) {\n        T temp_min, temp_max;\n        ImMinMaxArray(values,rows*cols,&temp_min,&temp_max);\n        scale_min = (double)temp_min;\n        scale_max = (double)temp_max;\n    }\n    if (scale_min == scale_max) {\n        ImVec2 a = transformer(bounds_min);\n        ImVec2 b = transformer(bounds_max);\n        ImU32  col = GetColormapColorU32(0,gp.Style.Colormap);\n        draw_list.AddRectFilled(a, b, col);\n        return;\n    }\n    const double yref = reverse_y ? bounds_max.y : bounds_min.y;\n    const double ydir = reverse_y ? -1 : 1;\n    if (col_maj) {\n        GetterHeatmapColMaj<T> getter(values, rows, cols, scale_min, scale_max, (bounds_max.x - bounds_min.x) / cols, (bounds_max.y - bounds_min.y) / rows, bounds_min.x, yref, ydir);\n        RenderPrimitives1<RendererRectC>(getter);\n    }\n    else {\n        GetterHeatmapRowMaj<T> getter(values, rows, cols, scale_min, scale_max, (bounds_max.x - bounds_min.x) / cols, (bounds_max.y - bounds_min.y) / rows, bounds_min.x, yref, ydir);\n        RenderPrimitives1<RendererRectC>(getter);\n    }\n    // labels\n    if (fmt != nullptr) {\n        const double w = (bounds_max.x - bounds_min.x) / cols;\n        const double h = (bounds_max.y - bounds_min.y) / rows;\n        const ImPlotPoint half_size(w*0.5,h*0.5);\n        int i = 0;\n        if (col_maj) {\n            for (int c = 0; c < cols; ++c) {\n                for (int r = 0; r < rows; ++r) {\n                    ImPlotPoint p;\n                    p.x = bounds_min.x + 0.5*w + c*w;\n                    p.y = yref + ydir * (0.5*h + r*h);\n                    ImVec2 px = transformer(p);\n                    char buff[32];\n                    ImFormatString(buff, 32, fmt, values[i]);\n                    ImVec2 size = ImGui::CalcTextSize(buff);\n                    double t = ImClamp(ImRemap01((double)values[i], scale_min, scale_max),0.0,1.0);\n                    ImVec4 color = SampleColormap((float)t);\n                    ImU32 col = CalcTextColor(color);\n                    draw_list.AddText(px - size * 0.5f, col, buff);\n                    i++;\n                }\n            }\n        }\n        else {\n            for (int r = 0; r < rows; ++r) {\n                for (int c = 0; c < cols; ++c) {\n                    ImPlotPoint p;\n                    p.x = bounds_min.x + 0.5*w + c*w;\n                    p.y = yref + ydir * (0.5*h + r*h);\n                    ImVec2 px = transformer(p);\n                    char buff[32];\n                    ImFormatString(buff, 32, fmt, values[i]);\n                    ImVec2 size = ImGui::CalcTextSize(buff);\n                    double t = ImClamp(ImRemap01((double)values[i], scale_min, scale_max),0.0,1.0);\n                    ImVec4 color = SampleColormap((float)t);\n                    ImU32 col = CalcTextColor(color);\n                    draw_list.AddText(px - size * 0.5f, col, buff);\n                    i++;\n                }\n            }\n        }\n    }\n}\n\ntemplate <typename T>\nvoid PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags) {\n    if (BeginItemEx(label_id, FitterRect(bounds_min, bounds_max))) {\n        ImDrawList& draw_list = *GetPlotDrawList();\n        const bool col_maj = ImHasFlag(flags, ImPlotHeatmapFlags_ColMajor);\n        RenderHeatmap(draw_list, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true, col_maj);\n        EndItem();\n    }\n}\n#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotHeatmap<T>(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotHistogram\n//-----------------------------------------------------------------------------\n\ntemplate <typename T>\ndouble PlotHistogram(const char* label_id, const T* values, int count, int bins, double bar_scale, ImPlotRange range, ImPlotHistogramFlags flags) {\n\n    const bool cumulative = ImHasFlag(flags, ImPlotHistogramFlags_Cumulative);\n    const bool density    = ImHasFlag(flags, ImPlotHistogramFlags_Density);\n    const bool outliers   = !ImHasFlag(flags, ImPlotHistogramFlags_NoOutliers);\n\n    if (count <= 0 || bins == 0)\n        return 0;\n\n    if (range.Min == 0 && range.Max == 0) {\n        T Min, Max;\n        ImMinMaxArray(values, count, &Min, &Max);\n        range.Min = (double)Min;\n        range.Max = (double)Max;\n    }\n\n    double width;\n    if (bins < 0)\n        CalculateBins(values, count, bins, range, bins, width);\n    else\n        width = range.Size() / bins;\n\n    ImPlotContext& gp = *GImPlot;\n    ImVector<double>& bin_centers = gp.TempDouble1;\n    ImVector<double>& bin_counts  = gp.TempDouble2;\n    bin_centers.resize(bins);\n    bin_counts.resize(bins);\n    int below = 0;\n\n    for (int b = 0; b < bins; ++b) {\n        bin_centers[b] = range.Min + b * width + width * 0.5;\n        bin_counts[b] = 0;\n    }\n    int counted = 0;\n    double max_count = 0;\n    for (int i = 0; i < count; ++i) {\n        double val = (double)values[i];\n        if (range.Contains(val)) {\n            const int b = ImClamp((int)((val - range.Min) / width), 0, bins - 1);\n            bin_counts[b] += 1.0;\n            if (bin_counts[b] > max_count)\n                max_count = bin_counts[b];\n            counted++;\n        }\n        else if (val < range.Min) {\n            below++;\n        }\n    }\n    if (cumulative && density) {\n        if (outliers)\n            bin_counts[0] += below;\n        for (int b = 1; b < bins; ++b)\n            bin_counts[b] += bin_counts[b-1];\n        double scale = 1.0 / (outliers ? count : counted);\n        for (int b = 0; b < bins; ++b)\n            bin_counts[b] *= scale;\n        max_count = bin_counts[bins-1];\n    }\n    else if (cumulative) {\n        if (outliers)\n            bin_counts[0] += below;\n        for (int b = 1; b < bins; ++b)\n            bin_counts[b] += bin_counts[b-1];\n        max_count = bin_counts[bins-1];\n    }\n    else if (density) {\n        double scale = 1.0 / ((outliers ? count : counted) * width);\n        for (int b = 0; b < bins; ++b)\n            bin_counts[b] *= scale;\n        max_count *= scale;\n    }\n    if (ImHasFlag(flags, ImPlotHistogramFlags_Horizontal))\n        PlotBars(label_id, &bin_counts.Data[0], &bin_centers.Data[0], bins, bar_scale*width, ImPlotBarsFlags_Horizontal);\n    else\n        PlotBars(label_id, &bin_centers.Data[0], &bin_counts.Data[0], bins, bar_scale*width);\n    return max_count;\n}\n#define INSTANTIATE_MACRO(T) template IMPLOT_API double PlotHistogram<T>(const char* label_id, const T* values, int count, int bins, double bar_scale, ImPlotRange range, ImPlotHistogramFlags flags);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotHistogram2D\n//-----------------------------------------------------------------------------\n\ntemplate <typename T>\ndouble PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins, int y_bins, ImPlotRect range, ImPlotHistogramFlags flags) {\n\n    // const bool cumulative = ImHasFlag(flags, ImPlotHistogramFlags_Cumulative); NOT SUPPORTED\n    const bool density  = ImHasFlag(flags, ImPlotHistogramFlags_Density);\n    const bool outliers = !ImHasFlag(flags, ImPlotHistogramFlags_NoOutliers);\n    const bool col_maj  = ImHasFlag(flags, ImPlotHistogramFlags_ColMajor);\n\n    if (count <= 0 || x_bins == 0 || y_bins == 0)\n        return 0;\n\n    if (range.X.Min == 0 && range.X.Max == 0) {\n        T Min, Max;\n        ImMinMaxArray(xs, count, &Min, &Max);\n        range.X.Min = (double)Min;\n        range.X.Max = (double)Max;\n    }\n    if (range.Y.Min == 0 && range.Y.Max == 0) {\n        T Min, Max;\n        ImMinMaxArray(ys, count, &Min, &Max);\n        range.Y.Min = (double)Min;\n        range.Y.Max = (double)Max;\n    }\n\n    double width, height;\n    if (x_bins < 0)\n        CalculateBins(xs, count, x_bins, range.X, x_bins, width);\n    else\n        width = range.X.Size() / x_bins;\n    if (y_bins < 0)\n        CalculateBins(ys, count, y_bins, range.Y, y_bins, height);\n    else\n        height = range.Y.Size() / y_bins;\n\n    const int bins = x_bins * y_bins;\n\n    ImPlotContext& gp = *GImPlot;\n    ImVector<double>& bin_counts = gp.TempDouble1;\n    bin_counts.resize(bins);\n\n    for (int b = 0; b < bins; ++b)\n        bin_counts[b] = 0;\n\n    int counted = 0;\n    double max_count = 0;\n    for (int i = 0; i < count; ++i) {\n        if (range.Contains((double)xs[i], (double)ys[i])) {\n            const int xb = ImClamp( (int)((double)(xs[i] - range.X.Min) / width)  , 0, x_bins - 1);\n            const int yb = ImClamp( (int)((double)(ys[i] - range.Y.Min) / height) , 0, y_bins - 1);\n            const int b  = yb * x_bins + xb;\n            bin_counts[b] += 1.0;\n            if (bin_counts[b] > max_count)\n                max_count = bin_counts[b];\n            counted++;\n        }\n    }\n    if (density) {\n        double scale = 1.0 / ((outliers ? count : counted) * width * height);\n        for (int b = 0; b < bins; ++b)\n            bin_counts[b] *= scale;\n        max_count *= scale;\n    }\n\n    if (BeginItemEx(label_id, FitterRect(range))) {\n        ImDrawList& draw_list = *GetPlotDrawList();\n        RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj);\n        EndItem();\n    }\n    return max_count;\n}\n#define INSTANTIATE_MACRO(T) template IMPLOT_API double PlotHistogram2D<T>(const char* label_id,   const T*   xs, const T*   ys, int count, int x_bins, int y_bins, ImPlotRect range, ImPlotHistogramFlags flags);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotDigital\n//-----------------------------------------------------------------------------\n\n// TODO: Make this behave like all the other plot types (.e. not fixed in y axis)\n\ntemplate <typename Getter>\nvoid PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags) {\n    if (BeginItem(label_id, flags, ImPlotCol_Fill)) {\n        ImPlotContext& gp = *GImPlot;\n        ImDrawList& draw_list = *GetPlotDrawList();\n        const ImPlotNextItemData& s = GetItemData();\n        if (getter.Count > 1 && s.RenderFill) {\n            ImPlotPlot& plot   = *gp.CurrentPlot;\n            ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];\n            ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];\n\n            int pixYMax = 0;\n            ImPlotPoint itemData1 = getter(0);\n            for (int i = 0; i < getter.Count; ++i) {\n                ImPlotPoint itemData2 = getter(i);\n                if (ImNanOrInf(itemData1.y)) {\n                    itemData1 = itemData2;\n                    continue;\n                }\n                if (ImNanOrInf(itemData2.y)) itemData2.y = ImConstrainNan(ImConstrainInf(itemData2.y));\n                int pixY_0 = (int)(s.LineWeight);\n                itemData1.y = ImMax(0.0, itemData1.y);\n                float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y;\n                int pixY_1 = (int)(pixY_1_float); //allow only positive values\n                int pixY_chPosOffset = (int)(ImMax(s.DigitalBitHeight, pixY_1_float) + s.DigitalBitGap);\n                pixYMax = ImMax(pixYMax, pixY_chPosOffset);\n                ImVec2 pMin = PlotToPixels(itemData1,IMPLOT_AUTO,IMPLOT_AUTO);\n                ImVec2 pMax = PlotToPixels(itemData2,IMPLOT_AUTO,IMPLOT_AUTO);\n                int pixY_Offset = 0; //20 pixel from bottom due to mouse cursor label\n                pMin.y = (y_axis.PixelMin) + ((-gp.DigitalPlotOffset)                   - pixY_Offset);\n                pMax.y = (y_axis.PixelMin) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset);\n                //plot only one rectangle for same digital state\n                while (((i+2) < getter.Count) && (itemData1.y == itemData2.y)) {\n                    const int in = (i + 1);\n                    itemData2 = getter(in);\n                    if (ImNanOrInf(itemData2.y)) break;\n                    pMax.x = PlotToPixels(itemData2,IMPLOT_AUTO,IMPLOT_AUTO).x;\n                    i++;\n                }\n                //do not extend plot outside plot range\n                if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin;\n                if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin;\n                if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax;\n                if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax;\n                //plot a rectangle that extends up to x2 with y1 height\n                if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) {\n                    // ImVec4 colAlpha = item->Color;\n                    // colAlpha.w = item->Highlight ? 1.0f : 0.9f;\n                    draw_list.AddRectFilled(pMin, pMax, ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]));\n                }\n                itemData1 = itemData2;\n            }\n            gp.DigitalPlotItemCnt++;\n            gp.DigitalPlotOffset += pixYMax;\n        }\n        EndItem();\n    }\n}\n\n\ntemplate <typename T>\nvoid PlotDigital(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags, int offset, int stride) {\n    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);\n    return PlotDigitalEx(label_id, getter, flags);\n}\n#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotDigital<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags, int offset, int stride);\nCALL_INSTANTIATE_FOR_NUMERIC_TYPES()\n#undef INSTANTIATE_MACRO\n\n// custom\nvoid PlotDigitalG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotDigitalFlags flags) {\n    GetterFuncPtr getter(getter_func,data,count);\n    return PlotDigitalEx(label_id, getter, flags);\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotImage\n//-----------------------------------------------------------------------------\n\nvoid PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) {\n    if (BeginItemEx(label_id, FitterRect(bmin,bmax))) {\n        ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col);\n        GetCurrentItem()->Color = tint_col32;\n        ImDrawList& draw_list = *GetPlotDrawList();\n        ImVec2 p1 = PlotToPixels(bmin.x, bmax.y,IMPLOT_AUTO,IMPLOT_AUTO);\n        ImVec2 p2 = PlotToPixels(bmax.x, bmin.y,IMPLOT_AUTO,IMPLOT_AUTO);\n        PushPlotClipRect();\n        draw_list.AddImage(user_texture_id, p1, p2, uv0, uv1, tint_col32);\n        PopPlotClipRect();\n        EndItem();\n    }\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotText\n//-----------------------------------------------------------------------------\n\nvoid PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) {\n    IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, \"PlotText() needs to be called between BeginPlot() and EndPlot()!\");\n    SetupLock();\n    ImDrawList & draw_list = *GetPlotDrawList();\n    PushPlotClipRect();\n    ImU32 colTxt = GetStyleColorU32(ImPlotCol_InlayText);\n    if (ImHasFlag(flags,ImPlotTextFlags_Vertical)) {\n        ImVec2 siz = CalcTextSizeVertical(text) * 0.5f;\n        ImVec2 ctr = siz * 0.5f;\n        ImVec2 pos = PlotToPixels(ImPlotPoint(x,y),IMPLOT_AUTO,IMPLOT_AUTO) + ImVec2(-ctr.x, ctr.y) + pixel_offset;\n        if (FitThisFrame() && !ImHasFlag(flags, ImPlotItemFlags_NoFit)) {\n            FitPoint(PixelsToPlot(pos));\n            FitPoint(PixelsToPlot(pos.x + siz.x, pos.y - siz.y));\n        }\n        AddTextVertical(&draw_list, pos, colTxt, text);\n    }\n    else {\n        ImVec2 siz = ImGui::CalcTextSize(text);\n        ImVec2 pos = PlotToPixels(ImPlotPoint(x,y),IMPLOT_AUTO,IMPLOT_AUTO) - siz * 0.5f + pixel_offset;\n        if (FitThisFrame() && !ImHasFlag(flags, ImPlotItemFlags_NoFit)) {\n            FitPoint(PixelsToPlot(pos));\n            FitPoint(PixelsToPlot(pos+siz));\n        }\n        draw_list.AddText(pos, colTxt, text);\n    }\n    PopPlotClipRect();\n}\n\n//-----------------------------------------------------------------------------\n// [SECTION] PlotDummy\n//-----------------------------------------------------------------------------\n\nvoid PlotDummy(const char* label_id, ImPlotDummyFlags flags) {\n    if (BeginItem(label_id, flags, ImPlotCol_Line))\n        EndItem();\n}\n\n} // namespace ImPlot\n"
  },
  {
    "path": "Source/External/imgui_tools/xmake.lua",
    "content": ""
  },
  {
    "path": "Source/External/mustache/mustache.hpp",
    "content": "/*\n * Boost Software License - Version 1.0\n *\n * Mustache\n * Copyright 2015-2020 Kevin Wojniak\n *\n * Permission is hereby granted, free of charge, to any person or organization\n * obtaining a copy of the software and accompanying documentation covered by\n * this license (the \"Software\") to use, reproduce, display, distribute,\n * execute, and transmit the Software, and to prepare derivative works of the\n * Software, and to permit third-parties to whom the Software is furnished to\n * do so, all subject to the following:\n *\n * The copyright notices in the Software and this entire statement, including\n * the above license grant, this restriction and the following disclaimer,\n * must be included in all copies of the Software, in whole or in part, and\n * all derivative works of the Software, unless such copies or derivative\n * works are solely in the form of machine-executable object code generated by\n * a source language processor.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef KAINJOW_MUSTACHE_HPP\n#define KAINJOW_MUSTACHE_HPP\n\n#include <cassert>\n#include <cctype>\n#include <functional>\n#include <iostream>\n#include <memory>\n#include <sstream>\n#include <unordered_map>\n#include <vector>\n\n#define KAINJOW_MUSTACHE_VERSION_MAJOR 5\n#define KAINJOW_MUSTACHE_VERSION_MINOR 0\n#define KAINJOW_MUSTACHE_VERSION_PATCH 0\n\nnamespace kainjow {\nnamespace mustache {\n\ntemplate <typename string_type>\nstring_type trim(const string_type& s) {\n    auto it = s.begin();\n    while (it != s.end() && std::isspace(*it)) {\n        it++;\n    }\n    auto rit = s.rbegin();\n    while (rit.base() != it && std::isspace(*rit)) {\n        rit++;\n    }\n    return {it, rit.base()};\n}\n\ntemplate <typename string_type>\nstring_type html_escape(const string_type& s) {\n    string_type ret;\n    ret.reserve(s.size()*2);\n    for (const auto ch : s) {\n        switch (ch) {\n            case '&':\n                ret.append({'&','a','m','p',';'});\n                break;\n            case '<':\n                ret.append({'&','l','t',';'});\n                break;\n            case '>':\n                ret.append({'&','g','t',';'});\n                break;\n            case '\\\"':\n                ret.append({'&','q','u','o','t',';'});\n                break;\n            case '\\'':\n                ret.append({'&','a','p','o','s',';'});\n                break;\n            default:\n                ret.append(1, ch);\n                break;\n        }\n    }\n    return ret;\n}\n\ntemplate <typename string_type>\nstd::vector<string_type> split(const string_type& s, typename string_type::value_type delim) {\n    std::vector<string_type> elems;\n    std::basic_stringstream<typename string_type::value_type> ss(s);\n    string_type item;\n    while (std::getline(ss, item, delim)) {\n        elems.push_back(item);\n    }\n    return elems;\n}\n\ntemplate <typename string_type>\nclass basic_renderer {\npublic:\n    using type1 = std::function<string_type(const string_type&)>;\n    using type2 = std::function<string_type(const string_type&, bool escaped)>;\n\n    string_type operator()(const string_type& text) const {\n        return type1_(text);\n    }\n\n    string_type operator()(const string_type& text, bool escaped) const {\n        return type2_(text, escaped);\n    }\n\nprivate:\n    basic_renderer(const type1& t1, const type2& t2)\n        : type1_(t1)\n        , type2_(t2)\n    {}\n\n    const type1& type1_;\n    const type2& type2_;\n\n    template <typename StringType>\n    friend class basic_mustache;\n};\n\ntemplate <typename string_type>\nclass basic_lambda_t {\npublic:\n    using type1 = std::function<string_type(const string_type&)>;\n    using type2 = std::function<string_type(const string_type&, const basic_renderer<string_type>& render)>;\n\n    basic_lambda_t(const type1& t) : type1_(new type1(t)) {}\n    basic_lambda_t(const type2& t) : type2_(new type2(t)) {}\n\n    bool is_type1() const { return static_cast<bool>(type1_); }\n    bool is_type2() const { return static_cast<bool>(type2_); }\n\n    const type1& type1_value() const { return *type1_; }\n    const type2& type2_value() const { return *type2_; }\n\n    // Copying\n    basic_lambda_t(const basic_lambda_t& l) {\n        if (l.type1_) {\n            type1_.reset(new type1(*l.type1_));\n        } else if (l.type2_) {\n            type2_.reset(new type2(*l.type2_));\n        }\n    }\n\n    string_type operator()(const string_type& text) const {\n        return (*type1_)(text);\n    }\n\n    string_type operator()(const string_type& text, const basic_renderer<string_type>& render) const {\n        return (*type2_)(text, render);\n    }\n\nprivate:\n    std::unique_ptr<type1> type1_;\n    std::unique_ptr<type2> type2_;\n};\n\ntemplate <typename string_type>\nclass basic_data;\ntemplate <typename string_type>\nusing basic_object = std::unordered_map<string_type, basic_data<string_type>>;\ntemplate <typename string_type>\nusing basic_list = std::vector<basic_data<string_type>>;\ntemplate <typename string_type>\nusing basic_partial = std::function<string_type()>;\ntemplate <typename string_type>\nusing basic_lambda = typename basic_lambda_t<string_type>::type1;\ntemplate <typename string_type>\nusing basic_lambda2 = typename basic_lambda_t<string_type>::type2;\n\ntemplate <typename string_type>\nclass basic_data {\npublic:\n    enum class type {\n        object,\n        string,\n        list,\n        bool_true,\n        bool_false,\n        partial,\n        lambda,\n        lambda2,\n        invalid,\n    };\n\n    // Construction\n    basic_data() : basic_data(type::object) {\n    }\n    basic_data(const string_type& string) : type_{type::string} {\n        str_.reset(new string_type(string));\n    }\n    basic_data(const typename string_type::value_type* string) : type_{type::string} {\n        str_.reset(new string_type(string));\n    }\n    basic_data(const basic_object<string_type>& obj) : type_{type::object} {\n        obj_.reset(new basic_object<string_type>(obj));\n    }\n    basic_data(const basic_list<string_type>& l) : type_{type::list} {\n        list_.reset(new basic_list<string_type>(l));\n    }\n    basic_data(type t) : type_{t} {\n        switch (type_) {\n            case type::object:\n                obj_.reset(new basic_object<string_type>);\n                break;\n            case type::string:\n                str_.reset(new string_type);\n                break;\n            case type::list:\n                list_.reset(new basic_list<string_type>);\n                break;\n            default:\n                break;\n        }\n    }\n    basic_data(const string_type& name, const basic_data& var) : basic_data{} {\n        set(name, var);\n    }\n    basic_data(const basic_partial<string_type>& p) : type_{type::partial} {\n        partial_.reset(new basic_partial<string_type>(p));\n    }\n    basic_data(const basic_lambda<string_type>& l) : type_{type::lambda} {\n        lambda_.reset(new basic_lambda_t<string_type>(l));\n    }\n    basic_data(const basic_lambda2<string_type>& l) : type_{type::lambda2} {\n        lambda_.reset(new basic_lambda_t<string_type>(l));\n    }\n    basic_data(const basic_lambda_t<string_type>& l) {\n        if (l.is_type1()) {\n            type_ = type::lambda;\n        } else if (l.is_type2()) {\n            type_ = type::lambda2;\n        }\n        lambda_.reset(new basic_lambda_t<string_type>(l));\n    }\n    basic_data(bool b) : type_{b ? type::bool_true : type::bool_false} {\n    }\n\n    // Copying\n    basic_data(const basic_data& dat) : type_(dat.type_) {\n        if (dat.obj_) {\n            obj_.reset(new basic_object<string_type>(*dat.obj_));\n        } else if (dat.str_) {\n            str_.reset(new string_type(*dat.str_));\n        } else if (dat.list_) {\n            list_.reset(new basic_list<string_type>(*dat.list_));\n        } else if (dat.partial_) {\n            partial_.reset(new basic_partial<string_type>(*dat.partial_));\n        } else if (dat.lambda_) {\n            lambda_.reset(new basic_lambda_t<string_type>(*dat.lambda_));\n        }\n    }\n\n    // Move\n    basic_data(basic_data&& dat) : type_{dat.type_} {\n        if (dat.obj_) {\n            obj_ = std::move(dat.obj_);\n        } else if (dat.str_) {\n            str_ = std::move(dat.str_);\n        } else if (dat.list_) {\n            list_ = std::move(dat.list_);\n        } else if (dat.partial_) {\n            partial_ = std::move(dat.partial_);\n        } else if (dat.lambda_) {\n            lambda_ = std::move(dat.lambda_);\n        }\n        dat.type_ = type::invalid;\n    }\n    basic_data& operator= (basic_data&& dat) {\n        if (this != &dat) {\n            obj_.reset();\n            str_.reset();\n            list_.reset();\n            partial_.reset();\n            lambda_.reset();\n            if (dat.obj_) {\n                obj_ = std::move(dat.obj_);\n            } else if (dat.str_) {\n                str_ = std::move(dat.str_);\n            } else if (dat.list_) {\n                list_ = std::move(dat.list_);\n            } else if (dat.partial_) {\n                partial_ = std::move(dat.partial_);\n            } else if (dat.lambda_) {\n                lambda_ = std::move(dat.lambda_);\n            }\n            type_ = dat.type_;\n            dat.type_ = type::invalid;\n        }\n        return *this;\n    }\n\n    // Type info\n    bool is_object() const {\n        return type_ == type::object;\n    }\n    bool is_string() const {\n        return type_ == type::string;\n    }\n    bool is_list() const {\n        return type_ == type::list;\n    }\n    bool is_bool() const {\n        return is_true() || is_false();\n    }\n    bool is_true() const {\n        return type_ == type::bool_true;\n    }\n    bool is_false() const {\n        return type_ == type::bool_false;\n    }\n    bool is_partial() const {\n        return type_ == type::partial;\n    }\n    bool is_lambda() const {\n        return type_ == type::lambda;\n    }\n    bool is_lambda2() const {\n        return type_ == type::lambda2;\n    }\n    bool is_invalid() const {\n        return type_ == type::invalid;\n    }\n\n    // Object data\n    bool is_empty_object() const {\n        return is_object() && obj_->empty();\n    }\n    bool is_non_empty_object() const {\n        return is_object() && !obj_->empty();\n    }\n    void set(const string_type& name, const basic_data& var) {\n        if (is_object()) {\n            auto it = obj_->find(name);\n            if (it != obj_->end()) {\n                obj_->erase(it);\n            }\n            obj_->insert(std::pair<string_type,basic_data>{name, var});\n        }\n    }\n    const basic_data* get(const string_type& name) const {\n        if (!is_object()) {\n            return nullptr;\n        }\n        const auto& it = obj_->find(name);\n        if (it == obj_->end()) {\n            return nullptr;\n        }\n        return &it->second;\n    }\n\n    // List data\n    void push_back(const basic_data& var) {\n        if (is_list()) {\n            list_->push_back(var);\n        }\n    }\n    const basic_list<string_type>& list_value() const {\n        return *list_;\n    }\n    bool is_empty_list() const {\n        return is_list() && list_->empty();\n    }\n    bool is_non_empty_list() const {\n        return is_list() && !list_->empty();\n    }\n    basic_data& operator<< (const basic_data& data) {\n        push_back(data);\n        return *this;\n    }\n\n    // String data\n    const string_type& string_value() const {\n        return *str_;\n    }\n\n    basic_data& operator[] (const string_type& key) {\n        return (*obj_)[key];\n    }\n\n    const basic_partial<string_type>& partial_value() const {\n        return (*partial_);\n    }\n\n    const basic_lambda<string_type>& lambda_value() const {\n        return lambda_->type1_value();\n    }\n\n    const basic_lambda2<string_type>& lambda2_value() const {\n        return lambda_->type2_value();\n    }\n\nprivate:\n    type type_;\n    std::unique_ptr<basic_object<string_type>> obj_;\n    std::unique_ptr<string_type> str_;\n    std::unique_ptr<basic_list<string_type>> list_;\n    std::unique_ptr<basic_partial<string_type>> partial_;\n    std::unique_ptr<basic_lambda_t<string_type>> lambda_;\n};\n\ntemplate <typename string_type>\nclass delimiter_set {\npublic:\n    string_type begin;\n    string_type end;\n    delimiter_set()\n        : begin(default_begin)\n        , end(default_end)\n    {}\n    bool is_default() const { return begin == default_begin && end == default_end; }\n    static const string_type default_begin;\n    static const string_type default_end;\n};\n\ntemplate <typename string_type>\nconst string_type delimiter_set<string_type>::default_begin(2, '{');\ntemplate <typename string_type>\nconst string_type delimiter_set<string_type>::default_end(2, '}');\n\ntemplate <typename string_type>\nclass basic_context {\npublic:\n    virtual ~basic_context() = default;\n    virtual void push(const basic_data<string_type>* data) = 0;\n    virtual void pop() = 0;\n\n    virtual const basic_data<string_type>* get(const string_type& name) const = 0;\n    virtual const basic_data<string_type>* get_partial(const string_type& name) const = 0;\n};\n\ntemplate <typename string_type>\nclass context : public basic_context<string_type> {\npublic:\n    context(const basic_data<string_type>* data) {\n        push(data);\n    }\n\n    context() {\n    }\n\n    virtual void push(const basic_data<string_type>* data) override {\n        items_.insert(items_.begin(), data);\n    }\n\n    virtual void pop() override {\n        items_.erase(items_.begin());\n    }\n\n    virtual const basic_data<string_type>* get(const string_type& name) const override {\n        // process {{.}} name\n        if (name.size() == 1 && name.at(0) == '.') {\n            return items_.front();\n        }\n        if (name.find('.') == string_type::npos) {\n            // process normal name without having to split which is slower\n            for (const auto& item : items_) {\n                const auto var = item->get(name);\n                if (var) {\n                    return var;\n                }\n            }\n            return nullptr;\n        }\n        // process x.y-like name\n        const auto names = split(name, '.');\n        for (const auto& item : items_) {\n            auto var = item;\n            for (const auto& n : names) {\n                var = var->get(n);\n                if (!var) {\n                    break;\n                }\n            }\n            if (var) {\n                return var;\n            }\n        }\n        return nullptr;\n    }\n\n    virtual const basic_data<string_type>* get_partial(const string_type& name) const override {\n        for (const auto& item : items_) {\n            const auto var = item->get(name);\n            if (var) {\n                return var;\n            }\n        }\n        return nullptr;\n    }\n\n    context(const context&) = delete;\n    context& operator= (const context&) = delete;\n\nprivate:\n    std::vector<const basic_data<string_type>*> items_;\n};\n\ntemplate <typename string_type>\nclass line_buffer_state {\npublic:\n    string_type data;\n    bool contained_section_tag = false;\n\n    bool is_empty_or_contains_only_whitespace() const {\n        for (const auto ch : data) {\n            // don't look at newlines\n            if (ch != ' ' && ch != '\\t') {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    void clear() {\n        data.clear();\n        contained_section_tag = false;\n    }\n};\n\ntemplate <typename string_type>\nclass context_internal {\npublic:\n    basic_context<string_type>& ctx;\n    delimiter_set<string_type> delim_set;\n    line_buffer_state<string_type> line_buffer;\n\n    context_internal(basic_context<string_type>& a_ctx)\n        : ctx(a_ctx)\n    {\n    }\n};\n\nenum class tag_type {\n    text,\n    variable,\n    unescaped_variable,\n    section_begin,\n    section_end,\n    section_begin_inverted,\n    comment,\n    partial,\n    set_delimiter,\n};\n\ntemplate <typename string_type>\nclass mstch_tag /* gcc doesn't allow \"tag tag;\" so rename the class :( */ {\npublic:\n    string_type name;\n    tag_type type = tag_type::text;\n    std::shared_ptr<string_type> section_text;\n    std::shared_ptr<delimiter_set<string_type>> delim_set;\n    bool is_section_begin() const {\n        return type == tag_type::section_begin || type == tag_type::section_begin_inverted;\n    }\n    bool is_section_end() const {\n        return type == tag_type::section_end;\n    }\n};\n\ntemplate <typename string_type>\nclass context_pusher {\npublic:\n    context_pusher(context_internal<string_type>& ctx, const basic_data<string_type>* data)\n        : ctx_(ctx)\n    {\n        ctx.ctx.push(data);\n    }\n    ~context_pusher() {\n        ctx_.ctx.pop();\n    }\n    context_pusher(const context_pusher&) = delete;\n    context_pusher& operator= (const context_pusher&) = delete;\nprivate:\n    context_internal<string_type>& ctx_;\n};\n\ntemplate <typename string_type>\nclass component {\nprivate:\n    using string_size_type = typename string_type::size_type;\n\npublic:\n    string_type text;\n    mstch_tag<string_type> tag;\n    std::vector<component> children;\n    string_size_type position = string_type::npos;\n\n    enum class walk_control {\n        walk, // \"continue\" is reserved :/\n        stop,\n        skip,\n    };\n    using walk_callback = std::function<walk_control(component&)>;\n\n    component() {}\n    component(const string_type& t, string_size_type p) : text(t), position(p) {}\n\n    bool is_text() const {\n        return tag.type == tag_type::text;\n    }\n\n    bool is_newline() const {\n        return is_text() && ((text.size() == 2 && text[0] == '\\r' && text[1] == '\\n') ||\n        (text.size() == 1 && (text[0] == '\\n' || text[0] == '\\r')));\n    }\n\n    bool is_non_newline_whitespace() const {\n        return is_text() && !is_newline() && text.size() == 1 && (text[0] == ' ' || text[0] == '\\t');\n    }\n\n    void walk_children(const walk_callback& callback) {\n        for (auto& child : children) {\n            if (child.walk(callback) != walk_control::walk) {\n                break;\n            }\n        }\n    }\n\nprivate:\n    walk_control walk(const walk_callback& callback) {\n        walk_control control{callback(*this)};\n        if (control == walk_control::stop) {\n            return control;\n        } else if (control == walk_control::skip) {\n            return walk_control::walk;\n        }\n        for (auto& child : children) {\n            control = child.walk(callback);\n            if (control == walk_control::stop) {\n                return control;\n            }\n        }\n        return control;\n    }\n};\n\ntemplate <typename string_type>\nclass parser {\npublic:\n    parser(const string_type& input, context_internal<string_type>& ctx, component<string_type>& root_component, string_type& error_message)\n    {\n        parse(input, ctx, root_component, error_message);\n    }\n\nprivate:\n    void parse(const string_type& input, context_internal<string_type>& ctx, component<string_type>& root_component, string_type& error_message) const {\n        using string_size_type = typename string_type::size_type;\n        using streamstring = std::basic_ostringstream<typename string_type::value_type>;\n\n        const string_type brace_delimiter_end_unescaped(3, '}');\n        const string_size_type input_size{input.size()};\n\n        bool current_delimiter_is_brace{ctx.delim_set.is_default()};\n\n        std::vector<component<string_type>*> sections{&root_component};\n        std::vector<string_size_type> section_starts;\n        string_type current_text;\n        string_size_type current_text_position = string_type::npos;\n\n        current_text.reserve(input_size);\n\n        const auto process_current_text = [&current_text, &current_text_position, &sections]() {\n            if (!current_text.empty()) {\n                const component<string_type> comp{current_text, current_text_position};\n                sections.back()->children.push_back(comp);\n                current_text.clear();\n                current_text_position = string_type::npos;\n            }\n        };\n\n        const std::vector<string_type> whitespace{\n            string_type(1, '\\r') + string_type(1, '\\n'),\n            string_type(1, '\\n'),\n            string_type(1, '\\r'),\n            string_type(1, ' '),\n            string_type(1, '\\t'),\n        };\n\n        for (string_size_type input_position = 0; input_position != input_size;) {\n            bool parse_tag = false;\n\n            if (input.compare(input_position, ctx.delim_set.begin.size(), ctx.delim_set.begin) == 0) {\n                process_current_text();\n\n                // Tag start delimiter\n                parse_tag = true;\n            } else {\n                bool parsed_whitespace = false;\n                for (const auto& whitespace_text : whitespace) {\n                    if (input.compare(input_position, whitespace_text.size(), whitespace_text) == 0) {\n                        process_current_text();\n\n                        const component<string_type> comp{whitespace_text, input_position};\n                        sections.back()->children.push_back(comp);\n                        input_position += whitespace_text.size();\n\n                        parsed_whitespace = true;\n                        break;\n                    }\n                }\n\n                if (!parsed_whitespace) {\n                    if (current_text.empty()) {\n                        current_text_position = input_position;\n                    }\n                    current_text.append(1, input[input_position]);\n                    input_position++;\n                }\n            }\n\n            if (!parse_tag) {\n                continue;\n            }\n\n            // Find the next tag start delimiter\n            const string_size_type tag_location_start = input_position;\n\n            // Find the next tag end delimiter\n            string_size_type tag_contents_location{tag_location_start + ctx.delim_set.begin.size()};\n            const bool tag_is_unescaped_var{current_delimiter_is_brace && tag_location_start != (input_size - 2) && input.at(tag_contents_location) == ctx.delim_set.begin.at(0)};\n            const string_type& current_tag_delimiter_end{tag_is_unescaped_var ? brace_delimiter_end_unescaped : ctx.delim_set.end};\n            const auto current_tag_delimiter_end_size = current_tag_delimiter_end.size();\n            if (tag_is_unescaped_var) {\n                ++tag_contents_location;\n            }\n            const string_size_type tag_location_end{input.find(current_tag_delimiter_end, tag_contents_location)};\n            if (tag_location_end == string_type::npos) {\n                streamstring ss;\n                ss << \"Unclosed tag at \" << tag_location_start;\n                error_message.assign(ss.str());\n                return;\n            }\n\n            // Parse tag\n            const string_type tag_contents{trim(string_type{input, tag_contents_location, tag_location_end - tag_contents_location})};\n            component<string_type> comp;\n            if (!tag_contents.empty() && tag_contents[0] == '=') {\n                if (!parse_set_delimiter_tag(tag_contents, ctx.delim_set)) {\n                    streamstring ss;\n                    ss << \"Invalid set delimiter tag at \" << tag_location_start;\n                    error_message.assign(ss.str());\n                    return;\n                }\n                current_delimiter_is_brace = ctx.delim_set.is_default();\n                comp.tag.type = tag_type::set_delimiter;\n                comp.tag.delim_set.reset(new delimiter_set<string_type>(ctx.delim_set));\n            }\n            if (comp.tag.type != tag_type::set_delimiter) {\n                parse_tag_contents(tag_is_unescaped_var, tag_contents, comp.tag);\n            }\n            comp.position = tag_location_start;\n            sections.back()->children.push_back(comp);\n\n            // Start next search after this tag\n            input_position = tag_location_end + current_tag_delimiter_end_size;\n\n            // Push or pop sections\n            if (comp.tag.is_section_begin()) {\n                sections.push_back(&sections.back()->children.back());\n                section_starts.push_back(input_position);\n            } else if (comp.tag.is_section_end()) {\n                if (sections.size() == 1) {\n                    streamstring ss;\n                    ss << \"Unopened section \\\"\" << comp.tag.name << \"\\\" at \" << comp.position;\n                    error_message.assign(ss.str());\n                    return;\n                }\n                sections.back()->tag.section_text.reset(new string_type(input.substr(section_starts.back(), tag_location_start - section_starts.back())));\n                sections.pop_back();\n                section_starts.pop_back();\n            }\n        }\n\n        process_current_text();\n\n        // Check for sections without an ending tag\n        root_component.walk_children([&error_message](component<string_type>& comp) -> typename component<string_type>::walk_control {\n            if (!comp.tag.is_section_begin()) {\n                return component<string_type>::walk_control::walk;\n            }\n            if (comp.children.empty() || !comp.children.back().tag.is_section_end() || comp.children.back().tag.name != comp.tag.name) {\n                streamstring ss;\n                ss << \"Unclosed section \\\"\" << comp.tag.name << \"\\\" at \" << comp.position;\n                error_message.assign(ss.str());\n                return component<string_type>::walk_control::stop;\n            }\n            comp.children.pop_back(); // remove now useless end section component\n            return component<string_type>::walk_control::walk;\n        });\n        if (!error_message.empty()) {\n            return;\n        }\n    }\n\n    bool is_set_delimiter_valid(const string_type& delimiter) const {\n        // \"Custom delimiters may not contain whitespace or the equals sign.\"\n        for (const auto ch : delimiter) {\n            if (ch == '=' || std::isspace(ch)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    bool parse_set_delimiter_tag(const string_type& contents, delimiter_set<string_type>& delimiter_set) const {\n        // Smallest legal tag is \"=X X=\"\n        if (contents.size() < 5) {\n            return false;\n        }\n        if (contents.back() != '=') {\n            return false;\n        }\n        const auto contents_substr = trim(contents.substr(1, contents.size() - 2));\n        const auto spacepos = contents_substr.find(' ');\n        if (spacepos == string_type::npos) {\n            return false;\n        }\n        const auto nonspace = contents_substr.find_first_not_of(' ', spacepos + 1);\n        assert(nonspace != string_type::npos);\n        const string_type begin = contents_substr.substr(0, spacepos);\n        const string_type end = contents_substr.substr(nonspace, contents_substr.size() - nonspace);\n        if (!is_set_delimiter_valid(begin) || !is_set_delimiter_valid(end)) {\n            return false;\n        }\n        delimiter_set.begin = begin;\n        delimiter_set.end = end;\n        return true;\n    }\n\n    void parse_tag_contents(bool is_unescaped_var, const string_type& contents, mstch_tag<string_type>& tag) const {\n        if (is_unescaped_var) {\n            tag.type = tag_type::unescaped_variable;\n            tag.name = contents;\n        } else if (contents.empty()) {\n            tag.type = tag_type::variable;\n            tag.name.clear();\n        } else {\n            switch (contents.at(0)) {\n                case '#':\n                    tag.type = tag_type::section_begin;\n                    break;\n                case '^':\n                    tag.type = tag_type::section_begin_inverted;\n                    break;\n                case '/':\n                    tag.type = tag_type::section_end;\n                    break;\n                case '>':\n                    tag.type = tag_type::partial;\n                    break;\n                case '&':\n                    tag.type = tag_type::unescaped_variable;\n                    break;\n                case '!':\n                    tag.type = tag_type::comment;\n                    break;\n                default:\n                    tag.type = tag_type::variable;\n                    break;\n            }\n            if (tag.type == tag_type::variable) {\n                tag.name = contents;\n            } else {\n                string_type name{contents};\n                name.erase(name.begin());\n                tag.name = trim(name);\n            }\n        }\n    }\n};\n\ntemplate <typename StringType>\nclass basic_mustache {\npublic:\n    using string_type = StringType;\n\n    basic_mustache(const string_type& input)\n        : basic_mustache() {\n        context<string_type> ctx;\n        context_internal<string_type> context{ctx};\n        parser<string_type> parser{input, context, root_component_, error_message_};\n    }\n\n    bool is_valid() const {\n        return error_message_.empty();\n    }\n\n    const string_type& error_message() const {\n        return error_message_;\n    }\n\n    using escape_handler = std::function<string_type(const string_type&)>;\n    void set_custom_escape(const escape_handler& escape_fn) {\n        escape_ = escape_fn;\n    }\n\n    template <typename stream_type>\n    stream_type& render(const basic_data<string_type>& data, stream_type& stream) {\n        render(data, [&stream](const string_type& str) {\n            stream << str;\n        });\n        return stream;\n    }\n\n    string_type render(const basic_data<string_type>& data) {\n        std::basic_ostringstream<typename string_type::value_type> ss;\n        return render(data, ss).str();\n    }\n\n    template <typename stream_type>\n    stream_type& render(basic_context<string_type>& ctx, stream_type& stream) {\n        context_internal<string_type> context{ctx};\n        render([&stream](const string_type& str) {\n            stream << str;\n        }, context);\n        return stream;\n    }\n\n    string_type render(basic_context<string_type>& ctx) {\n        std::basic_ostringstream<typename string_type::value_type> ss;\n        return render(ctx, ss).str();\n    }\n\n    using render_handler = std::function<void(const string_type&)>;\n    void render(const basic_data<string_type>& data, const render_handler& handler) {\n        if (!is_valid()) {\n            return;\n        }\n        context<string_type> ctx{&data};\n        context_internal<string_type> context{ctx};\n        render(handler, context);\n    }\n\n    basic_mustache()\n        : escape_(html_escape<string_type>)\n    {\n    }\n    \nprivate:\n    using string_size_type = typename string_type::size_type;\n\n\n    basic_mustache(const string_type& input, context_internal<string_type>& ctx)\n        : basic_mustache() {\n        parser<string_type> parser{input, ctx, root_component_, error_message_};\n    }\n\n    string_type render(context_internal<string_type>& ctx) {\n        std::basic_ostringstream<typename string_type::value_type> ss;\n        render([&ss](const string_type& str) {\n            ss << str;\n        }, ctx);\n        return ss.str();\n    }\n\n    void render(const render_handler& handler, context_internal<string_type>& ctx, bool root_renderer = true) {\n        root_component_.walk_children([&handler, &ctx, this](component<string_type>& comp) -> typename component<string_type>::walk_control {\n            return render_component(handler, ctx, comp);\n        });\n        // process the last line, but only for the top-level renderer\n        if (root_renderer) {\n            render_current_line(handler, ctx, nullptr);\n        }\n    }\n\n    void render_current_line(const render_handler& handler, context_internal<string_type>& ctx, const component<string_type>* comp) const {\n        // We're at the end of a line, so check the line buffer state to see\n        // if the line had tags in it, and also if the line is now empty or\n        // contains whitespace only. if this situation is true, skip the line.\n        bool output = true;\n        if (ctx.line_buffer.contained_section_tag && ctx.line_buffer.is_empty_or_contains_only_whitespace()) {\n            output = false;\n        }\n        if (output) {\n            handler(ctx.line_buffer.data);\n            if (comp) {\n                handler(comp->text);\n            }\n        }\n        ctx.line_buffer.clear();\n    }\n\n    void render_result(context_internal<string_type>& ctx, const string_type& text) const {\n        ctx.line_buffer.data.append(text);\n    }\n\n    typename component<string_type>::walk_control render_component(const render_handler& handler, context_internal<string_type>& ctx, component<string_type>& comp) {\n        if (comp.is_text()) {\n            if (comp.is_newline()) {\n                render_current_line(handler, ctx, &comp);\n            } else {\n                render_result(ctx, comp.text);\n            }\n            return component<string_type>::walk_control::walk;\n        }\n\n        const mstch_tag<string_type>& tag{comp.tag};\n        const basic_data<string_type>* var = nullptr;\n        switch (tag.type) {\n            case tag_type::variable:\n            case tag_type::unescaped_variable:\n                if ((var = ctx.ctx.get(tag.name)) != nullptr) {\n                    if (!render_variable(handler, var, ctx, tag.type == tag_type::variable)) {\n                        return component<string_type>::walk_control::stop;\n                    }\n                }\n                break;\n            case tag_type::section_begin:\n                if ((var = ctx.ctx.get(tag.name)) != nullptr) {\n                    if (var->is_lambda() || var->is_lambda2()) {\n                        if (!render_lambda(handler, var, ctx, render_lambda_escape::optional, *comp.tag.section_text, true)) {\n                            return component<string_type>::walk_control::stop;\n                        }\n                    } else if (!var->is_false() && !var->is_empty_list()) {\n                        render_section(handler, ctx, comp, var);\n                    }\n                }\n                return component<string_type>::walk_control::skip;\n            case tag_type::section_begin_inverted:\n                if ((var = ctx.ctx.get(tag.name)) == nullptr || var->is_false() || var->is_empty_list()) {\n                    render_section(handler, ctx, comp, var);\n                }\n                return component<string_type>::walk_control::skip;\n            case tag_type::partial:\n                if ((var = ctx.ctx.get_partial(tag.name)) != nullptr && (var->is_partial() || var->is_string())) {\n                    const auto& partial_result = var->is_partial() ? var->partial_value()() : var->string_value();\n                    basic_mustache tmpl{partial_result};\n                    tmpl.set_custom_escape(escape_);\n                    if (!tmpl.is_valid()) {\n                        error_message_ = tmpl.error_message();\n                    } else {\n                        tmpl.render(handler, ctx, false);\n                        if (!tmpl.is_valid()) {\n                            error_message_ = tmpl.error_message();\n                        }\n                    }\n                    if (!tmpl.is_valid()) {\n                        return component<string_type>::walk_control::stop;\n                    }\n                }\n                break;\n            case tag_type::set_delimiter:\n                ctx.delim_set = *comp.tag.delim_set;\n                break;\n            default:\n                break;\n        }\n\n        return component<string_type>::walk_control::walk;\n    }\n\n    enum class render_lambda_escape {\n        escape,\n        unescape,\n        optional,\n    };\n\n    bool render_lambda(const render_handler& handler, const basic_data<string_type>* var, context_internal<string_type>& ctx, render_lambda_escape escape, const string_type& text, bool parse_with_same_context) {\n        const typename basic_renderer<string_type>::type2 render2 = [this, &ctx, parse_with_same_context, escape](const string_type& text, bool escaped) {\n            const auto process_template = [this, &ctx, escape, escaped](basic_mustache& tmpl) -> string_type {\n                if (!tmpl.is_valid()) {\n                    error_message_ = tmpl.error_message();\n                    return {};\n                }\n                context_internal<string_type> render_ctx{ctx.ctx}; // start a new line_buffer\n                const auto str = tmpl.render(render_ctx);\n                if (!tmpl.is_valid()) {\n                    error_message_ = tmpl.error_message();\n                    return {};\n                }\n                bool do_escape = false;\n                switch (escape) {\n                    case render_lambda_escape::escape:\n                        do_escape = true;\n                        break;\n                    case render_lambda_escape::unescape:\n                        do_escape = false;\n                        break;\n                    case render_lambda_escape::optional:\n                        do_escape = escaped;\n                        break;\n                }\n                return do_escape ? escape_(str) : str;\n            };\n            if (parse_with_same_context) {\n                basic_mustache tmpl{text, ctx};\n                tmpl.set_custom_escape(escape_);\n                return process_template(tmpl);\n            }\n            basic_mustache tmpl{text};\n            tmpl.set_custom_escape(escape_);\n            return process_template(tmpl);\n        };\n        const typename basic_renderer<string_type>::type1 render = [&render2](const string_type& text) {\n            return render2(text, false);\n        };\n        if (var->is_lambda2()) {\n            const basic_renderer<string_type> renderer{render, render2};\n            render_result(ctx, var->lambda2_value()(text, renderer));\n        } else {\n            render_current_line(handler, ctx, nullptr);\n            render_result(ctx, render(var->lambda_value()(text)));\n        }\n        return error_message_.empty();\n    }\n\n    bool render_variable(const render_handler& handler, const basic_data<string_type>* var, context_internal<string_type>& ctx, bool escaped) {\n        if (var->is_string()) {\n            const auto& varstr = var->string_value();\n            render_result(ctx, escaped ? escape_(varstr) : varstr);\n        } else if (var->is_lambda()) {\n            const render_lambda_escape escape_opt = escaped ? render_lambda_escape::escape : render_lambda_escape::unescape;\n            return render_lambda(handler, var, ctx, escape_opt, {}, false);\n        } else if (var->is_lambda2()) {\n            using streamstring = std::basic_ostringstream<typename string_type::value_type>;\n            streamstring ss;\n            ss << \"Lambda with render argument is not allowed for regular variables\";\n            error_message_ = ss.str();\n            return false;\n        }\n        return true;\n    }\n\n    void render_section(const render_handler& handler, context_internal<string_type>& ctx, component<string_type>& incomp, const basic_data<string_type>* var) {\n        const auto callback = [&handler, &ctx, this](component<string_type>& comp) -> typename component<string_type>::walk_control {\n            return render_component(handler, ctx, comp);\n        };\n        if (var && var->is_non_empty_list()) {\n            for (const auto& item : var->list_value()) {\n                // account for the section begin tag\n                ctx.line_buffer.contained_section_tag = true;\n\n                const context_pusher<string_type> ctxpusher{ctx, &item};\n                incomp.walk_children(callback);\n\n                // ctx may have been cleared. account for the section end tag\n                ctx.line_buffer.contained_section_tag = true;\n            }\n        } else if (var) {\n            // account for the section begin tag\n            ctx.line_buffer.contained_section_tag = true;\n\n            const context_pusher<string_type> ctxpusher{ctx, var};\n            incomp.walk_children(callback);\n\n            // ctx may have been cleared. account for the section end tag\n            ctx.line_buffer.contained_section_tag = true;\n        } else {\n            // account for the section begin tag\n            ctx.line_buffer.contained_section_tag = true;\n\n            incomp.walk_children(callback);\n\n            // ctx may have been cleared. account for the section end tag\n            ctx.line_buffer.contained_section_tag = true;\n        }\n    }\n\nprivate:\n    string_type error_message_;\n    component<string_type> root_component_;\n    escape_handler escape_;\n};\n\nusing mustache = basic_mustache<std::string>;\nusing data = basic_data<mustache::string_type>;\nusing object = basic_object<mustache::string_type>;\nusing list = basic_list<mustache::string_type>;\nusing partial = basic_partial<mustache::string_type>;\nusing renderer = basic_renderer<mustache::string_type>;\nusing lambda = basic_lambda<mustache::string_type>;\nusing lambda2 = basic_lambda2<mustache::string_type>;\nusing lambda_t = basic_lambda_t<mustache::string_type>;\n\nusing mustachew = basic_mustache<std::wstring>;\nusing dataw = basic_data<mustachew::string_type>;\n\n} // namespace mustache\n} // namespace kainjow\n\n#endif // KAINJOW_MUSTACHE_HPP\n"
  },
  {
    "path": "Source/External/slang/docs/64bit-type-support.md",
    "content": "Slang 64-bit Type Support\n=========================\n\n## Summary\n\n* Not all targets support 64 bit types, or all 64 bit types \n  * 64 bit integers generally require later APIs/shader models\n* When specifying 64 bit literals *always* use the type suffixes (ie `L`, `ULL`, `LL`) \n* GPU target/s generally do not support all double intrinsics \n  * Typically missing are trascendentals (sin, cos etc), logarithm and exponental functions\n  * CUDA is the exception supporting nearly all double intrinsics\n* D3D \n  * D3D targets *appear* to support double intrinsics (like sin, cos, log etc), but behind the scenes they are actually being converted to float\n  * When using D3D12, it is best to use DXIL if you use double because there are some serious issues around double and DXBC\n* VK will produce an error in validation if a double intrinsic is used it does support (which is most of them)\n* Vector and Matrix types have even spottier than scalar intrinsic support across targets\n\nOverview\n========\n\nThe Slang language supports 64 bit built in types. Such as\n\n* double\n* uint64_t\n* int64_t\n\nThis also applies to vector and matrix versions of these types. \n\nUnfortunately if a specific target supports the type or the typical HLSL instrinsic functions (such as sin/cos/max/min etc) depends very much on the target. \n\nSpecial attention has to be made with respect to literal 64 bit types. By default float and integer literals if they do not have an explicit suffix are assumed to be 32 bit. There is a variety of reasons for this design choice - the main one being around by default behavior of getting good performance. The suffixes required for 64 bit types are as follows\n\n```\n// double - 'l' or 'L'\n\ndouble a = 1.34e-200L;\n// WRONG!: This is the same as b = double(float(1.34e-200)) which will be 0. Will produce a warning.\ndouble b = 1.34e-200; \n\n// int64_t - 'll' or 'LL' (or combination of upper/lower)\n\nint64_t c = -5436365345345234ll;\n// WRONG!: This is the same as d = int64_t(int32_t(-5436365345345234)) which means d ! = -5436365345345234LL. \n// Will produce a warning.\nint64_t d = -5436365345345234;      \n\nint64_t e = ~0LL;       // Same as 0xffffffffffffffff\n// Does produce the same result as 'e' because equivalent int64_t(~int32_t(0))\nint64_t f = ~0;         \n\n// uint64_t - 'ull' or 'ULL' (or combination of upper/lower)\n\nuint64_t g = 0x8000000000000000ull; \n// WRONG!: This is the same as h = uint64_t(uint32_t(0x8000000000000000)) which means h = 0\n// Will produce a warning.\nuint64_t h = 0x8000000000000000u;   \n\nuint64_t i = ~0ull;       // Same as 0xffffffffffffffff\nuint64_t j = ~0;          // Equivalent to 'i' because uint64_t(int64_t(~int32_t(0)));\n```\n\nThese issues are discussed more on issue [#1185](https://github.com/shader-slang/slang/issues/1185)\n\nDouble support\n==============\n\nTarget   | Compiler/Binary  |  Double Type   |   Intrinsics          |  Notes\n---------|------------------|----------------|-----------------------|-----------\nCPU      |                  |      Yes       |          Yes          |  1\nCUDA     | Nvrtx/PTX        |      Yes       |          Yes          |  1\nD3D12    | DXC/DXIL         |      Yes       |          Small Subset |  4 \nVulkan   | GlSlang/Spir-V   |      Yes       |          Partial      |  2\nD3D11    | FXC/DXBC         |      Yes       |          Small Subset |  4\nD3D12    | FXC/DXBC         |      Yes       |          Small Subset |  3, 4\n\n1) CUDA and CPU support most intrinsics, with the notable exception currently of matrix invert\n2) In terms of lack of general intrinsic support, the restriction is described in  https://www.khronos.org/registry/spir-v/specs/1.0/GLSL.std.450.html\n\nThe following intrinsics are available for Vulkan \n\n`fmod` (as %), `rcp`, `sign`, `saturate`, `sqrt`, `rsqrt`, `frac`, `ceil`, `floor`, `trunc`, `abs`, `min`, `max`, `smoothstep`, `lerp`, `clamp`, `step` and `asuint`. \n\nThese are tested in the test `tests/hlsl-intrinsic/scalar-double-vk-intrinsic.slang`.\n\nWhat is missing are transedentals, expX, logX. \n\nNote that GlSlang does produce Spir-V that contains double intrinsic calls for the missing intrinsics, the failure happens when validating the Spir-V \n\n```\nValidation: error 0:  [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object: VK_NULL_HANDLE (Type = 0) | SPIR-V module not valid: GLSL.std.450 Sin: expected Result Type to be a 16 or 32-bit scalar or vector float type\n  %57 = OpExtInst %double %1 Sin %56\n```\n\n3) That if a RWStructuredBuffer<double> is used on D3D12 with DXBC, and a double is written, it can lead to incorrect behavior. Thus it is recommended not to use double with dxbc, but to use dxil to keep things simple. A test showing this problem is `tests/bugs/dxbc-double-problem.slang`. The test `tests/hlsl-intrinsic/scalar-double-simple.slang` shows not using a double resource, doubles do appear to work on D3D12 DXBC. \n\n4) If you compile code using double and intrinsics through Slang at first blush it will seem to work. Assuming there are no errors in your code, your code will even typically appear to work correctly. Unfortunately what is really happening is the backend compiler (fxc or dxc) compiler is narrowing double to float and then using float intrinsics. It typically generates a warning when this happens, but unless there is an error in your code you will not see these warnings because dxc doesn't appear to have a mechanism to return warnings if there isn't an error. This is why everything appears to work - but actually any intrinsic call is losing precision silently. \n\nNote on dxc by default Slang disables warnings - warnings need to be enabled to see the narrowing warnings. \n\nThere is another exception around the use of % - if you do this with double it will return an error saying on float is supported. \n\nIt appears that no intrinsics are available for double with fxc. \n\nOn dxc the following intrinsics are available with double::\n\n`rcp`, `sign`, `saturate`, `abs`, `min`, `max`, `clamp`, `asuint`. \n\nThese are tested in the test `tests/hlsl-intrinsic/scalar-double-d3d-intrinsic.slang`.\n\nThere is no suport for transcendentals (`sin`, `cos` etc) or `log`/`exp`. More surprising is that`sqrt`, `rsqrt`, `frac`, `ceil`, `floor`, `trunc`, `step`, `lerp`, `smoothstep` are also not supported.\n\nuint64_t and int64_t Support\n============================\n\nTarget   | Compiler/Binary  | u/int64_t Type |  Intrinsic support | Notes\n---------|------------------|----------------|--------------------|--------\nCPU      |                  |      Yes       |          Yes       |   \nCUDA     | Nvrtx/PTX        |      Yes       |          Yes       |   \nVulkan   | GlSlang/Spir-V   |      Yes       |          Yes       |   \nD3D12    | DXC/DXIL         |      Yes       |          Yes       |   1\nD3D11    | FXC/DXBC         |      No        |          No        |   2\nD3D12    | FXC/DXBC         |      No        |          No        |   2\n\n1) The [sm6.0 docs](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12) describe only supporting uint64_t, but dxc says int64_t is supported in [HLSL 2016](https://github.com/Microsoft/DirectXShaderCompiler/wiki/Language-Versions). Tests show that this is indeed the case.\n\n2) uint64_t support requires https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12, so DXBC is not a target.\n\nThe intrinsics available on uint64_t type are `abs`, `min`, `max`, `clamp` and `countbits`.\nThe intrinsics available on uint64_t type are `abs`, `min`, `max` and `clamp`.\n\nGLSL\n====\n\nGLSL/Spir-v based targets do not support 'generated' intrinsics on matrix types. For example 'sin(mat)' will not work on GLSL/Spir-v.\n\n"
  },
  {
    "path": "Source/External/slang/docs/README.md",
    "content": "Slang Documentation\n===================\n\nThis directory contains documentation for the Slang system.\nSome of the documentation is intended for users of the language and compiler, while other documentation is intended for developers contributing to the project.\n\nGetting Started\n---------------\n\nThe Slang [User's Guide](https://shader-slang.github.io/slang/user-guide/) provides an introduction to the Slang language and its major features.\n\nThe [API user's guide](api-users-guide.md) gives information on how to drive Slang programmatically from an application.\nThere is also documentation specific to using the [`slangc`](command-line-slangc.md) command-line tool.\n\nAdvanced Users\n--------------\n\nFor the benefit of advanced users we provide detailed documentation on how Slang compiles code for specific platforms.\nThe [target compatibility guide](target-compatibility.md) gives an overview of feature compatibility for targets. \n\nThe [CPU target guide](cpu-target.md) gives information on compiling Slang or C++ source into shared libraries/executables or functions that can be directly executed. It also covers how to generate C++ code from Slang source.  \n\nThe [CUDA target guide](cuda-target.md) provides information on compiling Slang/HLSL or CUDA source. Slang can compile to equivalent CUDA source, as well as to PTX via the nvrtc CUDA complier.\n\nContributors\n------------\n\nFor contributors to the Slang project, the information under the [`design/`](design/) directory may help explain the rationale behind certain design decisions and help when ramping up in the codebase.\n\nResearch\n--------\n\nThe Slang project is based on a long history of research work. While understanding this research is not necessary for working with Slang, it may be instructive for understanding the big-picture goals of the language, as well as why certain critical decisions were made.\n\nA [paper](http://graphics.cs.cmu.edu/projects/slang/) on the Slang system was accepted into SIGGRAPH 2018, and it provides an overview of the language and the compiler implementation.\nYong He's [dissertation](http://graphics.cs.cmu.edu/projects/renderergenerator/yong_he_thesis.pdf) provided more detailed discussion of the design of the Slang system.\n"
  },
  {
    "path": "Source/External/slang/docs/api-users-guide.md",
    "content": "Slang API User's Guide\n======================\n\nThis document is intended to guide user's who want to integrate Slang into their application programmatically.\nIt covers issues around building and linking Slang, as well as giving an overview of the main API functionality.\n\nPreliminaries\n-------------\n\nBefore using the Slang API, you'll need to link Slang into your application.\nWe recommend using a pre-built binary package, available through GitHub [releases](https://github.com/shader-slang/slang/releases).\n\nJust add the downloaded package to your include path, and make sure to add (or copy) the `slang.dll` and `slang-glslang.dll` libraries into the path of your executable.\n\nGetting Started with the API\n----------------------------\n\n### Include the Header\n\nIn order to use the Slang API, you'll need to include its header:\n\n```c\n#include <slang.h>\n```\n\nWhile the Slang implementation is C++, the header exposes a pure C interface (plus a few wrappers that only get defined for C++).\n\n### Create a Session\n\nAll interactions with the Slang API are under the control of a *session*, represented by the type `SlangSession`:\n\n```c++\nSlangSession* session = spCreateSession(NULL);\n```\n\nYou can think of the session as owning resources that can be re-used across multiple compiles.\nMost notably this includes the shader \"standard library,\" which will be parsed and checked when you first create a session.\nBy re-using a session across multiple files, you can avoid paying the cost of loading the standard library multiple times.\n\nWhen you are done with a session, you'll want to destroy it to free up these resources:\n\n```c++\nspDestroySession(session);\n```\n\n**Warning**: The majority of the Slang API is *not* currently thread safe. It is possible to use Slang across multiple threads but requires care. See the section on [multithreading](#multithreading) for more details. \n\n### Create a Compile Request\n\nA *compile request* represents an interaction where you ask Slang to compile one or more files for you, and produce some output.\nA `SlangCompileRequest` object is used both to hold the input for the request (what files and entry points you want to compile), and to communicate back output (error messages and/or code).\n\nYou can create a request using an existing session:\n\n```c++\nSlangCompileRequest* request = spCreateCompileRequest(session);\n```\n\nWhen you are done with the request you will need to destroy it to free resources:\n\n```c++\nspDestroyCompileRequest(request);\n```\n\n### Specify Compilation Options\n\n#### Code Generation Target\n\nWhen invoking the compiler, it is important to specify what kind of code you'd like Slang to generate.\nThis is done using the `SlangCompileTarget` options.\nFor example, to request output as SPIR-V binary code:\n\n```c++\nspSetCodeGenTarget(request, SLANG_SPIRV);\n```\n\n#### Include Paths\n\nIf you will be passing files with `#include` directives to Slang, you'll need to specify where it should look for those files:\n\n```c++\nspAddSearchPath(request, \"some/path/\");\n```\n\nNote that for now Slang does not support any kind of \"virtual file-system,\" although that is obviously a desirable feature to add.\n\n#### Preprocessor Definitions\n\nIf you want any kind of preprocessor macros to be defined when compiling your code, you can add global macro definitions to the compile request:\n\n```c++\nspAddPreprocessorDefine(request, \"ENABLE_FOO\", \"1\")\n```\n\nNote that Slang currently doesn't provide an automatic definition like `__SLANG__` to identify the compiler, so you might want to do that manually, if you need to have files that are processed by Slang and other tools.\n\n```c++\nspAddPreprocessorDefine(request, \"__SLANG__\", \"1\")\n```\n\n### Specify Input Code and Entry Points\n\nOnce you've made your global configuration of the compile request, it is time to start adding source code.\nThe Slang model is that a compile request involves one or more *translation units*, each of which may comprise one or more *source files* (or strings), and which might define one or more *entry points*.\n\nIn the case of HLSL or GLSL code, each translation unit will usually have only a single source file or string.\nIn the case of GLSL, a translation unit will only expose a single entry point.\n\n#### Translation Units\n\nTo add a translation unit to the compile request:\n\n```c++\nint translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_HLSL, \"\");\n```\n\nThe first argument is the compile request.\nThe second argument is the source language for the translation unit (you may not have a single translation unit that mixes source files in different languages).\nThe last argument is an optional name for the translation unit; Slang currently doesn't do anything with this value.\n\nThe `spAddTranslationUnit` function returns the zero-based index of the translation unit you added.\nYou don't need to use this return value, because it will be deterministic (the first translation unit gets `0`, the next gets `1`, etc.), but the API returns it in case it saves you from having to track it with your own counter.\nThe translation unit index is used in subsequent API calls that modify or query the translation unit.\n\n#### Source Files/Strings\n\nOnce you've created a translation unit, you can add source code to it.\nSource code can either come from a file or a string:\n\n```c++\nspAddTranslationUnitSourceFile(request, translationUnitIndex, \"some/file.hlsl\");\n\n// or:\n\nspAddTranslationUnitSourceString(\n    request,\n    translationUnitIndex,\n    \"file.hlsl\",\n    \"/* source code */ ...\");\n```\n\nNote that even in the case where you provide a string, you need to provide a file name (even a made-up one) so that Slang can use it in error messages.\n\n#### Entry Points\n\nOnce you've added source code to your translation unit, you can specify which entry point(s) you want to compile in the translation unit:\n\n```c++\nint entryPointIndex = spAddEntryPoint(\n    request,\n    translationUnitIndex,\n    \"main\",\n    profileID);\n```\n\nThis adds an entry point to be compiled to the compilation `request`.\nAn entry point named `\"main\"` will be looked up in translation unit `translationUnitIndex` and code will be generated based on the given `profileID` (a value of type `SlangProfileID`).\n\nIn order to get a profile to use, you'll typically want to look one up by name:\n\n```c++\nSlangProfileID profileID = spFindProfile(session, \"ps_5_0\");\n```\n\nThe names of profiles passed to this function are the same as are available for command-line [`slangc`](command-line-slangc.md).\n\nLike `spAddTranslationUnit`, `spAddEntryPoint` returns a zero-based index for the entry point.\nNote that this index is for all entry points in the compile request (not per-translation-unit).\n\n### Compiling and Checking Diagnostics\n\nWith all the setup out of the way, it is finally time to actually compile things:\n\n```c++\nint anyErrors = spCompile(request);\n```\n\nThe `spCompile` function will compile all the translation units and entry points you specified.\nIf any errors were encountered during compilation, then `spCompile` will return a non-zero result.\nTo find out what went wrong, you can get a null-terminated log of error messages with:\n\n```c++\nchar const* diagnostics = spGetDiagnosticOutput(request);\n```\n\nThe diagnostic output will also contain any warnings produced, even if the compilation didn't have any errors.\nNote that the returned pointer is guaranteed to live at least as long as the compile request, but no longer.\nIf you need to retain the data for later use, then you must make your own copy.\n\nIf any errors occurred, you shouldn't expect to read any useful output (other than the diagnostics) from the request; you should destroy it and move on.\n\n### Reading Output Code\n\nIf you compilation was successful, then you probably want to extract the output code that was generated.\nSlang provides access to the generated code for each entry point:\n\n```c++\nsize_t dataSize = 0;\nvoid const* data = spGetEntryPointCode(request, entryPointIndex, &dataSize);\n```\n\nAs a shorthand, if you expect the output to be textual source-code:\n\n```c++\nchar const* code = spGetEntryPointSource(request, entryPointIndex);\n```\n\nNote that the pointer returned by these functions is guaranteed to remain live as long as the compileRequest is alive, but no longer.\nIf you need to retain the output code for longer, you need to make a copy.\n\n### Reflection Information\n\nIf a compilation is successful, Slang also produces reflection information that the application can query:\n\n```c++\nSlangReflection* reflection = spGetReflection(request);\n```\n\nNote that just as with output code, the reflection object (and all other objects queried from it) is guaranteed to live as long as the request is alive, but no longer.\nUnlike the other data, there is no easy way to save the reflection data for later user (we do not currently implement serialization for reflection data).\nApplications are encouraged to extract whatever information they need before destroying the compilation request.\n\nFor convenience (since the reflection API surface area is large), the Slang API provides a C++ wrapper interface around the reflection API, and this document will show code examples using those wrappers:\n\n```c++\nslang::ShaderReflection* shaderReflection = slang::ShaderReflection::get(request);\n```\n\n#### Program Reflection\n\nWhen looking at the whole program (`slang::ShaderReflection`) we can enumerate global-scope shader parameters:\n\n```c++\nunsigned parameterCount = shaderReflection->getParameterCount();\nfor(unsigned pp = 0; pp < parameterCount; pp++)\n{\n\tslang::VariableLayoutReflection* parameter =\n\t    shaderReflection->getParameterByIndex(pp);\n\t// ...\n}\n```\n\nWe can also enumerate the compile entry points, in order to inspect their parameters:\n\n```c++\nSlangUInt entryPointCount = shaderRefelction->getEntryPointCount();\nfor(SlangUInt ee = 0; ee < entryPointCount; ee++)\n{\n\tslang::EntryPointReflection* entryPoint =\n\t    shaderReflection->getEntryPointByIndex(ee);\n\t// ...\n}\n```\n\nSlang's reflection API does not currently expose by-name lookup of parameters, but this is obviously a desirable feature.\n\n#### Variable Layouts\n\nIn the Slang reflection API, we draw a distinction between a *variable* (a particular declaration in the code), from a *variable layout* which has been laid out according to some API-specific rules.\nIt is possible for the same variable (e.g., a `struct` field) to be laid out multiple times, with different results (e.g., if the same `struct` type is used both for a `cbuffer` member and a varying shader `in` parameter).\n\nFor most purposes, a `VariableLayoutReflection` represents what a shading language user thinks of as a \"shader parameter.\"\nWe can query a parameter for its name:\n\n```c++\nchar const* parameterName = parameter->getName();\n```\n\nAn application will typically want to know where a parameter got \"bound.\"\nIn the simple case, we can query this information directly:\n\n```c++\nslang::ParameterCategory category = parameter->getCategory();\nunsigned index = parameter->getBindingIndex();\nunsigned space = parameter->getBindingSpace();\n```\n\nFor a simple global-scope \"resource\" parameter (e.g., HLSL `Texture2D t : register(t3)`) the `category` tells what kind of resource the parameter consumes (e.g., `slang::ParameterCategory::ShaderResource`), the `index` gives the register number (`3`), and `space` gives the register \"space\" (`0`) as added for D3D12.\n\nIn the case of SPIR-V output a binding index corresponds to the `binding` layout qualifier, and the binding space corresponds to the `set`.\nThe main difference from D3D is that the `category` will usually be `slang::ParameterCategory::DescriptorTableSlot`.\n\nTextures, samplers, and constant buffers all follow this same basic pattern.\nFor uniform parameters (e.g., members of an HLSL `cbuffer`), the binding \"space\" is unused, the category is `slang::ParameterCategory::Uniform`, and the \"index\" is the byte offset of the parameter in its parent.\n\nThe above are the simple cases, where a parameter only consumes a single kind of resource.\nIn HLSL, however, we can do things like combine textures, samplers, and uniform values in a `struct` type, so given a parameter of such a type, the reflection API needs to be able to report appropriate layout information for each of the different categories of resource.\n\nIf `getCategory()` returns `slang::ParameterCategory::Mixed`, then the user can query additional information:\n\n```c++\nunsigned categoryCount = parameter->getCategoryCount();\nfor(unsigned cc = 0; cc < categoryCount; cc++)\n{\n\tslang::ParameterCategory category = parameter->getCategoryByIndex(cc);\n\n\tsize_t offsetForCategory = parameter->getOffset(category);\n\tsize_t spaceForCategory = parameter->getBindingSpace(category);\n\n\t// ...\n}\n```\n\nA loop like this lets you enumerate all of the resource types consumed by a parameter, and get a starting offset (and space) for each category.\n\n#### Type Layouts\n\nJust knowing where a shader parameter *starts* is only part of the story, of course.\nWe also need to know how many resources (e.g., registers, bytes of uniform data, ...) it consumes, how many elements it occupies (if it is an array), and what \"sub-parameters\" it might include.\n\nFor these kinds of queries, we need to look at the *type layout* of a parameter:\n\n```c++\nslang::TypeLayoutReflection* typeLayout = parameter->getTypeLayout();\n```\n\nJust as with the distinction between a variable and a variable layout, a type layout represents a particular type in the source code that has been laid out according to API-specific rules.\nA single type like `float[10]` might be laid out differently in different contexts (e.g., using GLSL `std140` vs. `std430` rules).\n\nThe first thing we want to know about a type is its *kind*:\n\n```c++\nslang::TypeReflection::Kind kind = typeLayout->getKind();\n```\n\nThe available cases for `slang::TypeReflection::Kind` include `Scalar`, `Vector`, `Array`, `Struct`, etc.\n\nFor any type layout, you can query the resources it consumes, or a particular parameter category:\n\n```c++\n// query the number of bytes of constant-buffer storage used by a type layout\nsize_t sizeInBytes = typeLayout->getSize(slang::ParameterCategory::Uniform);\n\n// query the number of HLSL `t` registers used by a type layout\nsize_t tRegCount = typeLayout->getSize(slang::ParameterCategory::ShaderResource);\n```\n\n##### Arrays\n\nIf you have a type layout with kind `Array` you can query information about the number and type of elements:\n\n```c++\nsize_t arrayElementCount = typeLayout->getElementCount();\nslang::TypeLayoutReflection* elementTypeLayout = typeLayout->getElementTypeLayout();\nsie_t arrayElementStride = typeLayout->getElementStride(category);\n```\n\nAn array of unknown size will currently report zero elements.\nThe \"stride\" of an array is the amount of resources (e.g., the number of bytes of uniform data) that need to be skipped between consecutive array elements.\nThis need *not* be the same as `elementTypeLayout->getSize(category)`, and there are two notable cases to be aware of:\n\n- An array in a constant buffer may have a stride larger than the element size. E.g., a `float a[10]` in a D3D or `std140` constant buffer will have 4-byte elements, but a stride of 16.\n\n- An array of resources in Vulkan will have a stride of *zero* descriptor-table slots, because the entire array is allocated a single `binding`.\n\n##### Structures\n\nIf you have a type layout with kind `Struct`, you can query information about the fields:\n\n```c++\nunsigned fieldCount = typeLayout->getFieldCount();\nfor(unsigned ff = 0; ff < fieldCount; ff++)\n{\n\tVariableLayoutReflection* field = typeLayout->getFieldByIndex(ff);\n\t// ...\n}\n```\n\nEach field is represented as a full variable layout, so application code can recursively extract full information.\n\nAn important caveat to be aware of when recursing into structure types like this, is that the layout information on a field is relative to the start of the parent type layout, and not absolute.\nThis is perhaps not surprising in the case of `slang::ParameterCategory::Uniform`: if you ask a field in a `struct` type for its byte offset, it will return the offset from the start of the `struct`.\n\nWhere this can trip up users is when a `struct` type contains fields of other categories (e.g., a structure with a `Texture2D` in it).\nIn these cases, the \"binding index\" of a structure field in a relative offset from whatever binding index is given to the parent structure.\n\nThe basic rule is that no matter what category of binding resource (bytes, registers, etc.) you are talking about, the index/offset of `a.b.c` must be computed by adding together the offsets of `a`, `b` and `c`.\n\n#### Entry Points\n\nGiven an `EntryPointReflection` we can query its name and stage:\n\n```c++\nchar const* entryPointName = entryPoint->getName();\nSlangStage stage = entryPoint->getStage();\n```\n\nYou can also enumerate the parameters of the entry point (that is, those that were written as parameters of the entry-point function):\n\n```c++\nunsigned parameterCount = entryPoint->getParameterCount();\nfor(unsigned pp = 0; pp < parameterCount; pp++)\n{\n\tslang::VariableLayoutReflection* parameter =\n\t    entryPoint->getParameterByIndex(pp);\n\t// ...\n}\n```\n\nIn the case of a compute shader entry point, you can also query the user-specified thread-group size (if any):\n\n```c++\nSlangUInt threadGroupSize[3];\nentryPoint->getComputeThreadGruopSize(3, &threadGroupSize[0]);\n```\n\n### Checking Dependencies\n\nIf you are implementing some kind of \"hot reload\" system for shaders, then you probably need to know what files on disk a particular compilation request ended up depending on.\nSlang provides a simple API for enumerating these, on a successful compile:\n\n```c++\nint depCount = spGetDependencyFileCount(request);\nfor(int dep = 0; dep < depCount; dep++)\n{\n\tchar const* depPath = spGetDependencyFilePath(request, dep);\n\t// ...\n}\n```\n\nThis will enumerate all file paths that were referenced by the compile, either directly through the API or via a `#include` directive.\n\n### Setting Other Options\n\nThere are other compilation options that are more specialized, and less often used.\n\nIf HLSL or GLSL input code uses constructs that Slang doesn't understand (that is, it is giving spurious error messages) it may be possible to make progress by suppressing Slang's semantic checking for these languages:\n\n```c++\nspSetCompileFlags(request, SLANG_COMPILE_FLAG_NO_CHECKING);\n```\n\nIf you are trying to debug shader compilation issues in a large application, it may be helpful to have Slang dump all the intermediate code it generates to disk:\n\n```c++\nspSetDumpIntermediates(request, true);\n```\n\nIf you don't like the way that Slang adds `#line` directives to generated source code, you can control this behavior:\n\n```c++\nspSetLineDirectiveMode(request, SLANG_LINE_DIRECTIVE_MODE_NONE);\n```\n\n### <a id=\"multithreading\"/>Multithreading\n\nThe only functions which are currently thread safe are \n\n```C++\nSlangSession* spCreateSession(const char* deprecated);\nSlangResult slang_createGlobalSession(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession);\nSlangResult slang_createGlobalSessionWithoutStdLib(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession);\nISlangBlob* slang_getEmbeddedStdLib();\nSlangResult slang::createGlobalSession(slang::IGlobalSession** outGlobalSession);\nconst char* spGetBuildTagString();\n```\n\nThis assumes Slang has been built with the C++ multithreaded runtime, as is the default.\n\nAll other functions and methods are not [reentrant](https://en.wikipedia.org/wiki/Reentrancy_(computing)) and can only execute on a single thread. More precisely function and methods can only be called on a *single* thread at *any one time*. This means for example a global session can be used across multiple threads, as long as some synchronisation enforces that only one thread can be in a Slang call at any one time.\n\nMuch of the Slang API is available through [COM interfaces](https://en.wikipedia.org/wiki/Component_Object_Model). In strict COM interfaces should be atomically reference counted. Currently *MOST* Slang API COM interfaces are *NOT* atomic reference counted. One exception is the `ISlangSharedLibrary` interface when produced from [host-callable](cpu-target.md#host-callable). It is atomically reference counted, allowing it to persist and be used beyond the original compilation and be freed on a different thread. \n\nA Slang compile request/s (`slang::ICompileRequest` or `SlangCompileRequest`) can be thought of belonging to the Slang global session (`slang::IGlobalSession` or `SlangSession`) it was created from.  Note that *creating* a global session is currently a fairly costly process, whereas the cost of creating and destroying a request is relatively small. \n\nThe *simplest* way to multithread would be for a thread to \n\n* Create a global session\n* Create request/s from that session \n* Compile\n* Destroy request/s\n* Destroy the global session \n\nThis works, but typically isn't very efficient with multiple compilations because of the cost of creating the global session each time. \n\nA significant improvement is to limit the global session cost via a pool. \n\n* Get a global session from a global session pool \n* *Optionally* set any state on the global session\n* Create request/s from the global session \n* Compile\n* Destroy request/s\n* Return the global session to the global session pool\n\nCare is needed with the pool because the global session holds state, so it is either important to have a condition that all global sessions hold the same state, or all state is setup on the session when it's removed from the pool for use. Global sessions use a significant amount of memory, so an implementation may want to limit how many global sessions are available and their lifetimes.\n\nMore nuance is possible in so far as the use of global session/requests *can* move between threads as long as use is only ever on one thread at any one time. Another style of implementation could use a thread pool, and associate global sessions with threads in the pool for example.\n\nSlang can hold references to user implemented functions and interfaces such as `ISlangFileSystem` and `SlangDiagnosticCallback`. If Slang is used in a multithreaded manner such implementations typically must also be thread safe.\n"
  },
  {
    "path": "Source/External/slang/docs/building.md",
    "content": "# Building Slang From Source\n\n## Get the Source Code \n\nClone [this](https://github.com/shader-slang/slang) repository, and then run:\n\n```\n% git submodule update --init\n```\n\nThe submodule update step is required to pull in dependencies used for testing infrastructure as well as the `glslang` compiler that we currently use for generating SPIR-V. \n\n## Windows Using Visual Studio\n\nIf you are using Visual Studio on Windows, then you can just open `slang.sln` and build your desired platform/configuration. `slang.sln` and associated project files are actually just generated using [`premake5`](https://premake.github.io/). See instructions in premake section below for further explanation.\n \nWhilst using the provided `slang.sln` solution is a fast and easy way to get a build to work, it does not make all binary dependencies available which can add features and improve performance (such as [slang-llvm](https://github.com/shader-slang/slang-llvm)). To get the binary dependencies create the solution using [`premake5`](https://premake.github.io/) described in a later section.\n \n## Other Targets\n\nSlang uses [`premake5`](https://premake.github.io/) to generate projects (such as `Makefile`s) that can then be used to build Slang binaries from source. \n\nFor Linux and other targets the section below on `premake` describes the process. \n\nSome targets below are described as 'unofficial'. In practice this means that they are not tested as part of contiguous integration. Thus unfortunately it is quite possible from time to time for them to break on a merge of a PR. That said, if broken it is likely only very minor changes are needed to make them work again. \n\n### Generated Files\n\nSlang as part of it's build process generates header files, which are then used to compile the main Slang project. If you use `premake` to create your project, it will automatically generate these files before compiling the rest of the Slang. These are the current header generations which are created via the `slang-generate` and other tools... \n\n* core.meta.slang -> core.meta.slang.h\n* hlsl.meta.slang -> hlsl.meta.slang.h \n\nOther files that are generated have `generated` as part of their name.\n\nIt may be necessary or desirable to create a build of Slang without using `premake`. \n\nOne way to do this would be to first compile slang-generate and then invoke it directly or as a dependency in your build. Another perhaps simpler way would be to first compile the same Slang source on another system that does support `premake`, or using a preexisting build mechanism (such as Visual Studio projects on Windows). Then copy the generated header files to your target system. This is appropriate because the generated files are indentical across platforms. It does of course mean that if `core.meta.slang` or `hlsl.meta.slang` files change the headers will need to be regenerated. \n\n## Premake\n\nSlang uses the tool [`premake5`](https://premake.github.io/) in order to generate projects that can be built on different targets. On Linux premake will generate Makefile/s and on windows it will generate a Visual Studio solution. Information on invoking premake for different kinds of targets can be found [here](https://github.com/premake/premake-core/wiki/Using-Premake). \n\nSlang includes `premake5` as part of `slang-binaries` which is in the `external` directory. For the external directory to be setup it is necessary to have updated submodules with `git submodule update --init`. \n\nIf you are on a unix-like operating system such as OSX/Linux, it may be necesary to make premake5 executable. Use \n\n```\n% chmod u+x external/slang-binaries/premake/***path to premake version and os***/premake5\n```\n\nAlternatively you can download and install [`premake5`](https://premake.github.io/) on your build system. \n\nRun `premake5` with `--help` to in the root of the Slang project to see available command line options (assuming `premake5` is in your `PATH`):\n \n```\n% premake5 --help\n```\n\nTo download and use binaries for a particular architecture the [slang-pack](https://github.com/shader-slang/slang-binaries/tree/master/lua-modules) package manager can be invoked via the additional `--deps` and `--arch` options. If `--arch` isn't specified it defaults to `x64`. On Windows targets, the Visual Studio platform setting should be consistent with the `--arch` option such that the appropriate binary dependencies are available. The `--deps=true` option just indicates that on invoking premake it should make the binary dependencies for the `arch` available. \n\nSupported `--arch` options are\n\n* x64\n* x86\n* aarch64\n* arm\n\nFor Unix like targets that might have `clang` or `gcc` compilers available you can select which one via the `-cc` option. For example...\n\n```\n% premake5 gmake --cc=clang --deps=true --arch=x64\n```\n\nor \n\n```\n% premake5 gmake --cc=gcc --deps=true --arch=x64\n```\n\nIf you want to build the [`glslang`](https://github.com/KhronosGroup/glslang) library that Slang uses, add the option `--build-glslang=true`.\n\n# Projects using `make`\n\nThe Slang project does not include Makefiles by default - they need to be generated via `premake`. Please read the section on your target operating system on how to use `premake` to create Makefiles. \n\nIf building a Makefile based project, for example on Linux, OSX or [Cygwin](https://cygwin.com/), the configuration needs to be specified when invoking make, the following are typical...\n\n```\n% make config=release_x64\n% make config=debug_x64\n% make config=release_x86\n% make config=debug_x86\n% make config=release_aarch64\n% make config=debug_aarch64\n```\n\nTo check what compiler is being used/command line options you can add `verbose=1` to `make` command line. For example\n\n```\n% make config=debug_x64 verbose=1\n```\n\n### Windows\n\nFirst download and install [`premake5`](https://premake.github.io/) on your build system. Open up a command line and go to the root directory of the slang source tree (ie the directory containing `slang.h`).\n \nAssuming premake5 is in your `PATH`, you can create a Visual Studio 2017 project for Slang with the following command line\n\n```\n% premake5 vs2017 --deps=true --arch=x64\n```\n\nFor Visual Studio 2019 use\n\n```\n% premake5 vs2019 --deps=true --arch=x64\n```\n\nThese should create a slang.sln in the same directory and which you can then open in the appropriate Visual Studio. Building will build all of Slang, examples and it's test infrastructure.\n\n### Linux \n\nOn Linux we need to generate Makefiles using `premake`. Please read the `premake` section for more details. \n\nIn the terminal go to the root directory of the slang source tree (ie the directory containing `slang.h`). Assuming `premake5` is in your `PATH` use  \n\n```\n% premake5 gmake --deps=true --arch=x64\n```\n\nTo create a release build use\n\n```\n% make config=release_x64\n```\n \nYou can vary the compiler to use via the --cc option with 'gcc' or 'clang' for example\n\n### Mac OSX\n\nNote that OSX isn't an official target. \n\nOn Mac OSX to generate Makefiles or an XCode project we use `premake`. Please read the `premake` section for more details. \n\n```\n% premake5 gmake --deps=true --arch=x64\n```\n\nIf you want to build `glslang` (necessary for Slang to output SPIR-V for example), then the additional `--build-glslang` option should be used\n\n```\n% premake5 gmake --build-glslang=true --deps=true --arch=x64\n```\n\nTo build for release you can use...\n\n```\n% make config=release_x64\n```\n\nSlang can also be built within the Xcode IDE. Invoke `premake` as follows\n\n```\n% premake5 xcode4 --deps=true --arch=x64\n```\n\nThen open the `slang.xcworkspace` project inside of Xcode and build. \n\n### Cygwin\n\nNote that Cygwin isn't an official target. \n\nOne issue with building on [Cygwin](https://cygwin.com/), is that there isn't a binary version of `premake` currently available. It may be possible to make this work by building `premake` from source, and then just doing `premake5 gmake`. Here we use another approach - using the windows `premake` to create a Cygwin project. To do this use the command line...\n\n```\n% premake5 --target-detail=cygwin gmake --deps=true --arch=x64\n```\n\n## Testing\n\nWhen slang is built from source it also builds tools to be able to test the Slang compiler. Testing is achieved using the `slang-test` tool. The binaries are placed in the appropriate directory underneath `bin`. It is important that you initiate the test binary from the root directory of the slang source tree, such that all tests can be correctly located.\n\nFor example to run the tests on a windows release x64 build from the command line, in the root directory of slang source tree you can use...\n\n```\n% bin\\windows-x64\\release\\slang-test\n```\n\nNote that on windows if you want to run all of the tests from inside visual studio, it is necessary to set the `Working Directory` under \"slang-test project\" > \"Configuration Properties\" > \"Debugging\" > \"Working Directory\" to the root directory of the slang source tree. You can do this by setting it to `$(ProjectDir)/../..` for all configurations.\n\nIf you only see 'unit-tests' being run (unit tests are prefixed with 'unit-tests/') then the working directory is not correctly set. Most tests are text files describing the test held in the `tests` directory in the root of the slang project. \n\nSee the [documentation on testing](../tools/slang-test/README.md) for more information.\n \n"
  },
  {
    "path": "Source/External/slang/docs/command-line-slangc.md",
    "content": "Using the `slangc` Command-Line Compiler\n========================================\n\nThe `slangc` command-line tool is used to compile or cross-compile shader source code.\n\n```\nslangc [<options>] <file1> [<file2>...]\n\n```\n\nSimple Examples\n---------------\n\n### HLSL\n\nWhen compiling an HLSL shader, you must specify the path to your shader code file as well as the target shader model (profile) and shader stage to use.\nFor example, to see D3D bytecode assembly for a fragment shader entry point:\n\n    slangc my-shader.hlsl -profile sm_5_0 -stage fragment\n\nTo direct that output to a bytecode file:\n\n    slangc my-shader.hlsl -profile sm_5_0 -stage fragment -o my-shader.dxbc\n\nIf the entry-point function has a name other than the default `main`, then this is specified with `-entry`:\n\n    slangc my-shader.hlsl -profile sm_5_0 -entry psMain -stage fragment \n\nIf you are using the `[shader(\"...\")]` syntax to mark your entry points, then you may leave off the `-stage` option:\n\n    slangc my-shader.hlsl -profile sm_5_0 -entry psMain\n\n### Slang\n\nCompiling an entry point from a Slang file is similar to HLSL, except that you must also specify a desired code generation target, because there is no assumed default (like DXBC for Direct3D Shader Model 5.x).\n\nTo get DXBC assembly written to the console:\n\n    slangc my-shader.slang -profile sm_5_0 -stage fragment -entry main -target dxbc\n\nTo get SPIR-V assembly:\n\n    slangc my-shader.slang -profile sm_5_0 -stage fragment -entry main -target spriv\n\nThe code generation target is implicit when writing to a file with an appropriate extension.\nTo write DXBC, SPIR-V, or GLSL to files, use:\n\n    slangc my-shader.slang -profile sm_5_0 -entry main -stage fragment -o my-shader.dxbc\n    slangc my-shader.slang -profile sm_6_0 -entry main -stage fragment -o my-shader.dxil\n    slangc my-shader.slang -profile glsl_450 -entry main -stage fragment -o my-shader.spv\n\nMultiple Entry Points\n---------------------\n\n`slangc` can compile multiple entry points, which may span multiple files in a single invocation.\nThis is useful when you are taking advantage of Slang's ability to automatically assign binding locations to shader parameters, because the compiler can take all of your entry points into account when assigning location (avoiding overlap between entry points that will be used together).\n\nWhen specifying multiple entry points, you use multiple `-entry` options on the command line.\nThe main thing to be aware of is that any `-stage` options apply to the most recent `-entry` point, and the same goes for any `-o` options to specify per-entry-point output files.\nFor example, here is a command line to compile both vertex and fragment shader entry points from a single file and output them to distinct DXBC files:\n\n    slangc -profile sm_5_0 my-shader.hlsl \n                          -entry vsMain -stage vertex   -o my-shader.vs.dxbc\n                          -entry fsMain -stage fragment -o my-shader.fs.dxbc\n\nIf your shader entry points are spread across multiple HLSL files, then each `-entry` option indicates an entry point in the preceding file.\nFor example, if the preceding example put its vertex and fragment entry points in distinct files, the command line would be:\n\n    slangc -profile sm_5_0 my-shader.vs.hlsl -entry vsMain -stage vertex   -o my-shader.vs.dxbc\n                           my-shader.fs.hlsl -entry fsMain -stage fragment -o my-shader.fs.dxbc\n\nNote that when compiling multiple `.slang` files in one invocation, they will all be compiled together as a single module (with a single global namespace) so that the relative order of `-entry` options and source files does not matter.\n\nThese long command lines obviously aren't pleasant.\nWe encourage applications that require complex shader compilation workflows to use the Slang API directly so that they can implement compilation that follows application conventions/policy.\nThe ability to specify compilation actions like this on the command line is primarily intended a testing and debugging tool.\n\nOptions\n-------\n\nFor completeness, here are the options that `slangc` currently accepts:\n\n* `-v`: Displays the build version. This is the contents of `git describe --tags`. It is typically only set from automated builds (such as distros available on github). A user build will by default be 'unknown'. \n\n* `-D <name>[=<value>]`: Insert a preprocessor macro definition\n  * The space between `-D` and `<name>` is optional\n  * If no `<value>` is specified, Slang will define the macro with an empty value\n\n* `-I <path>`: Add a path to be used in resolving `#include` and `import` operations\n  * The space between `-I` and `<path>` is optional\n\n* `-entry <name>`: Specify the name of the entry-point function\n  * When compiling from a single file, this defaults to `main` *if* you specify a stage using `-stage`\n  * Multiple `-entry` options may appear on the command line. When they do, the file associated with the entry point will be the first one found when searching to the left in the command line.\n\n* `-stage <name>`: Specify the stage of an entry-point function\n  * When there are multiple entry points, a `-stage` option applies to the most recent `-entry` point specified\n  * When there is only a single entry point, the `-stage` option may appear anywhere on the command line\n  * The traditional stages are named as follows:\n    * `vertex`\n    * `hull`: D3D Hull Shader and GL/VK Tessellation Control Shader\n    * `domain`: D3D Domain Shader and GL/VK Tessellation Evaluation Shader\n    * `geometry`\n    * `fragment` / `pixel`: D3D Pixel Shader and GL/VK Fragment Shader\n    * `compute`\n  * The stages for ray tracing use the following names:\n    * `raygeneration`\n    * `intersection`\n    * `anyhit`\n    * `closesthit`\n    * `miss`\n    * `callable`\n\n* `-target <format>`: Specifies the format in which code should be generated. Values for `<target>` are:\n  * `glsl`: GLSL source code\n  * `hlsl`: HLSL source code\n  * `spirv`: SPIR-V intermediate language binary.\n  * `spirv-assembly` / `spirv-asm`: SPIR-V intermediate language assembly\n  * `dxbc`: DirectX shader bytecode binary\n  * `dxbc-assembly` / `dxbc-asm`: DirectX shader bytecode assembly\n  * `dxil`: DirectX Intermediate Language binary\n  * `dxil-assembly` / `dxil-asm`: DirectX Intermediate Language assembly\n\n* `-profile <profile>`: Specify the \"profile\" to use for the code generation target, which represents an abstact feature level as defined by a particular API standard. Available values include:\n  * The Direct3D \"Shader Model\" levels are available as `sm_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6}`\n  * Profiles corresponding to GLSL langauge versions are available as `glsl_{110,120,130,140,150,330,400,410,420,430,440,450,460}`\n  * As a convenience, names matching traditional HLSL shader profiles are provided such that, e.g., `-profile vs_5_0` is an abbreviation for `-profile sm_5_0 -stage vertex`\n\n* `-o <path>`: Specify a path where generated output should be written\n  * When multiple `-entry` options are present, each `-o` associates with the first `-entry` to its left.\n\n* `-pass-through <name>`: Don't actually perform Slang parsing/checking/etc. on the input and instead pass it through (more or less) unmodified to the existing compiler `<name>`\n  * `fxc`: Use the `D3DCompile` API as exposed by `d3dcompiler_47.dll`\n  * `glslang`: Use Slang's internal version of `glslang` as exposed by `slang-glslang.dll`\n  * `dxc`: Use DirectXShaderCompiler (https://github.com/Microsoft/DirectXShaderCompiler)\n  * These are intended for debugging/testing purposes, when you want to be able to see what these existing compilers do with the \"same\" input and options\n\n* `-verbose-paths`: When displaying diagnostic output aim to display more detailed path information. In practice this is typically the complete 'canonical' path to the source file used.\n\n* `-g`: Include debug information in the generated code, where possible. Currently only supported for DXBC and DXIL output (not SPIR-V).\n\n* `-O`: Control optimization levels. This currently only affects DXBC and DXIL generation.\n  * `-O0`: Disable all optimizations\n  * `-O1`, `-O`: Enable a default level of optimization. This is the default if no `-O` options are used.\n  * `-O2`: Enable aggressive optimizations for speed.\n  * `-O3`: Enable further optimizations, which might have a significant impact on compile time, or involve unwanted tradeoffs in terms of code size.\n\n* `--`: Stop parsing options, and treat the rest of the command line as input paths\n\n* `-output-includes`: After pre-processing has been performed will output to via the diagnostics the hierarchy of paths to source files reached \n\n* -Xname to specify arguments to downstream tool `name` (covered in more detail in \"Downstream Arguments\")\n\n<a id=\"downstream-arguments\"></a>\n### Downstream Arguments\n\nDuring a Slang compilation work may be performed by multiple other stages including downstream compilers and linkers. It isn't possible in general or perhaps even desirable to provide Slang command line equivalents of every option available at every stage of compilation. It is useful to be able to set options specific to a particular compilation stage - to alter code generation, linkage and other options.\n\nThe mechanism used here is based on the `-X` mechanism used in GCC, to specify arguments to the linker.\n\n```\n-Xlinker option\n```\n\nWhen used, `option` is not interpreted by GCC, but is passed to the linker once compilation is complete. Slang extends this idea in several ways. First there are many more 'downstream' stages available to Slang than just `linker`. These different stages are known as `SlangPassThrough` types in the API and have the following names\n\n* `fxc` - FXC HLSL compiler\n* `dxc` - DXC HLSL compiler\n* `glslang` - GLSLANG GLSL compiler\n* `visualstudio` - Visual Studio C/C++ compiler\n* `clang` - Clang C/C++ compiler\n* `gcc` - GCC C/C++ compiler\n* `genericcpp` - A generic C++ compiler (can be any one of visual studio, clang or gcc depending on system and availability)\n* `nvrtc` - NVRTC CUDA compiler\n\nThe Slang command line allows you to specify an argument to these downstream compilers, by using their name after the `-X`. So for example to send an option `-Gfa` through to DXC you can use \n\n```\n-Xdxc -Gfa\n```\n\nNote that if an option is available via normal Slang command line options then these should be used. This will generally work across multiple targets, but also avoids options clashing which is undefined behavior currently. The `-X` mechanism is best used for options that are unavailable through normal Slang mechanisms. \n\nIf you want to pass multiple options using this mechanism the `-Xdxc` needs to be in front of every options. For example \n\n```\n-Xdxc -Gfa -Xdxc -Vd\n```\n\nWould reach `dxc` as \n\n```\n-Gfa -Vd\n```\n\nThis can get a little repetitive especially if there are many parameters, so Slang adds a mechanism to have multiple options passed by using an ellipsis `...`. The syntax is as follows\n\n```\n-Xdxc... -Gfa -Vd -X.\n```\n\nThe `...` at the end indicates all the following parameters should be sent to `dxc` until it reaches the matching terminating `-X.` or the end of the command line. \n\nIt is also worth noting that `-X...` options can be nested. This would allow a GCC downstream compilation to control linking, for example with\n\n```\n-Xgcc -Xlinker --split -X.\n```\n\nIn this example gcc would see\n\n```\n-Xlinker --split\n```\n\nAnd the linker would see (as passed through by gcc) \n\n```\n--split\n```\n\nSetting options for tools that aren't used in a Slang compilation has no effect. This allows for setting `-X` options specific for all downstream tools on a command line, and they are only used as part of a compilation that needs them.\n\nNOTE! Not all tools that Slang uses downstream make command line argument parsing available. `FXC` and `GLSLANG` currently do not have any command line argument passing as part of their integration, although this could change in the future.\n\nThe `-X` mechanism is also supported by render-test tool. In this usage `slang` becomes a downstream tool. Thus you can use the `dxc` option `-Gfa` in a render-test via \n\n```\n-Xslang... -Xdxc -Gfa -X.\n```\n\nMeans that the dxc compilation in the render test (assuming dxc is invoked) will receive \n\n```\n-Gfa\n```\n\nSome options are made available via the same mechanism for all downstream compilers. \n\n* Use `-I` to specify include path for downstream compilers\n\nFor example to specify an include path \"somePath\" to DXC you can use...\n\n```\n-Xdxc -IsomePath\n```\n\n### Specifying where dlls/shared libraries are loaded from\n\nOn windows if you want a dll loaded from a specific path, the path must be specified absolutely. See the [LoadLibrary documentation](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya) for more details. A relative path will cause Windows to check all locations along it's search procedure.\n\nOn linux it's similar, but any path (relative or not) will override the regular search mechanism. See [dlopen](https://man7.org/linux/man-pages/man3/dlopen.3.html) for more details. \n\n* `-dxc-path`: Sets the path where dxc dll/shared libraries are loaded from (dxcompiler & dxil).\n\n* `-fxc-path`: Sets the path where fxc dll is loaded from (d3dcompiler_47.dll). \n\n* `-glslang-path`: Sets where the Slang specific 'slang-glslang' is loaded from\n\nPaths can specify a directory that holds the appropriate binaries. It can also be used to name a specific downstream binary - be it a shared library or an executable. Note that if it is a shared library, it is not necessary to provide the full filesystem name - just the path and/or name that will be used to load it. For example on windows `fxc` can be loaded from `D:/mydlls` with\n\n* `D:/mydlls` - will look for `d3dcompiler_47.dll` in this directory\n* `D:/mydlls/d3dcompiler_47` - it's not necessary to specify .dll to load a dll on windows\n* `D:/mydlls/d3dcompiler_47.dll` - it is also possible name the shared library explicitly for example\n\nThe name of the shared library/executable can be used to specify a specific version, for example by using `D:/mydlls/dxcompiler-some-version` for a specific version of `dxc`. \n\nLimitations\n-----------\n\nA major limitation of the `slangc` command today is that there is no provision for getting reflection data out along with the compiled shader code.\nFor now, the command-line tool is best seen as a debugging/testing tool, and all serious applications should drive Slang through the API.\n"
  },
  {
    "path": "Source/External/slang/docs/cpu-target.md",
    "content": "Slang CPU Target Support\n========================\n\nSlang has preliminary support for producing CPU source and binaries. \n\n# Features\n\n* Can compile C/C++/Slang source to binaries (executables, shared libraries or [directly executable](#host-callable))\n* Does *not* require a C/C++ be installed if [slang-llvm](#slang-llvm) is available (as distributed with slang binary distributions)\n* Can compile Slang source into C++ source code\n* Supports compute style shaders \n\n# Limitations\n\nThese limitations apply to Slang transpiling to C++. \n\n* Barriers are not supported (making these work would require an ABI change)\n* Atomics are not currently supported\n* Limited support for [out of bounds](#out-of-bounds) accesses handling\n* Entry point/s cannot be named `main` (this is because downstream C++ compiler/s expecting a regular `main`)\n* `float16_t` type is not currently supported\n\nFor current C++ source output, the compiler needs to support partial specialization. \n\n# How it works\n\nThe initial version works by using a 'downstream' C/C++ compiler. A C++ compiler does *not* in general need to be installed on a system to compile and execute code as long as [slang-llvm](#slang-llvm) is available. A [regular C/C++](#regular-cpp) compiler can also be used, allowing access to tooling, such as profiling and debuggers, as well as being able to use regular host development features such as linking, libraries, shared libraries/dlls and executables. \n\nThe C/C++ backend can be directly accessed much like 'dxc', 'fxc' of 'glslang' can, using the pass-through mechanism with the following new backends... \n\n```\nSLANG_PASS_THROUGH_CLANG,                   ///< Clang C/C++ compiler \nSLANG_PASS_THROUGH_VISUAL_STUDIO,           ///< Visual studio C/C++ compiler\nSLANG_PASS_THROUGH_GCC,                     ///< GCC C/C++ compiler\nSLANG_PASS_THROUGH_LLVM,                    ///< slang-llvm 'compiler' - includes LLVM and Clang\nSLANG_PASS_THROUGH_GENERIC_C_CPP,           ///< Generic C or C++ compiler, which is decided by the source type\n```\n\nSometimes it is not important which C/C++ compiler is used, and this can be specified via the 'Generic C/C++' option. This will aim to use the compiler that is most likely binary compatible with the compiler that was used to build the Slang binary being used. \n\nTo make it possible for Slang to produce CPU code, in this first iteration we convert Slang code into C/C++ which can subsequently be compiled into CPU code. If source is desired instead of a binary this can be specified via the SlangCompileTarget. These can be specified on the `slangc` command line as `-target cpp`.\n\nWhen using the 'pass through' mode for a CPU based target it is currently necessary to set an entry point, even though it's basically ignored. \n\nIn the API the `SlangCompileTarget`s are \n\n```\nSLANG_C_SOURCE             ///< The C language\nSLANG_CPP_SOURCE           ///< The C++ language\nSLANG_HOST_CPP_SOURCE,     ///< C++ code for `host` style \n```        \n   \nUsing the `-target` command line option\n\n* C_SOURCE: c\n* CPP_SOURCE: cpp,c++,cxx\n* HOST_CPP_SOURCE: host-cpp,host-c++,host-cxx\n\nNote! Output of C source is not currently supported.\n\nIf a CPU binary is required this can be specified as a `SlangCompileTarget` of \n   \n```   \nSLANG_EXECUTABLE                ///< Executable (for hosting CPU/OS)\nSLANG_SHADER_SHARED_LIBRARY     ///< A shared library/Dll (for hosting CPU/OS)\nSLANG_SHADER_HOST_CALLABLE      ///< A CPU target that makes `compute kernel` compiled code available to be run immediately \nSLANG_HOST_HOST_CALLABLE        ///< A CPU target that makes `scalar` compiled code available to be run immediately\nSLANG_OBJECT_CODE,              ///< Object code that can be used for later linking\n```\n\nUsing the `-target` command line option\n\n* EXECUTABLE: exe, executable\n* SHADER_SHARED_LIBRARY: sharedlib, sharedlibrary, dll\n* SHADER_HOST_CALLABLE: callable, host-callable\n* OBJECT_CODE: object-conde\n* HOST_HOST_CALLABLE: host-host-callable\n    \nUsing `host-callable` types from the the command line, other than to test such code compile and can be loaded for host execution.\n\nFor launching a [shader like](#compile-style) Slang code on the CPU, there typically needs to be binding of values passed the entry point function. How this works is described in the [ABI section](#abi). Functions *can* be executed directly but care must be taken to [export](#visibility) them and such that there isn't an issue with [context threading](#context-threading).\n\nIf a binary target is requested, the binary contents can be returned in a ISlangBlob just like for other targets. When using a [regular C/C++ compiler](#regular-cpp) the CPU binary typically must be saved as a file and then potentially marked for execution by the OS. It may be possible to load shared libraries or dlls from memory - but doing so is a non standard feature, that requires unusual work arounds. If possible it is typically fastest and easiest to use [slang-llvm](#slang-llvm) to directly execute slang or C/C++ code.\n\n## <a id=\"compile-style\"/>Compilation Styles\n\nThere are currently two styles of *compilation style* supported - `host` and `shader`. \n\nThe `shader` style implies \n\n* The code *can* be executed in a GPU-kernel like execution model, launched across multiple threads (as described in the [ABI](#abi)) \n* Currently no reference counting\n* Only functionality from the Slang stdlib, built in HLSL or anything supplied by a [COM interfaces](#com-interface) is available\n* Currently [slang-llvm](#slang-llvm) only supports the `shader` style\n\nThe `host` style implies \n\n* Execution style is akin to more regular CPU scalar code\n* Typically requires linking with `slang-rt` and use of `slang-rt` types such as `Slang::String` \n* Allows use of `new` \n* Allows the use of `class` for reference counted types\n* COM interfaces are reference counted\n\nThe styles as used with [host-callable](#host-callable) are indicated via the API by \n\n```\nSLANG_SHADER_HOST_CALLABLE  ///< A CPU target that makes `compute kernel` compiled code available to be run immediately \nSLANG_HOST_HOST_CALLABLE    ///< A CPU target that makes `scalar` compiled code available to be run immediately\n```\n\nOr via the `-target` command line options\n\n* For 'shader' `callable` `host-callable`\n* For 'host' `host-host-callable`\n\nFor an example of the `host` style please look at \"examples/cpu-hello-world\".\n\n## <a id=\"host-callable\"/>Host callable\n\nSlang supports `host-callable` compilation targets which allow for the direct execution of the compiled code on the CPU. Currently this style of execution is supported if [slang-llvm](#slang-llvm) or a [regular C/C++ compiler](#regular-cpp) are available.\n\nThere are currently two [compilation styles](#compile-style) supported. \n\nIn order to call into `host-callable` code after compilation it's necessary to access the result via the `ISlangSharedLibrary` interface. \n\nPlease look at the [ABI](#abi) section for more specifics around ABI usage especially for `shader` [compile styles](#compile-style).\n\n```C++\n    slang::ICompileRequest* request = ...;\n\n    const SlangResult compileRes = request->compile();\n\n    // Even if there were no errors that forced compilation to fail, the\n    // compiler may have produced \"diagnostic\" output such as warnings.\n    // We will go ahead and print that output here.\n    //\n    if(auto diagnostics = request->getDiagnosticOutput())\n    {\n        printf(\"%s\", diagnostics);\n    }\n\n    // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library\n    // it's just an interface to executable code).\n    ComPtr<ISlangSharedLibrary> sharedLibrary;\n    SLANG_RETURN_ON_FAIL(request->getTargetHostCallable(0, sharedLibrary.writeRef()));\n\n    // We can now find exported functions/variables via findSymbolAddressByName\n\n    // For a __global public __extern_cpp int myGlobal;\n    {    \n        auto myGlobalPtr = (int*)sharedLibrary->findSymbolAddressByName(\"myGlobal\");\n        if (myGlobalPtr)\n        {\n            *myGlobalPtr = 10;\n        }\n    }\n    \n    // To get a function \n    // \n    // public __extern_cpp int add(int a, int b);\n    \n    // Test a free function\n    {\n        typedef int (*AddFunc)(int a, int b); \n        auto func = (AddFunc)sharedLibrary->findFuncByName(\"add\");\n\n        if (func)\n        {\n            // Let's add!\n            int c = func(10, 20):\n        }\n    }\n```\n\n## <a id=\"slang-llvm\"/>slang-llvm\n\n`slang-llvm` is a special Slang version of [LLVM](https://llvm.org/). It's current main purpose is to allow compiling C/C++ such that it is [directly available](#host-callable) for execution using the LLVM JIT feature. If `slang-llvm` is available it is the default downstream compiler for [host-callable](#host-callable). This is because it allows for faster compilation, avoids the file system, and can execute the compiled code directly. [Regular C/C++ compilers](#regular-cpp) can be used for [host-callable](#host-callable) but requires writing source files to the file system and creating/loading shared-libraries/dlls to make the feature work.  Additionally using `slang-llvm` avoids the need for a C/C++ compiler installed on a target system.   \n \n`slang-llvm` contains the Clang C++ compiler, so it is possible to also compile and execute C/C++ code in the [host-callable](#host-callable) style. \n\nLimitations of using `slang-llvm`\n \n* Can only currently be used for [shader style](#compile-style) \n  * Cannot produce object files, libraries, OS executables or binaries \n* Is *limited* because it is not possible to directly access libraries such as the C or C++ standard libraries (see [COM interface](#com-interface) for a work-around)\n* It's not possible to source debug into `slang-llvm` compiled code running on the JIT (see [debugging](#debugging) for a work-around)\n* Not currently possible to return as a ISlangBlob representation \n\nYou can detect if `slang-llvm` is available via\n\n```C++\n    slang::IGlobalSession* slangSession = ...;\n    const bool hasSlangLlvm = SLANG_SUCCEEDED(slangSession->checkPassThroughSupport(SLANG_PASS_THROUGH_LLVM)); \n```\n\n## <a id=\"regular-cpp\"/>Regular C/C++ compilers\n\nSlang can work with regular C/C++ 'downstream' compilers. It has been tested to work with Visual Studio, Clang and G++/Gcc on Windows and Linux.\n\nUnder the covers when Slang is used to generate a binary via a C/C++ compiler, it must do so through the file system. Currently this means the source (say generated by Slang) and the binary (produced by the C/C++ compiler) must all be files. To make this work Slang uses temporary files. The reasoning for hiding this mechanism, other than simplicity, is that it allows using with [slang-llvm](#slang-llvm) without any changes. \n\n## <a id=\"visibility\"/>Visibility\n\nIn a typical Slang [shader like](#compile-style) scenario, functionality is exposed via entry points. It can be convenient and desirable to be able to call Slang functions directly from application code, and not just via entry points. By default non entry point functions are *removed* if they are not reachable by the specified entry point. Additionally for non entry point functions Slang typically generates function names that differ from the original name. \n\nTo work around these two issues the `public` and `__extern_cpp` modifiers can be used.\n\n`public` makes the variable or function visible outside of the module even if it isn't used within the module. For the function to work it will also keep around any function or variable it accesses. \n\nNote! Some care is needed here around [context threading](#context-threading) - if a function or any function a function accesses requires state held in the context, the signature of the function will be altered to include the context as the first parameter.\n\nMaking a function or variable `public` does not mean that the name remains the same. To indicate that the name should not be altered use the `__extern_cpp` modifier. For example\n\n```\n// myGlobal will be visible to the application (note the __global modifier additionally means it has C++ global behavior)\n__global public __extern_cpp int myGlobal;\n\n// myFunc is available to the application\npublic __extern_cpp myFunc(int a) \n{\n    return a * a;\n}\n```\n\n## <a id=\"com-interface\"/>COM interface support\n\nSlang has preliminary support for [Component Object Model (COM)](https://en.wikipedia.org/wiki/Component_Object_Model) interfaces in CPU code. \n\n```\n[COM]\ninterface IDoThings\n{\n    int doThing(int a, int b);\n    int calcHash(NativeString in);\n    void printMessage(NativeString nativeString);\n}\n```\n\nThis support provides a way for an application to provide access to functionality in the application runtime - essentially it allows Slang code to call into application code. To do this a COM interface can be created that exposes the desired functionality. The interface/s can be made available through any of the normal mechanisms - such as through a constant buffer variable. Additionally [`__global`](#actual-global) provides a way to make functions available to Slang code without the need for [context threading](#context-threading).\n\nThe example \"examples/cpu-com-example\" shows this at work.\n\n## <a id=\"actual-global\"/>Global support\n\nThe Slang language is based on the HLSL language. This heritage means that globals have slightly different meaning to typical C/C++ usage. \n\n```\nint myGlobal;                           ///< A constant value stored in a constant buffer\nstatic int staticMyGlobal;              ///< A global that cannot be seen by the application \nstatic const int staticConstMyGlobal;   ///< A fixed value\n``` \n\nThe variable `myGlobal` will be a member of a constant buffer, meaning it's value can only change via bindings and not during execution. For some uses having `myGlobal` in the constant buffer might be appropriate, for example\n\n* It's use is reached from a [shader style](#compile-style) entry point \n* It's value is constant across the launch \n\nIn Slang a variable can be declared as global in the C/C++ sense via the `__global` modifier. For example\n\n```\n__global int myGlobal;\n```\n\nDoing so means\n\n* `myGlobal` will not be defined in the constant buffer\n* It can be used in functions that do not have access to the [constant buffer](#context-threading)\n* It can be modified in the kernel \n* Can only be used on CPU targets (currently `__global` is not supported on the GPU targets)\n\nOne disadvantage of using `__global` is in multi-threaded environments, with multiple launches on multiple CPU threads, there is only one global and will likely cause problems unless the global value is the same across all threads.\n\nIt may be useful to set a global directly via host code, without having to write a function to enable the access. This is possible by using [`public`](#visibility) and [`__extern_cpp`](#visibility) modifiers. For example \n\n```\n__global public __extern_cpp int myGlobal;\n```\n\nThe global can now be set from host code via\n\n```C++\n    slang::ICompileRequest = ...;\n\n    // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library\n    // it's just an interface to executable code).\n    ComPtr<ISlangSharedLibrary> sharedLibrary;\n    SLANG_RETURN_ON_FAIL(request->getTargetHostCallable(0, sharedLibrary.writeRef()));\n\n    // Set myGlobal to 20\n    {\n        auto myGlobalPtr = (int*)sharedLibrary->findSymbolAddressByName(\"myGlobal\");\n        *myGlobalPtr = 20;\n    }\n```\n\nIn terms of reflection `__global` variables are not visibile. \n\n## NativeString\n\nSlang supports a rich 'String' type when using the [host style](#compile-style), which for C++ targets is implemented as the `Slang::String` C++ type. The type is only available on CPU targets that support `slang-rt`. \n\nSome limited String-like support is available via `NativeString` type which for C/C++ CPU targets is equivalent to `const char*`. For GPU targets this will use the same hash mechanism as normally available. \n\n`NativeString` is supported by all [shader compilation styles](#compile-style) including [slang-llvm](#slang-llvm).\n\nTODO(JS): What happens with String with shader compile style on CPU? Shouldn't it be the same as GPU (and reflected as such in reflection)?\n\n## Debugging\n\nIt is currently not possible to step into LLVM-JIT code when using [slang-llvm](#slang-llvm). Fortunately it is possible to step into code compiled via a [regular C/C++ compiler](#regular-cpp). \n\nBelow is a code snippet showing how to swich to a [regular C/C++ compiler](#regular-cpp) at runtime. \n\n```C++\n    SlangPassThrough findRegularCppCompiler(slang::IGlobalSession* slangSession)\n    {\n        // Current list of 'regular' C/C++ compilers\n        const SlangPassThrough cppCompilers[] = \n        {\n            SLANG_PASS_THROUGH_VISUAL_STUDIO,\n            SLANG_PASS_THROUGH_GCC,\n            SLANG_PASS_THROUGH_CLANG,\n        };\n        // Do we have a C++ compiler\n        for (const auto compiler : cppCompilers)\n        {\n            if (SLANG_SUCCEEDED(slangSession->checkPassThroughSupport(compiler)))\n            {\n                return compile;\n            }\n        }\n        return SLANG_PASS_THROUGH_NONE;\n    }\n\n    SlangResult useRegularCppCompiler(slang::IGlobalSession* session)\n    {\n        const auto regularCppCompiler = findRegularCppCompiler(session)\n        if (regularCppCompiler != SLANG_PASS_THROUGH_NONE)\n        {\n            slangSession->setDownstreamCompilerForTransition(SLANG_CPP_SOURCE, SLANG_SHADER_HOST_CALLABLE, regularCppCompiler);\n            slangSession->setDownstreamCompilerForTransition(SLANG_CPP_SOURCE, SLANG_HOST_HOST_CALLABLE, regularCppCompiler);\n            return SLANG_OK;\n        }\n        return SLANG_FAIL;\n    }\n```        \n\nIt is generally recommended to use [slang-llvm](#slang-llvm) if that is appropriate, but to switch to using a [regular C/C++ compiler](#regular-cpp) when debugging is needed. This should be largely transparent to most code.\n\nExecuting CPU Code\n==================\n\nIn typical Slang operation when code is compiled it produces either source or a binary that can then be loaded by another API such as a rendering API. With CPU code the binary produced could be saved to a file and then executed as an exe or a shared library/dll. In practice though it is common to want to be able to execute compiled code immediately. Having to save off to a file and then load again can be awkward. It is also not necessarily the case that code needs to be saved to a file to be executed. \n\nTo handle being able call code directly, code can be compiled using the [host-callable](#host-callable).\n\nFor pass through compilation of C/C++ this mechanism allows any functions marked for export to be directly queried. Marking for export is a C/C++ compiler specific feature. Look at the definition of `SLANG_PRELUDE_EXPORT` in the [C++ prelude](#prelude).\n\nFor a complete example on how to execute CPU code using `spGetEntryPointHostCallable`/`getEntryPointHostCallable` look at code in `example/cpu-hello-world`. \n\n<a id=\"abi\"/>Application Binary Interface (ABI)\n===\n\nSay we have some Slang source like the following:\n\n```\nstruct Thing { int a; int b; }\n\nTexture2D<float> tex;\nSamplerState sampler;\nRWStructuredBuffer<int> outputBuffer;        \nConstantBuffer<Thing> thing3;        \n        \n[numthreads(4, 1, 1)]\nvoid computeMain(\n    uint3 dispatchThreadID : SV_DispatchThreadID, \n    uniform Thing thing, \n    uniform Thing thing2)\n{\n   // ...\n}\n```\n\nWhen compiled into a [shader compile style](#compile-style) shared library/dll/host-callable - how is it invoked? An entry point in the Slang source code produces several exported functions. The 'default' exported function has the same name as the entry point in the original source. It has the signature  \n\n```\nvoid computeMain(ComputeVaryingInput* varyingInput, UniformEntryPointParams* uniformParams, UniformState* uniformState);\n```\n\nNOTE! Using `main` as an entry point name should be avoided if CPU is a target because it typically causes compilation errors due it's normal C/C++ usage.\n\nComputeVaryingInput is defined in the prelude as \n\n```\nstruct ComputeVaryingInput\n{\n    uint3 startGroupID;\n    uint3 endGroupID;\n};\n```\n\n`ComputeVaryingInput` allows specifying a range of groupIDs to execute - all the ids in a grid from startGroup to endGroup, but not including the endGroupIDs. Most compute APIs allow specifying an x,y,z extent on 'dispatch'. This would be equivalent as having startGroupID = { 0, 0, 0} and endGroupID = { x, y, z }. The exported function allows setting a range of groupIDs such that client code could dispatch different parts of the work to different cores. This group range mechanism was chosen as the 'default' mechanism as it is most likely to achieve the best performance.\n\nThere are two other functions that consist of the entry point name postfixed with `_Thread` and `_Group`. For the entry point 'computeMain' these functions would be accessable from the shared library interface as `computeMain_Group` and `computeMain_Thread`. `_Group` has the same signature as the listed for computeMain, but it doesn't execute a range, only the single group specified by startGroupID (endGroupID is ignored). That is all of the threads within the group (as specified by `[numthreads]`) will be executed in a single call. \n\nIt may be desirable to have even finer control of how execution takes place down to the level of individual 'thread's and this can be achieved with the `_Thread` style. The signature looks as follows\n\n```\nstruct ComputeThreadVaryingInput\n{\n    uint3 groupID;\n    uint3 groupThreadID;\n};\n\nvoid computeMain_Thread(ComputeThreadVaryingInput* varyingInput, UniformEntryPointParams* uniformParams, UniformState* uniformState);\n```\n\nWhen invoking the kernel at the `thread` level it is a question of updating the groupID/groupThreadID, to specify which thread of the computation to execute. For the example above we have `[numthreads(4, 1, 1)]`. This means groupThreadID.x can vary from 0-3 and .y and .z must be 0. That groupID.x indicates which 'group of 4' to execute. So groupID.x = 1, with groupThreadID.x=0,1,2,3 runs the 4th, 5th, 6th and 7th 'thread'. Being able to invoke each thread in this way is flexible - in that any specific thread can specified and executed. It is not necessarily very efficient because there is the call overhead and a small amount of extra work that is performed inside the kernel. \n\nNote that the `_Thread` style signature is likely to change to support 'groupshared' variables in the near future.\n\nIn terms of performance the 'default' function is probably the most efficient for most common usages. The `_Group` style allows for slightly less loop overhead, but with many invocations this will likely be drowned out by the extra call/setup overhead. The `_Thread` style in most situations will be the slowest, with even more call overhead, and less options for the C/C++ compiler to use faster paths. \n\nThe UniformState and UniformEntryPointParams struct typically vary by shader. UniformState holds 'normal' bindings, whereas UniformEntryPointParams hold the uniform entry point parameters. Where specific bindings or parameters are located can be determined by reflection. The structures for the example above would be something like the following... \n\n```\nstruct UniformEntryPointParams\n{\n    Thing thing;\n    Thing thing2;\n};\n\nstruct UniformState\n{\n    Texture2D<float > tex;\n    SamplerState sampler;\n    RWStructuredBuffer<int32_t> outputBuffer;\n    Thing* thing3;\n};   \n```\n\nNotice that of the entry point parameters `dispatchThreadID` is not part of UniformEntryPointParams and this is because it is not uniform.\n\n`ConstantBuffer` and `ParameterBlock` will become pointers to the type they hold (as `thing3` is in the above structure).\n \n`StructuredBuffer<T>`,`RWStructuredBuffer<T>` become\n\n```\n    T* data;\n    size_t count;\n```    \n\n`ByteAddressBuffer`, `RWByteAddressBuffer` become \n\n```\n    uint32_t* data;\n    size_t sizeInBytes;\n```    \n\n\nResource types become pointers to interfaces that implement their features. For example `Texture2D` become a pointer to a `ITexture2D` interface that has to be implemented in client side code. Similarly SamplerState and SamplerComparisonState become `ISamplerState` and `ISamplerComparisonState`.  \n \nThe actual definitions for the interfaces for resource types, and types are specified in 'slang-cpp-types.h' in the `prelude` directory.\n\n## Unsized arrays\n\nUnsized arrays can be used, which are indicated by an array with no size as in `[]`. For example \n\n```\n    RWStructuredBuffer<int> arrayOfArrays[];\n```\n\nWith normal 'sized' arrays, the elements are just stored contiguously within wherever they are defined. With an unsized array they map to `Array<T>` which is...\n\n```\n    T* data;\n    size_t count;\n```    \n\nNote that there is no method in the shader source to get the `count`, even though on the CPU target it is stored and easily available. This is because of the behavior on GPU targets \n\n* That the count has to be stored elsewhere (unlike with CPU) \n* On some GPU targets there is no bounds checking - accessing outside the bound values can cause *undefined behavior*\n* The elements may be laid out *contiguously* on GPU\n\nIn practice this means if you want to access the `count` in shader code it will need to be passed by another mechanism - such as within a constant buffer. It is possible in the future support may be added to allow direct access of `count` work across targets transparently. \n\nIt is perhaps worth noting that the CPU allows us to have an indirection (a pointer to the unsized arrays contents) which has the potential for more flexibility than is possible on GPU targets. GPU target typically require the elements to be placed 'contiguously' from their location in their `container` - be that registers or in memory. This means on GPU targets there may be other restrictions on where unsized arrays can be placed in a structure for example, such as only at the end. If code needs to work across targets this means these restrictions will need to be followed across targets. \n\n## <a id=\"context-threading\"/>Context Threading\n\nThe [shader compile style](#compile-style) brings some extra issues to bare. In the HLSL compute kernel launch model application visible variables and resource are bound. As described in the [ABI](#abi) section these bindings and additional information identifying a compute thread are passed into the launch as a context. Take for example the code snippet below\n\n```\nint myGlobal;\n\nint myFunc(int v)\n{\n    return myGlobal + v;\n}\n\nint anotherFunc(int a, int b)\n{\n    return a + b;\n}\n\n[numthreads(4, 1, 1)]\nvoid computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)\n{    \n    outputBuffer[dispatchThreadID.x] = myFunc(dispatchThreadID.x) + anotherFunc(1, dispatchThreadID.y);\n}\n```\n\nThe function `myFunc` accesses a variable `myGlobal` that is held within a constant buffer. The function cannot be meaningfully executed without access to the context, and the context is available as a parameter passed through `computeMain` entry point at launch. This means the *actual* signature of this function in output code will be something like\n\n```\nint32_t myFunc_0(KernelContext_0 * kernelContext_0)\n{\n    return *(&(*(&kernelContext_0->globalParams_0))->myGlobal_0) + int(1);\n}\n```\n\nThe context parameter has been *threaded* into this function. This *threading* will happen to any function that accesses any state that is held in the context. This behavior also happens transitively - if a function *could* call *any* another function that requires the context, the context will be threaded through to it also.\n\nIf application code assumed `myFunc` could be called with no parameters a crash would likely ensue. Note that `anotherFunc` does not have the issue because it doesn't perform an access that needs the context, and so no context threading is added.\n\nIf a global is desired in a function that wants to be called from the application, the [`__global`](#actual-global) modifier can be used.\n\n## <a id=\"prelude\"/>Prelude\n\nFor C++ targets, there is code to support the Slang generated source defined within the 'prelude'. The prelude is inserted text placed before the Slang generated C++ source. For the Slang command line tools as well as the test infrastructure, the prelude functionality is achieved through a `#include` in the prelude text of the `prelude/slang-cpp-prelude.h` specified with an absolute path. Doing so means other files the `slang-cpp-prelude.h` might need can be specified relatively, and include paths for the backend C/C++ compiler do not need to be modified. \n\nThe prelude needs to define \n\n* 'Built in' types (vector, matrix, 'object'-like Texture, SamplerState etc) \n* Scalar intrinsic function implementations\n* Compiler based definations/tweaks \n\nFor the Slang prelude this is split into the following files...\n\n* 'prelude/slang-cpp-prelude.h' - Header that includes all the other requirements & some compiler tweaks\n* 'prelude/slang-cpp-scalar-intrinsics.h' - Scalar intrinsic implementations\n* 'prelude/slang-cpp-types.h' - The 'built in types' \n* 'slang.h' - Slang header is used for majority of compiler based definitions\n\nFor a client application - as long as the requirements of the generated code are met, the prelude can be implemented by whatever mechanism is appropriate for the client. For example the implementation could be replaced with another implementation, or the prelude could contain all of the required text for compilation. Setting the prelude text can be achieved with the method on the global session...\n\n```\n/** Set the 'prelude' for generated code for a 'downstream compiler'.\n@param passThrough The downstream compiler for generated code that will have the prelude applied to it. \n@param preludeText The text added pre-pended verbatim before the generated source\n\nThat for pass-through usage, prelude is not pre-pended, preludes are for code generation only. \n*/\nvirtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPrelude(\nSlangPassThrough passThrough,\nconst char* preludeText) = 0;\n```\n\nIt may be useful to be able to include `slang-cpp-types.h` in C++ code to access the types that are used in the generated code. This introduces a problem in that the types used in the generated code might clash with types in client code. To work around this problem, you can wrap all of the types defined in the prelude with a namespace of your choosing. For example \n\n```\n#define SLANG_PRELUDE_NAMESPACE CPPPrelude\n#include \"../../prelude/slang-cpp-types.h\"\n``` \n\nWould wrap all the Slang prelude types in the namespace `CPPPrelude`, such that say a `StructuredBuffer<int32_t>` could be specified in C++ source code as `CPPPrelude::StructuredBuffer<int32_t>`.\n\nThe code that sets up the prelude for the test infrastucture and command line usage can be found in ```TestToolUtil::setSessionDefaultPrelude```. Essentially this determines what the absolute path is to `slang-cpp-prelude.h` is and then just makes the prelude `#include \"the absolute path\"`.\n\nThe *default* prelude is set to the contents of the files for C++ held in the prelude directory and is held within the Slang shared library. It is therefore typically not necessary to distribute Slang with prelude files.\n\nLanguage aspects\n================\n\n# Arrays passed by Value\n\nSlang follows the HLSL convention that arrays are passed by value. This is in contrast the C/C++ where arrays are passed by reference. To make generated C/C++ follow this convention an array is turned into a 'FixedArray' struct type. Sinces classes by default in C/C++ are passed by reference the wrapped array is also. \n\nTo get something similar to C/C++ operation the array can be marked `inout` to make it passed by reference. \n\nLimitations\n===========\n\n# <a id=\"out-of-bounds\"/>Out of bounds access\n\nIn HLSL code if an access is made out of bounds of a StructuredBuffer, execution proceceeds. If an out of bounds read is performed, a zeroed value is returned. If an out of bounds write is performed it's effectively a noop, as the value is discarded. On the CPU target this behavior is *not* supported by default. \n\nFor a debug CPU build an out of bounds access will assert, for a release build the behaviour is by default undefined. A limited Limited [zero index](#zero-index) out of bounds mechanism is supported, but must be enabled.\n\nThe reason for this is that such an access is difficult and/or slow to implement the identical GPU behavior on the CPU. The underlying problem is `operator[]` typically returns a reference to the contained value. If this is out of bounds - it's not clear what to return, in particular because the value may be read or written and moreover elements of the type might be written. In practice this means a global zeroed value cannot be returned. \n\nThis could be somewhat supported if code gen worked as followed for say\n\n```\nRWStructuredBuffer<float4> values;\nvalues[3].x = 10;\n```\n\nProduces\n\n```\ntemplate <typename T>\nstruct RWStructuredBuffer\n{\n    T& at(size_t index, T& defValue) { return index < size ? values[index] : defValue; } \n\n    T* values;\n    size_t size;\n};\n\nRWStructuredBuffer<float4> values;\n\n// ...\nVector<float, 3> defValue = {};         // Zero initialize such that read access returns default values\nvalues.at(3).x = 10;\n```\n\nNote that '[] 'would be turned into the `at` function, which takes the default value as a paramter provided by the caller. If this is then written to then only the defValue is corrupted.  Even this mechanism not be quite right, because if we write and then read again from the out of bounds reference in HLSL we may expect that 0 is returned, whereas here we get the value that was last written.\n\n## <a id=\"zero-index\"/>Zero index bound checking\n\nIf bounds checking is wanted in order to avoid undefined behavior and limit how memory is accessed `zero indexed` bounds checking might be appropriate. When enabled if an access is out of bounds the value at the zero index is returned. This is quite different behavior than the typical GPU behavior, but is fairly efficient and simple to implement. Importantly it means behavior is well defined and always 'in range' assuming there is an element.\n\nTo enable zero indexing bounds checking pass in the define `SLANG_ENABLE_BOUND_ZERO_INDEX` to a Slang compilation. This define is passed down to C++ and CUDA compilations, and the code in the CUDA and C++ preludes implement the feature. Note that zero indexed bounds checking will slow down accesses that are checked.\n\nThe C++ implementation of the feature can be seen by looking at the file \"prelude/slang-cpp-types.h\". For CUDA \"prelude/slang-cuda-prelude.h\".\n\nThe bounds checking macros are guarded such it is possible to replace the implementations, without directly altering the prelude.\n\nTODO\n====\n\n# Main\n\n* groupshared is not yet supported\n* Output of header files \n* Output multiple entry points\n\n# Internal Slang compiler features\n\nThese issues are more internal Slang features/improvements \n\n* Currently only generates C++ code, it would be fairly straight forward to support C (especially if we have 'intrinsic definitions')\n* Have 'intrinsic definitions' in standard library - such that they can be generated where appropriate \n  + This will simplify the C/C++ code generation as means Slang language will generate must of the appropriate code\n* Currently 'construct' IR inst is supported as is, we may want to split out to separate instructions for specific scenarios\n* Refactoring around swizzle. Currently in emit it has to check for a variety of scenarios - could be simplified with an IR pass and perhaps more specific instructions. \n"
  },
  {
    "path": "Source/External/slang/docs/cuda-target.md",
    "content": "Slang CUDA Target Support\n=========================\n\nSlang has preliminary support for producing CUDA source, and PTX binaries using (NVRTC)[https://docs.nvidia.com/cuda/nvrtc/index.html]. \n\nNOTE! NVRTC is only available for 64-bit operating systems. On Windows Visual Studio make sure you are compiling for 'x64' and/or use 64 bit Slang binaries. \n\n# Features\n\n* Can compile Slang source into CUDA source code\n* Supports compute style shaders \n* Supports a 'bindless' CPU like model\n* Can compile CUDA source to PTX through 'pass through' mechansism\n\n# Limitations\n\nThese limitations apply to Slang transpiling to CUDA. \n\n* Only supports the 'texture object' style binding (The texture object API is only supported on devices of compute capability 3.0 or higher. )\n* Samplers are not separate objects in CUDA - they are combined into a single 'TextureObject'. So samplers are effectively ignored on CUDA targets. \n* When using a TextureArray.Sample (layered texture in CUDA) - the index will be treated as an int, as this is all CUDA allows\n* Care must be used in using `WaveGetLaneIndex` wave intrinsic - it will only give the right results for appropriate launches\n* CUDA 'surfaces' are used for textures which are read/write (aka RWTexture). \n\nThe following are a work in progress or not implemented but are planned to be so in the future\n\n* Some resource types remain unsupported, and not all methods on all types are supported\n\n# How it works\n\nFor producing PTX binaries Slang uses (NVRTC)[https://docs.nvidia.com/cuda/nvrtc/index.html]. NVRTC dll/shared library has to be available to Slang (for example in the appropriate PATH for example) for it to be able to produce PTX.\n\nThe NVRTC compiler can be accessed directly via the pass through mechanism and is identifed by the enum value `SLANG_PASS_THROUGH_NVRTC`.\n\nMuch like other targets that use downstream compilers Slang can be used to compile CUDA source directly to PTX via the pass through mechansism. The Slang command line options will broadly be mapped down to the appropriate options for the NVRTC compilation. In the API the `SlangCompileTarget` for CUDA is `SLANG_CUDA_SOURCE` and for PTX is `SLANG_PTX`. These can also be specified on the Slang command line as `-target cuda` and `-target ptx`. \n\n## Locating NVRTC\n\nFinding NVRTC can require some nuance if a specific version is required. On the command line the `-nvrtc-path` option can be used to set the `path` to NVRTC. Also `spProcessCommandLineArguments`/`processCommandLineArguments` with `-nvrtc-path` or `setDownstreamCompilerPath` with `SLANG_PASS_THROUGH_NVRTC` can be used to set the location and/or name of NVRTC via the API. \n\nImportant points of note are\n\n* The name of the shared library should *not* include any extension (such as `.dll`/`.so`/`.dynlib`) or prefix (such as `lib`).\n* The path also *doesn't* have to be path, it can just be the shared library name. Doing so will mean it will be searched for by whatever the default mechanism is on the target. \n* If a path and/or name is specified for NVRTC - this will be the *only* version searched for.\n \nIf a path/name is *not* specified for NVRTC, Slang will attempt to load a shared library called `nvrtc`. For non Windows targets this should be enough to find and load the latest version.\n \nOn Windows NVRTC dlls have a name the contains the version number, for example `nvrtc64_102_0.dll`. This will lead to the load of just `nvrtc` to fail. One approach to fix this is to place the NVRTC dll and associated files in the same directory as slang.dll, and rename the main dll to `nvrtc.dll`. Another approach is to specify directly on the command line the name including the version, as previously discussed. For example  \n\n`-nvrtc-path nvrtc64_102_0` \n \nwill load NVRTC 10.2 assuming that version of the dll can be found via the normal lookup mechanism.\n\nOn Windows if NVRTC is not loadable directly as 'nvrtc' Slang will attempt to search for the newest version of NVRTC on your system. The places searched are...\n\n* The instance directory (where the slang.dll and/or program exe is)\n* The CUDA_PATH enivonment variable (if set)\n* Directories in PATH that look like a CUDA installation.\n\nIf a candidate is found via an earlier mechanism, subsequent searches are not performed. If multiple candidates are found, Slang tries the newest version first.\n\nBinding \n=======\n\nSay we have some Slang source like the following:\n\n```\nstruct Thing { int a; int b; }\n\nTexture2D<float> tex;\nSamplerState sampler;\nRWStructuredBuffer<int> outputBuffer;        \nConstantBuffer<Thing> thing3;        \n        \n[numthreads(4, 1, 1)]\nvoid computeMain(\n    uint3 dispatchThreadID : SV_DispatchThreadID, \n    uniform Thing thing, \n    uniform Thing thing2)\n{\n   // ...\n}\n```\n\nThis will be turned into a CUDA entry point with \n\n```\nstruct UniformEntryPointParams\n{\n    Thing thing;\n    Thing thing2;\n};\n\nstruct UniformState\n{\n    CUtexObject tex;                // This is the combination of a texture and a sampler(!)\n    SamplerState sampler;           // This variable exists within the layout, but it's value is not used.\n    RWStructuredBuffer<int32_t> outputBuffer;    // This is implemented as a template in the CUDA prelude. It's just a pointer, and a size\n    Thing* thing3;                  // Constant buffers map to pointers\n};   \n\n// [numthreads(4, 1, 1)]\nextern \"C\" __global__  void computeMain(UniformEntryPointParams* params, UniformState* uniformState)\n```\n\nWith CUDA - the caller specifies how threading is broken up, so `[numthreads]` is available through reflection, and in a comment in output source code but does not produce varying code. \n\nThe UniformState and UniformEntryPointParams struct typically vary by shader. UniformState holds 'normal' bindings, whereas UniformEntryPointParams hold the uniform entry point parameters. Where specific bindings or parameters are located can be determined by reflection. The structures for the example above would be something like the following... \n\n`StructuredBuffer<T>`,`RWStructuredBuffer<T>` become\n\n```\n    T* data;\n    size_t count;\n```    \n\n`ByteAddressBuffer`, `RWByteAddressBuffer` become \n\n```\n    uint32_t* data;\n    size_t sizeInBytes;\n```  \n\n## Texture\n\nRead only textures will be bound as the opaque CUDA type CUtexObject. This type is the combination of both a texture AND a sampler. This is somewhat different from HLSL, where there can be separate `SamplerState` variables. This allows access of a single texture binding with different types of sampling. \n\nIf code relys on this behavior it will be necessary to bind multiple CtexObjects with different sampler settings, accessing the same texture data. \n\nSlang has some preliminary support for TextureSampler type - a combined Texture and SamplerState. To write Slang code that can target CUDA and other platforms using this mechanism will expose the semantics appropriately within the source.  \n \nLoad is only supported for Texture1D, and the mip map selection argument is ignored. This is because there is tex1Dfetch and no higher dimensional equivalents. CUDA also only allows such access if the backing array is linear memory - meaning the bound texture cannot have mip maps - thus making the mip map parameter superflous anyway. RWTexture does allow Load on other texture types.  \n \n## RWTexture \n \nRWTexture types are converted into CUsurfObject type. \n\nIn regular CUDA it is not possible to do a format conversion on an access to a CUsurfObject. Slang does add support for hardware write conversions where they are available. To enable the feature it is necessary to attribute your RWTexture with `format`. For example\n\n```\n[format(\"rg16f\")]\nRWTexture2D<float2> rwt2D_2;\n```\n\nThe format names used are the same as for (GLSL layout format types)[https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)]. If no format is specified Slang will *assume* that the format is the same as the type specified. \n\nNote that the format attribution is on variables/paramters/fields and not part of the type system. This means that if you have a scenario like...\n\n```\n[format(rg16f)]\nRWTexture2d<float2> g_texture;\n\nfloat2 getValue(RWTexture2D<float2> t)\n{\n    return t[int2(0, 0];\n}\n\nvoid doThing()\n{\n    float2 v = getValue(g_texture);\n}\n```\n\nEven `getValue` will receive t *without* the format attribute, and so will access it, presumably erroneously. A work around for this specific scenario would be to attribute the parameter\n\n```\nfloat2 getValue([format(\"rg16f\")] RWTexture2D<float2> t)\n{\n    return t[int2(0, 0];\n}\n```\n\nThis will only work correctly if `getValue` is called with a `t` that has that format attribute. As it stands no checking is performed on this matching so no error or warning will be produced if there is a mismatch. \n\nThere is limited software support for doing a conversion on reading. Currently this only supports only 1D, 2D, 3D RWTexture, backed with half1, half2 or half4. For this path to work NVRTC must have the `cuda_fp16.h` and associated files available. Please check the section on `Half Support`.\n\nIf hardware read conversions are desired, this can be achieved by having a Texture<T> that uses the surface of a RWTexture<T>. Using the Texture<T> not only allows hardware conversion but also filtering. \n\nIt is also worth noting that CUsurfObjects in CUDA are NOT allowed to have mip maps. \n\nBy default surface access uses cudaBoundaryModeZero, this can be replaced using the macro SLANG_CUDA_BOUNDARY_MODE in the CUDA prelude. For HW format conversions the macro SLANG_PTX_BOUNDARY_MODE. These boundary settings are in effect global for the whole of the kernel. \n\n`SLANG_CUDA_BOUNDARY_MODE` can be one of\n\n* cudaBoundaryModeZero      causes an execution trap on out-of-bounds addresses\n* cudaBoundaryModeClamp     stores data at the nearest surface location (sized appropriately)\n* cudaBoundaryModeTrap      drops stores to out-of-bounds addresses \n\n`SLANG_PTX_BOUNDARY_MODE` can be one of `trap`, `clamp` or `zero`. In general it is recommended to have both set to the same type of value, for example `cudaBoundaryModeZero` and `zero`.\n\n## Sampler\n\nSamplers are in effect ignored in CUDA output. Currently we do output a variable `SamplerState`, but this value is never accessed within the kernel and so can be ignored. More discussion on this behavior is in `Texture` section.\n\n## Unsized arrays\n\nUnsized arrays can be used, which are indicated by an array with no size as in `[]`. For example \n\n```\n    RWStructuredBuffer<int> arrayOfArrays[];\n```\n\nWith normal 'sized' arrays, the elements are just stored contiguously within wherever they are defined. With an unsized array they map to `Array<T>` which is...\n\n```\n    T* data;\n    size_t count;\n```    \n\nNote that there is no method in the shader source to get the `count`, even though on the CUDA target it is stored and easily available. This is because of the behavior on GPU targets \n\n* That the count has to be stored elsewhere (unlike with CUDA) \n* On some GPU targets there is no bounds checking - accessing outside the bound values can cause *undefined behavior*\n* The elements may be laid out *contiguously* on GPU\n\nIn practice this means if you want to access the `count` in shader code it will need to be passed by another mechanism - such as within a constant buffer. It is possible in the future support may be added to allow direct access of `count` work across targets transparently. \n\n## Prelude\n\nFor CUDA the code to support the code generated by Slang is partly defined within the 'prelude'. The prelude is inserted text placed before the generated CUDA source code. For the Slang command line tools as well as the test infrastructure, the prelude functionality is achieved through a `#include` in the prelude text of the `prelude/slang-cuda-prelude.h` specified with an absolute path. Doing so means other files the `slang-cuda-prelude.h` might need can be specified relatively, and include paths for the backend compiler do not need to be modified. \n\nThe prelude needs to define \n\n* 'Built in' types (vector, matrix, 'object'-like Texture, SamplerState etc) \n* Scalar intrinsic function implementations\n* Compiler based definations/tweaks \n\nFor a client application - as long as the requirements of the generated code are met, the prelude can be implemented by whatever mechanism is appropriate for the client. For example the implementation could be replaced with another implementation, or the prelude could contain all of the required text for compilation. Setting the prelude text can be achieved with the method on the global session...\n\n```\n/** Set the 'prelude' for generated code for a 'downstream compiler'.\n@param passThrough The downstream compiler for generated code that will have the prelude applied to it. \n@param preludeText The text added pre-pended verbatim before the generated source\n\nThat for pass-through usage, prelude is not pre-pended, preludes are for code generation only. \n*/\n\nvoid setDownstreamCompilerPrelude(SlangPassThrough passThrough, const char* preludeText);\n```\n\nThe code that sets up the prelude for the test infrastucture and command line usage can be found in ```TestToolUtil::setSessionDefaultPrelude```. Essentially this determines what the absolute path is to `slang-cpp-prelude.h` is and then just makes the prelude `#include \"the absolute path\"`.\n\nHalf Support\n============\n\nSlang supports the half/float16 types on CUDA. To do so NVRTC must have access to the `cuda_fp16.h` and `cuda_fp16.hpp` files that are typically distributed as part of the CUDA SDK. When Slang detects the use of half in source, it will define `SLANG_CUDA_ENABLE_HALF` when `slang-cuda-prelude.h` is included. This will in turn try to include `cuda_fp16.h` and enable extra functionality within the prelude for half support. \n\nSlang tries several mechanisms to locate `cuda_fp16.h` when NVRTC is initiated. The first mechanism is to look in the include paths that are passed to Slang. If `cuda_fp16.h` can be found in one of these paths, no more searching will be performed. \n\nIf this fails, the path where NVRTC is located will be searched. In that path \"include\" and \"CUDA/include\" paths will be searched. This is probably most suitable for Windows based targets, where NVRTC dll is placed along with other binaries. The \"CUDA/include\" path is used to try and make clear in this scenario what the contained files are for. \n\nIf this fails Slang will look for the CUDA_PATH environmental variable, as is typically set during a CUDA SDK installation. \n\nIf this fails - the prelude include of `cuda_fp16.h` will most likely fail on NVRTC invocation.\n\nCUDA has the `__half` and `__half2` types defined in `cuda_fp16.h`. The `__half2` can produce results just as quickly as doing the same operation on `__half` - in essence for some operations `__half2` is [SIMD](https://en.wikipedia.org/wiki/SIMD) like. The half implementation in Slang tries to take advantage of this optimization. \n\nSince Slang supports up to 4 wide vectors Slang has to build on CUDAs half support. The types _`_half3` and `__half4` are implemented in `slang-cuda-prelude.h` for this reason. It is worth noting that `__half3` is made up of a `__half2` and a `__half`. As `__half2` is 4 byte aligned, this means `__half3` is actually 8 bytes, rather than 6 bytes that might be expected.\n\nOne area where this optimization isn't fully used is in comparisons - as in effect Slang treats all the vector/matrix half comparisons as if they are scalar. This could be perhaps be improved on in the future. Doing so would require using features that are not directly available in the CUDA headers. \n\nWave Intrinsics\n===============\n\nThere is broad support for [HLSL Wave intrinsics](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12), including support for [SM 6.5 intrinsics](https://microsoft.github.io/DirectX-Specs/d3d/HLSL_ShaderModel6_5.html). \n\nMost Wave intrinsics will work with vector, matrix or scalar types of typical built in types - uint, int, float, double, uint64_t, int64_t.  \n\nThe support is provided via both the Slang stdlib as well as the Slang CUDA prelude found in 'prelude/slang-cuda-prelude.h'. Many Wave intrinsics are not directly applicable within CUDA which supplies a more low level mechanisms. The implementation of most Wave functions work most optimally if a 'Wave' where all lanes are used. If all lanes from index 0 to pow2(n) -1  are used (which is also true if all lanes are used) a binary reduction is typically applied. If this is not the case the implementation fallsback on a slow path which is linear in the number of active lanes, and so is typically significantly less performant. \n\nFor more a more concrete example take \n\n```\nint sum = WaveActiveSum(...);\n```\n\nWhen computing the sum, if all lanes (32 on CUDA), the computation will require 5 steps to complete (2^5 = 32). If say just one lane is not being used it will take 31 steps to complete (because it is now linear in amount of lanes). So just having one lane disabled required 6 times as many steps. If lanes with 0 - 15 are active, it will take 4 steps to complete (2^4 = 16). \n\nIn the future it may be possible to improve on the performance of the 'slow' path, however it will always remain the most efficient generally for all of 0 to pow2(n) - 1 lanes to be active. \n\nIt is also worth noting that lane communicating intrinsics performance will be impacted by the 'size' of the data communicated. The size here is at a minimum the amount of built in scalar types used in the processing. The CUDA language only allows direct communication with built in scalar types. \n\nThus \n\n```\nint3 v = ...;\nint3 sum = WaveActiveSum(v);\n```\n\nWill require 3 times as many steps as the earlier scalar example just using a single int. \n\n## WaveGetLaneIndex\n\n'WaveGetLaneIndex' defaults to `(threadIdx.x & SLANG_CUDA_WARP_MASK)`. Depending on how the kernel is launched this could be incorrect. There other ways to get lane index, for example using inline assembly. This mechanism though is apparently slower than the simple method used here. There is support for using the asm mechnism in the CUDA prelude using the `SLANG_USE_ASM_LANE_ID` preprocessor define to enable the feature. \n\nThere is potential to calculate the lane id using the [numthreads] markup in Slang/HLSL, but that also requires some assumptions of how that maps to a lane index. \n\n## Unsupported Intrinsics\n\n* Intrinsics which only work in pixel shaders\n  + QuadXXXX intrinsics\n  \nLimitations\n===========\n\nSome features are not available because they cannot be mapped with appropriate behavior to a target. Other features are unavailable because of resources to devote to more unusual features. \n\n* Not all Wave intrinsics are supported\n* There is not complete support for all methods on 'objects' like textures etc. \n* Does not currently support combined 'TextureSampler'. A Texture behaves equivalently to a TextureSampler and Samplers are ignored.\n* Half type is not currently supported\n* GetDimensions is not available on any Texture type currently - as there doesn't appear to be a CUDA equivalent \n\nLanguage aspects\n================\n\n# Arrays passed by Value\n\nSlang follows the HLSL convention that arrays are passed by value. This is in contrast with CUDA where arrays follow C++ conventions and are passed by reference. To make generated CUDA follow this convention an array is turned into a 'FixedArray' struct type. \n\nTo get something more similar to CUDA/C++ operation the array can be marked in out or inout to make it passed by reference. \n"
  },
  {
    "path": "Source/External/slang/docs/doc-system.md",
    "content": "Slang Doc System \n================\n\nSlang contains a rudimentary documentation generation system. The mechanism used to mark up source is similar to [doxygen](https://www.doxygen.nl/manual/docblocks.html). Namely\n\n```\n/**\n ... text ... (JavaDoc style)\n */\nvoid someFunctionA() {} \n \n/*!\n .. text .. (QT style)\n another line\n */ \nvoid someFunctionB() {} \n \n/// ... text ... (Multi line)\n/// another line\nvoid someFunctionC() {}\n \n//!... text ...  (QT Multi line)\n//! another line\nvoid someFunctionD() {}\n \n```\n \nAll of the above examples will add the documentation for the declaration that appears after them. Also note that this slightly diverges from doxygen in that an empty line before and after in a multi line comment is *not* required.\n\nWe can also document the parameters to a function similarly\n\n```\n/// My function\nvoid myFunction(\n    /// The A parameter \n    int a, \n    /// The B parameter\n    int b);\n```\n\nIf you just need a single line comment to describe something, you can place the documentation after the parameter as in\n\n```\n\n/// My function\nvoid myFunction(    int a,      //< The A parameter     \n                    int b)      //< The B parameter\n{}\n```\n\nThis same mechanisms work for other kinds of common situations such as with enums \n\n```\n/// An enum\nenum AnEnum\n{\n    Value, ///< A value\n    /// Another value\n    /// With a multi-line comment\n    AnotherValue,\n};\n```\n\nLike `doxygen` we can also have multi line comments after a declaration for example\n\n```\n/// An enum\nenum AnEnum\n{\n    Value, ///< A value\n           ///< Some more information about `Value`\n           \n    /// Another value\n    /// With a multi-line comment\n    AnotherValue,\n};\n```\n\n\n\n\nTo actually get Slang to output documentation you can use the `-doc` option from the `slangc` command line, or pass it in as parameter to `spProcessCommandLineArguments` or `processCommandLineArguments`. The documentation is currently output by default to the same `ISlangWriter` stream as diagnostics. So for `slangc` this will generally mean the terminal/stderr. \n\nCurrently the Slang doc system does not support any of the 'advanced' doxygen documentation features. If you add documentation to a declaration it is expected to be in [markdown](https://guides.github.com/features/mastering-markdown/). \n\nCurrently the only documentation style supported is a single file 'markdown' output. Future versions will support splitting into multiple files and linking between them. Also future versions may also support other documentation formats/standards.\n\nIt is possible to generate documentation for Slangs internal `stdlib`. This can be achieved with `slangc` via\n\n```\nslangc -doc -compile-stdlib\n```\n\nThe documentation will be written to a file `stdlib-doc.md`.\n\nIt should be noted that it is not necessary to add markup to a declaration for the documentation system to output documentation for it. Without the markup the documentation is going to be very limited, in essence saying the declaration exists and other aspects that are available from the source. This may not be very helpful. For this reason and other reasons there is a mechanism to control the visibility of items in your source. \n\nThere are 3 visibility levels 'public', 'internal' and 'hidden'/'private'. There is a special comment that controls visibility for subsequent lines. The special comment starts with `//@` as shown below.\n\n```\n//@ public:\n\nvoid thisFunctionAppearsInDocs() {}\n\n//@ internal:\n\nvoid thisFunctionCouldAppearInInternalDocs() {}\n\n//@ hidden:\n\nvoid thisFunctionWillNotAppearInDocs() {}\n```\n\n\n"
  },
  {
    "path": "Source/External/slang/docs/faq.md",
    "content": "Frequently Asked Questions\n==========================\n\n### How did this project start?\n\nThe Slang project forked off from the [\"Spire\"](https://github.com/spire-lang/spire) shading language research project.\nIn particular, Slang aims to take the lessons learned in that research effort (about how to make more productive shader compilation languages and tools) and apply them to a stystem that is easier to adopt, and hopefully moreamenable to production use.\n\n### Why should I use Slang instead of glslang, hlsl2glslfork, the Microsoft open-source HLSL compiler, etc.?\n\nIf you are mostly just shoping around for a tool to get HLSL shaders working on other graphics APIs, then [this](http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/) blog post is probably a good place to start.\n\nIf one of those tools meets your requirements, then you should probably use it.\nSlang is a small project, and early in development, so you might find that you hit fewer bumps in the road with one of the more established tools out there.\n\nThe goal of the Slang project is not to make \"yet another HLSL-to-GLSL translator,\" but rather to create a shading language and supporting toolchain that improves developer productivity (and happiness) over the existing HLSL language and toolchain, while providing a reasonable adoption path for developers who have an existing investment in HLSL shader code.\nIf you think that is something interesting and worth supporting, then please get involved!\n\n### What would make a shading language more productive?\n\nThis is probably best answered by pointing to the most recent publication from the Spire research project:\n\n[Shader Components: Modular and High Performance Shader Development](http://graphics.cs.cmu.edu/projects/shadercomp/)\n\nSome other papers for those who would like to read up on our inspiration:\n\n[A System for Rapid Exploration of Shader Optimization Choices](http://graphics.cs.cmu.edu/projects/spire/)\n[Spark: Modular, Composable Shaders for Graphics Hardware](https://graphics.stanford.edu/papers/spark/)\n\n### Who is using Slang?\n\nRight now the only user of Slang is the [Falcor](https://github.com/NVIDIA/Falcor) real-time rendering framework developed and used by NVIDIA Research.\nThe implementation of Slang has so far focused heavily on the needs of Falcor.\n\n### Won't we all just be using C/C++ for shaders soon?\n\nThe great thing about both Vulkan and D3D12 moving to publicly-documented binary intermediate langugaes (SPIR-V and DXIL, respectively) is that there is plenty of room for language innovation on top of these interfaces.\n\nHaving support for writing GPU shaders in a reasonably-complete C/C++ language would be great.\nWe are supportive of efforts in the \"C++ for shaders\" direction.\n\nThe Slang effort is about trying to solve the challenges that are unique to the real-time graphics domain, and that won't magically get better by switching to C++.\n"
  },
  {
    "path": "Source/External/slang/docs/language-guide.md",
    "content": "Slang Language Guide\n====================\n\nThis document will try to describe the main characteristis of the Slang language that might make it different from other shading languages you have used.\n\nThe Basics\n----------\n\nSlang is similar to HLSL, and it is expected that many HLSL programs can be used as Slang code with no modifications.\nBig-picture stuff that is supported:\n\n* A C-style preprocessor\n* Ordinary function, `struct`, `typedef`, etc. declarations\n* The standard vector/matrix types like `float3` and `float4x4`\n* The less-used explicit `vector<T,N>` and `matrix<T,R,C>` types\n* `cbuffer` declarations for uniform parameters\n* Global-scope declarations of texture/sampler parameters, including with `register` annotations\n* Entry points with varying `in`/`out` parameters using semantics (including `SV_*` system-value semantics)\n* The built-in templated resource types like `Texture2D<T>` with their object-oriented syntax for sampling operations\n* Attributes like `[unroll]` are parsed, and passed along for HLSL/DXBC output, but dropped for other targets\n* `struct` types that contain textures/samplers as well as ordinary uniform data, both as function parameters and in constant buffers\n* The built-in functions up through Shader Model 6.0 (as documented on MSDN) are supported\n\nNew Features\n------------\n\n### Import Declarations\n\nIn order to support better software modularity, and also to deal with the issue of how to integrate shader libraries written in Slang into other langauges, Slang introduces an `import` declaration construct.\n\nThe basic idea is that if you write a file `foo.slang` like this:\n\n```hlsl\n// foo.slang\n\nfloat4 someFunc(float4 x) { return x; }\n```\n\nyou can then import this code into another file in Slang, HLSL, or GLSL:\n\n```hlsl\n// bar.slang\n\nimport foo;\n\nfloat4 someOtherFunc(float4 y) { return someFunc(y); }\n```\n\nThe simplest way to think of it is that the `import foo` declaration instructs the compiler to look for `foo.slang` (in the same search paths it uses for `#include` files), and give an error if it isn't found.\nIf `foo.slang` is found, then the compiler will go ahead and parse and type-check that file, and make any declarations there visible to the original file (`bar.glsl` in this example).\n\nWhen it comes time to generate output code, Slang will output any declarations from `import`ed files that were actually used (it skips those that are never referenced), and it will cross-compile them as needed for the chosen target.\n\nA few other details worth knowing about `import` declarations:\n\n* The name you use on the `import` line gets translated into a file name with some very simple rules. An underscore (`_`) in the name turns into a dash (`-`) in the file name, and dot separators (`.`) turn into directory seprators (`/`). After these substitutions, `.slang` is added to the end of the name.\n\n* If there are multiple `import` declarations naming the same file, it will only be imported once. This is also true for nested imports.\n\n* Currently importing does not imply any kind of namespacing; all global declarations still occupy a single namespace, and collisions between different imported files (or between a file and the code it imports) are possible. This is a bug.\n\n* If file `A.slang` imports `B.slang`, and then some other file does `import A;`, then only the names from `A.slang` are brought into scope, not those from `B.slang`. This behavior can be controlled by having `A.slang` use `__exported import B;` to also re-export the declarations it imports from `B`.\n\n* An import is *not* like a `#include`, and so the file that does the `import` can't see preprocessor macros defined in the imported file (and vice versa). Think of `import foo;` as closer to `using namspace foo;` in C++ (perhaps without the same baggage).\n\n### Explicit Parameter Blocks\n\nOne of the most important new features of modern APIs like Direct3D 12 and Vulkan is an interface for providing shader parameters using efficient *parameter blocks* that can be stored in GPU memory (these are implemented as descritpor tables/sets in D3D12/Vulkan, and \"attribute buffers\" in Metal).\nHowever, HLSL and GLSL don't support explicit syntax for parmaeter blocks, and so shader programmers are left to manually pack parameters into blocks either using `register`/`layout` modifiers, or with API-based remapping (in the D3D12 case).\n\nSlang supports a simple and explicit syntax for exploiting parameter blocks:\n\n```hlsl\nstruct ViewParams\n{\n\tfloat3 cameraPos;\n\tfloat4x4 viewProj;\n\tTextureCube envMap;\n};\n\nParameterBlock<ViewParams> gViewParams;\n```\n\nIn this example, the fields of `gViewParams` will be assigned to registers/bindings in a way that supports allocating them into a single parameter block.\nFor example, when generating GLSL for Vulkan, the Slang compiler will generate a single `uniform` block (for `cameraPos` and `viewProj`) and a global `textureCube` for `envMap`, both decorated with the same `layout(set = ...)`.\n\n\n### Interfaces\n\nSlang supports declaring `interface`s that user-defined `struct` types can implement.\nFor example, here is a simple interface for light sources:\n\n```hlsl\n// light.slang\n\nstruct LightSample { float3 intensity; float3 direction; };\n\ninterface ILight\n{\n\tLightSample sample(float3 position);\n}\n```\n\nWe can now define a simple user type that \"conforms to\" (implements) the `ILight` interface:\n\n```hlsl\n// point-light.slang\n\nimport light;\n\nstruct PointLight : ILight\n{\n\tfloat3 position;\n\tfloat3 intensity;\n\n\tLightSample sample(float3 hitPos)\n\t{\n\t\tfloat3 delta = hitPos - position;\n\t\tfloat distance = length(delta);\n\n\t\tLightSample sample;\n\t\tsample.direction = delta / distance;\n\t\tsample.intensity = intensity * falloff(distance);\n\t\treturn sample;\n\t}\n}\n```\n\n### Generics\n\nSlang supports *generic* declarations, using the commong angle-brack (`<>`) syntax from languages like C#, Java, etc.\nFor example, here is a generic function that works with any type of light:\n\n```hlsl\n// diffuse.slang\nimport light;\n\nfloat4 computeDiffuse<L : ILight>( float4 albedo, float3 P, float3 N, L light )\n{\n\tLightSample sample = light.sample(P);\n\tfloat nDotL = max(0, dot(N, sample.direction));\n\treturn albedo * nDotL;\n}\n```\n\nThe `computeDiffuse` function works with any type `L` that implements the `ILight` interface.\nUnlike with C++ templates, the `computeDiffuse` function can be compiled and type-checked once (you won't suddenly get unexpected error messages when plugging in a new type).\n\n#### Global-Scope Generic Parameters\n\nPutting generic parameter directly on functions is helpful, but in many cases existing HLSL shaders declare their parameters at global scope.\nFor example, we might have a shader that uses a global declaration of material parameters:\n\n```hlsl\nMaterial gMaterial;\n```\n\nIn order to allow such a shader to be converted to use a generic parameter for the material type (to allow for specialization), Slang supports declaring type parameters at the global scope:\n\n```hlsl\ntype_param M : IMaterial;\nM gMaterial;\n```\n\nConceptually, you can think of this syntax as wrapping your entire shader program in a generic with parameter `<M : IMaterial>`.\nThis isn't beautiful syntax, but it may help when incrementally porting an existing HLSL codebase to use Slang's features.\n\n### Associated Types\n\nSometimes it is difficult to define an interface because each type that implements it might need to make its own choice about some intermediate type.\nAs a concrete example, suppose we want to define an interface `IMaterial` for material surface shaders, where each material might use its own BRDF.\nWe want to support evaluating the *pattern* of the surface separate from the reflectance function.\n\n```hlsl\n// A reflectance function\ninterface IBRDF\n{\n\tfloat3 eval(float3 wi, float3 wo);\n}\nstruct DisneyBRDF : IBRDF { ... };\nstruct KajiyaKay : IBRDF { ... };\n\n// a surface pattern\ninterface IMaterial\n{\n\t??? evalPattern(float3 position, float2 uv);\n}\n```\n\nWhat is the type `???` that `evalPattern` should return? We know that it needs to be a type that supports `IBRDF`, but *which* type?\nOne material might want to use `DisneyBRDF` while another wants to use `KajiyaKay`.\n\nThe solution in Slang, as in modern languages like Swift and Rust, is to use *associated types* to express the depdence of the BRDF type on the material type:\n\n```hlsl\ninterface IMaterial\n{\n\tassociatedtype B : IBRDF;\n\tB evalPattern(float3 position, float2 uv);\n}\n\nstruct MyCoolMaterial : IMaterial\n{\n\ttypedef DisneyBRDF B;\n\tB evalPattern(float3 position, float2 uv)\n\t{ ... }\n}\n```\n\nAssociated types are an advanced concept, and we only recommend using them when they are needed to define a usable interface.\n\n\nFuture Extensions\n-----------------\n\n### Implicit Generics Syntax\n\nThe syntax for generics and interfaces in Slang is currently explicit, but verbose:\n\n```hlsl\nfloat4 computeDiffuse<L : ILight>( L light, ... )\n{ ... }\n```\n\nAs a future change, we would like to allow using an interface like `ILight` as an ordinary parameter type:\n\n```hlsl\nfloat4 computeDiffuse( ILight light, ... )\n{ ... }\n```\n\nThis simpler syntax would act like \"syntactic sugar\" for the existing explicit generics syntax, so it would retain all of the important performance properties.\n\n### Returning a Value of Interface Type\n\nWhile the above dealt with using an interface as a parameter type, we would eventually like to support using an interface as the *return* type of a function:\n\n```hlsl\nILight getALightSource(Scene scene) { ... }\n```\n\nImplementing this case efficiently is more challenging. In most cases, an associated type can be used instead when an interface return type would be desired.\n\n\nNot Supported\n-------------\n\nSome features of the current HLSL language are not supported, but probably will be given enough time/resources:\n\n* Local variables of texture/sampler type (or that contain these)\n* Matrix swizzles\n* Explicit `packoffset` annotations on members of `cbuffer`s\n\nSome things from HLSL are *not* planned to be supported, unless there is significant outcry from users:\n\n* Pre-D3D10/11 syntax and operations\n* The \"effect\" system, and the related `<>` annotation syntax\n* Explicit `register` bindings on textures/samplers nested in `cbuffer`s\n* Any further work towards making HLSL a subset of C++ (simply because implementing a full C++ compiler is way out of scope for the Slang project)\n"
  },
  {
    "path": "Source/External/slang/docs/layout.md",
    "content": "Parameter Layout Rules\n======================\n\nAn important goal of the Slang project is that the rules for how shader parameters get assigned to `register`s/`binding`s is completely deterministic, so that users can rely on the compiler's behavior.\nThis document will attempt to explain the rules that Slang employs at a high level.\nEventually it might evolve into a formal specification of the expected behavior.\n\nGuarantees\n----------\n\nThe whole point of having a deterministic layout approach is the guarantees that it gives to users, so we will start by explicitly stating the guarantees that users can rely upon:\n\n* A single top-level shader parameter will always occupy a contiguous range of bindings/registers for each resource type it consumes (e.g., a contiguous range of `t` registers, a contiguous range of bytes in a `cbuffer`, etc.).\n\n* The amount of resources a parameter consumes depends only on its type, and top-level context in which it appears (e.g., is it in a `cbuffer`? an entry-point varying parameter? etc.).\n\n* A shader parameter that is declared the same way in two different programs will get the same *amount* of resources (registers/bytes) allocated for it in both programs, but it might get a different starting offset/register.\n\n* Changing the bodies of functions in shader code cannot change the layout of shader parameters. In particular, just because a shader parameter is \"dead\" does not mean it gets eliminated.\n\n* If the user doesn't use explicit `register`/`layout` modifiers to bind parameters, then each module will get a contiguous range of bindings, and the overall program will always use a contiguous range starting from zero for each resource type.\n\nOverview of the Layout Algorithm\n--------------------------------\n\nLayout is applied to a Slang *compile request* which comprises one or more *translation units* of user code, and zero or more `import`ed modules.\nThe compile request also specifies zero or more *entry points* to be compiled, where each entry point identifies a function and a profile to use.\n\nLayout is always done with respect to a chosen *target*, and different targets might compute the resource usage for types differently, or apply different alignment.\nWithin a single target there may also be different layout rules (e.g., the difference between GLSL `std140` and `std430`).\n\nLayout proceeds in four main phases:\n\n1. Establish a global ordering on shader parameters\n2. Compute the resource requirements of each shader parameter\n3. Process shader parameters with fixed binding modifiers\n4. Allocate bindings to parameter without fixed binding modifiers\n\nOrdering (and Collapsing) Shader Parameters\n-------------------------------------------\n\nShader parameters from the user's code always precede shader parameters from imported modules.\nThe order of parameters in the user's code is derived by \"walking\" through the code as follows:\n\n* Walk through each translation unit in the order they were added via API (or the order they were listed on the command line)\n\n* Walk through each source file of a translation unit in the order they were added/listed\n\n* Walk through global-scope shader paramter declarations (global variables, `cbuffer`s, etc.) in the order they are listed in the (preprocessed) file.\n\n* After all global parameters for a translation unit have been walked, walk through any entry points in the translation unit.\n\n* When walking through an entry point, walk through all of its function parameters (both uniforms and varyings) in order, and then walk the function result as a varying output parameter.\n\nWhen dealing with global-scope parameters in the user's code, it is possible for the \"same\" parameter to appear in multiple translation units.\nAny two global shader parameters in user code with the same name are assumed to represent the same parameter, and will only be included in the global order at the first location where they are seen.\nIt is an error for the different declarations to have a mismatch in type, or conflicting explicit bindings.\n\nParameters from `import`ed modules are enumerated after the user code, using the order in which modules were first `import`ed.\nThe order of parameters within each module is the same as when the module was compiled, which matches the ordering given above.\n\nComputing Resource Requirements\n-------------------------------\n\nEach shader parameter computes its resource requirements based on its type, and how it is declared.\n\n* Global-scope parameters, entry point `uniform` parameters, and `cbuffer` decalrations all use the \"default\" layout rules\n\n* Entry point non-`uniform` parameters use \"varying\" layout rules, either input or output\n\n* A few other special case rules exist (e.g., for laying out the elements of a `StructuredBuffer`), but most users will not need to worry about these\n\nNote that the \"default\" rules are different for D3D and GL/Vulkan targets, because they have slightly different packing behavior.\n\n### Plain Old Data\n\nUnder the default rules simple scalar types (`bool`, `int`, `float`, etc.) are laid out as \"uniform\" data (that is, bytes of ordinary memory).\nIn most cases, the size matches the expected data type size (although be aware that most targets treat `bool` as a synonym for `int`) and the alignment is the same as the size.\n\n### Vectors\n\nVectors are laid out as N sequential scalars.\nUnder HLSL rules, a vector has the same alignment as its scalar type.\nUnder GLSL `std140` rules, a vector has an alignment that is its size rounded up to the next power of two (so a `float3` has `float4` alignment).\n\n### Opaque Types\n\n\"Opaque\" types include resource/sampler types like `Texture2D` and `SamplerState`.\nThese consume a single \"slot\" of the appropriate category for the chosen API.\n\nNote that when compiling for D3D, a `Texture2D` and a `SamplerState` will consume different resources (`t` and `s` registers, respectively), but when compiling for Vulkan, they both consume the same resource (\"descriptor table slot\").\n\nOpaque types currently all have an alignment of one.\n\n### Structures\n\nA structure is laid out by initializing a counter for each resource type, and then processing fields sequential (in declaration order):\n\n* Compute resource usage for the field's type\n\n* Adjust counters based on the alignment of the field for each resource type where it has non-zero usage\n\n* Assign an offset to the field for each resource type where it has non-zero usage\n\n* Add the resource usage of the field to the counters\n\n\nAn important wrinkle is that when doing layout for HLSL, we must ensure that if a field with uniform data that is smaller than 16 bytes would straddle a 16-byte boundary, we advance to the next 16-byte aligned offset.\n\nThe overall alignment of a `struct` is the maximum alignment of its fields or the default alignment (if it is larger).\nThe default alignment is 16 for both D3D and Vulkan targets.\n\nThe final resource usage of a `struct` is rounded up to a multiple of the alignment for each resource type. Note that we allow a `struct` to consume zero bytes of uniform storage.\n\nIt is important to note that a `struct` type can use resources of many different kinds, so in general we cannot talk about the \"size\" of a type, but only its size for a particular kind of resource (uniform bytes, texture registers, etc.).\n\n### Sized Arrays\n\nFor uniform data, the size of the element type is rounded up to the target-specific minimum (e.g., 16 for D3D and Vulkan constant buffers) to arrive at the *stride* of the array. The total size of the array is then the stride times the element count.\n\nFor opaque resource types, the D3D case simply takes the stride to be the number of registers consumed by each element, and multiplies this by the element count.\n\nFor Vulkan, an array of resources uses only a single `binding`, so that the stride is always zero for these resource kinds, and the resource usage of an array is the same as its element type.\n\n### Unsized Arrays\n\nThe uniform part of an unsized array has the same stride as for the sized case, but an effectively infinite size.\n\nFor register/binding resource usage, a Vulkan unsized array is just like a sized one, while a D3D array will consume a full register *space* instead of individual registers.\n\n### Constant Buffers\n\nTo determine the resource usage of a constant buffer (either a `cbuffer { ... }` declaration or a `ConstantBuffer<T>`) we look at the resource usage of its element type.\n\nIf the element uses any uniform data, the constant buffer will use at least one constant-buffer register (or whatever the target-specific resource is).\nIf the element uses any non-uniform data, that usage will be added to that of the constant buffer.\n\n### Parameter Blocks\n\nA parameter block is similar to a constant buffer.\nIf the element type uses any uniform data, we compute resource usage for a constant buffer.\nWe then add in any non-uniform resource usage for the element types.\n\nIf the target requires use of register spaces (e.g., for Vulkan), then a parameter block uses a single register space; otherwise it exposes the resource usage of its element type directly.\n\nProcessing Explicit Binding Modifiers\n-------------------------------------\n\nIf the user put an explicit binding modifier on a parameter, and that modifier applies to the current target, then we use it and \"reserve\" space in the overall binding range.\n\nTraditional HLSL `register` modifiers only apply for D3D targets.\nSlang currently allows GLSL-style `layout(binding =...)` modifiers to be attached to shader parameters, and will use those modifiers for GL/Vulkan targets.\n\nIf two parameters reserve overlapping ranges, we currently issue an error.\nThis may be downgraded to a warning for targets that support overlapping ranges.\n\nAllocating Bindings to Parameters\n---------------------------------\n\nOnce ranges have been reserved for parameters with explicit bindings, the compiler goes through all parameters again, in the global order and assigns them bindings based on their resource requirements.\n\nFor each resource type used by a parameter, it is allocated the first contiguous range of resources of that type that have not been reserved.\n\nSplitting of Arrays\n-------------------\n\nIn order to support `struct` types that mix uniform and non-uniform data, the Slang compiler always \"splits\" these types.\nFor example, given:\n\n```hlsl\nstruct LightInfo { float3 pos; Texture2D shadowMap; };\n\nLightInfo gLight;\n```\n\nSlang will generate code like:\n\n```hlsl\nfloat3 gLight_pos;\nTexture2D gLight_shadowMap;\n```\n\nIn a simple case like the above, this doesn't affect layout at all, but once arrays get involved, the layout can be more complicated. Consider this case:\n\n```hlsl\nstruct Pair { Texture2D a; Texture2D b; };\nPair gPairs[8];\n```\n\nThe output from the splitting step is equivalent to:\n\n```hlsl\nTexture2D gPairs_a[8];\nTexture2D gPairs_b[8];\n```\n\nWhile this transformation is critical for having a type layout algorithm that applies across all APIs (and also it is pretty much required to work around various bugs in downstream compilers), it has the important down-side that the value `gPairs[0]` does not occupy a contiguous range of registers (although the top-level shader parameter `gPairs` *does*).\n\nThe Slang reflection API will correctly report the information about this situation:\n\n* The \"stride\" of the `gPairs` array will be reported as one, because `gPairs[n+1].a` is always one register after `gPairs[n].a`.\n\n* The offset of the `gPairs.b` field will be reported as 8, because `gPairs[0].b` will be 8 registers after the starting register for `gPairs`.\n\nThe Slang API tries to provide the best information it can in this case, but it is still important for users who mix arrays and complex `struct` types to know how the compiler will lay them out.\n\nGenerics\n--------\n\nGeneric type parameters complicate these layout rules.\nFor example, we cannot compute the exact resource requirements for a `vector<T,3>` without knowing what the type `T` is.\n\nWhen computing layouts for fully specialized types or programs, no special considerations are needed: the rules as described in this document still apply.\nOne important consequence to understand is that given a type like:\n\n```hlsl\nstruct MyStuff<T>\n{\n\tint a;\n\tT b;\n\tint c;\n}\n```\n\nthe offset computed for the `c` field depends on the concrete type that gets plugged in for `T`.\nWe think this is the least surprising behavior for programmers who might be familiar with things like C++ template specialization.\n\nIn cases where confusion about a field like `c` getting different offsets in different specializations is a concern, users are encouraged to declare types so that all non-generic-dependent fields come before generic-dependent ones.\n"
  },
  {
    "path": "Source/External/slang/docs/linking.md",
    "content": "Slang Linking\n=============\n\nThe Slang feature around libraries and linking are a *work in progress*. Future versions of Slang are likely to change the API and binary compatibility. Also note that currently reflection is mainly unsupported. \n\nIn many languages it is possible to compile source files into binaries such as libraries and object files. Later these files can be combined perhaps with other source files to produce a result such as an executable. Slang now has experimental support for such a feature. \n\nTo make such a feature work we need a few abilities\n\n* To create a library from source \n* A way for symbols to be exported and imported\n* Linkage - ability to combine source/libraries to produce things (such as other libraries, executables, etc)\n* A way to specify libraries to be used in linkage\n\n\nBinding\n-------\n\nDue to how the feature currently works, if a library contains any kind of binding (implicit or explicit) it should be considered platform specific. When linking with libraries, the libraries will not supply any reflection, other than minimal entry point information. Any source compiled and linked against does follow normal Slang rules in terms of implicit binding assignments and reflection.  \n\nIn practice this means that libraries either have to have no binding or manual binding. If any library has manual binding, this binding must be ensured to not clash with either implict or explicit binding in the source or other linked libraries. It is not guaranteed that Slang or downstream compilers will report binding clashes. \n\nIf platform independent libraries are linked against source compilation then appropriate reflection and normal Slang implicit binding rules apply.\n\nLibraries\n---------\n\nA library can be created from source from the Slang command line with the `-o` option naming the output file. The filename currently requires a `slang-lib` or `slang-module` extension. This extension will mean the library will be stored as serialized Slang IR. The option `-no-codegen` is also typically specified because we don't want to generate any *target* code, such as dxil, spir-v and so forth when producing a library, just the Slang IR. \n\nFor example\n\n```\nslangc -no-codegen tests/serialization/extern/module-a.slang -o tests/serialization/extern/module-a.slang-lib\n```\n\nFrom the slang API we need to indicate the container format and to disable target code generation \n\n```\n    SlangCompileRequest* compileRequest = ...;\n    SlangCompileFlags slangCompileFlags = ...;\n    \n    slangCompileFlags |= SLANG_COMPILE_FLAG_NO_CODEGEN;\n\n    spSetOutputContainerFormat(compileRequest, SLANG_CONTAINER_FORMAT_SLANG_MODULE);\n```\n\nWhen the compilation is completed the resulting serialized IR code can be accessed via \n\n```\n// To get the contents as a blob - whose scope can be maintained by the application\n\n    {\n        ComPtr<ISlangBlob> blob;\n        if (SLANG_SUCCEEDED(spGetContainerCode(compileRequest, blob.writeRef())))\n        {\n            // Do something with the blob\n        }\n    }\n\n    // To directly get the contents, will only remain valid as long as compileRequest stays in scope\n    // and without subsequent calls to spCompile on the request\n    {\n        size_t size;\n        const void* data = spGetCompileRequestCode(compileRequest, size);\n    }\n```\n\nLibraries can contain entry points. It is necessary though that the entry point is specified during the compilation producing the library. This can be achieved by specifying a function as an entry point via the API or command line through the normal mechanisms. \n\nEntry points can also be specified in source via the `[shader()]` attribute. For example\n\n```\n[shader(\"compute\")]\nvoid computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)\n{\n    // ... \n}\n```\n\nSlang libraries are stored as serialized Slang IR. That Slang IR currently maintains no forward or backward compatibility, and a new version of Slang may either produce incompatible IR, or be unable to consume previous versions IR.\n\nBy default Slang stores serialized Slang IR in a compressed `lite` format. It can also be stored without any addition compression. These options can be specified via the command line via\n\n```\n-ir-compression lite\n-ir-compression none\n```\n\nThey are also available via the API through the `spProcessCommandLineArguments` function. \n\nNote that Slang can consume and process either `lite` or `none` styles transparently. Also mixing compressed libraries with uncompressed libraries also works. \n\nSymbols\n-------\n\nLinkage is the process of combining of libraries and source to produce something. The mechanism used with Slang, is that items that are going to be imported or exported are named. As the Slang language supports function overloading and generics, it is not possible to just use a function name or a type name to uniquely identify an item. Thus exported and imported names are 'mangled' to include this additional information. This is not unlike how C++ produces mangled names for symbols for similar reasons.\n\nSymbols within a module are additionally uniquely marked with the name of the module, and thus the module name becomes part of the mangled name. This has implications for includes. For example say we have two modules, and they both #include a header file that contains a function. That function will appear as two separate functions - one defined in each module, because a #include is a textual the function will be defined once in each module and with each module name.\n\nBy default Slang will provide linkage symbols for all global symbols - types or functions, including declarations. In the future this is likely to change with declarations *not* being exported by default. \n\nTo mark a declaration as having it's definition defined elsewhere outside the current module, the `[__extern]` attribute can be used. For example \n\n```\n[__extern] Thing makeThing(int a, int b);\n``` \n\nWith types the `[__extern]` attribute can also be used. For the moment though a type declaration that is externed still needs to be a type definition. Therefore to declare a type to be imported from elsewhere we actually have to write\n\n```\n[__extern] struct Thing {};\n```\n\nWhich looks a little like a definition of `Thing` but because of the `[__extern]` it actually means that `Thing` is defined elsewhere. \n\nThe mechanism for making other symbols available from a library and/or source within Slang is through `import`. Currently though `import` does not support importing of libraries. \n\nThis means that a work around (aka hack) is needed so linkage works with a library. The short term fix, until importing of libraries is available, is to allow overriding of the name of the module - typically so that all symbols appear in the same module name. For example say we have two modules `module-a` and `module-b`, if `module-a` and `module-b` use the same module name they will be able to access one anothers symbols during linkage. \n\nSpecifying the module name can be achieve on the command line with the `-module-name` option as in\n\n```\nslangc -module-name somename -no-codegen tests/serialization/extern/module-a.slang -o tests/serialization/extern/module-a.slang-lib\n```\n\nFrom the API the module name can be specified via \n\n```\nspSetDefaultModuleName(compileRequest, \"somename\");\n```\n\nThe `[__extern]` attribute and the use of module names, are temporary functionality until more complete support for libraries and linkage is implemented. \n\nLinkage\n-------\n\nThe linkage process used in Slang is purposefully fairly straight forwards. When linkage occurs all items with linkage have a identifying mangled name. That for some mangled names there could be multiple definitions - for example a declaration of a function and a definition of that function. If there are multiple definitions, linking aims to determine the one that is 'best' which is then used. A definition is better than a declaration. And a definition that is specific to the current target is taken as better than some other definition. \n\nIf there are multiple identical definitions, or definitions where it cannot be determed if one is better than another then one is taken at effectively random. This therefore assumes that if there are multiple definitions that they are in effect the same. \n\nIf after the linkage process there are declarations that are used, without a definition, then linkage will fail with an unfound symbol.\n\nSpecifying Libraries\n--------------------\n  \nWhen compiling there needs to be a mechanism to specify library or libraries that will be used during linkage. From the command line this can be achieved with the `-r` option. For example...\n\n```\nslangc -target dxil -profile sm_6_3 computeMain.slang -entry computeMain -stage compute -r module-a.slang-lib -o linked.dxil\n```\n\nNote that multiple `-r` options can be specified on a command line to reference multiple libraries. \n\nFrom the API use\n\n```\nSLANG_API SlangResult spAddLibraryReference(\n    SlangCompileRequest*    request,\n    const void* libData,\n    size_t libDataSize)\n```\n    \nThe libData/libDataSize is the binary data that was was either loaded from a `slang-lib` file or was the result of a compilation of a module and the library contents retrieved via `spGetContainerCode` or `spGetCompileRequestCode`. \n\nAs with -r command line option, multiple libraries can be added to a SlangCompileRequest and all will be searched for relevant symbolds during linking. \n\nReflection\n----------\n\nIn general reflection is *not* available post linkage currently. A subset of functionality is available though including\n\n* spGetReflection\n* spReflection_getEntryPointCount\n* spReflection_getEntryPointByIndex\n* spReflectionEntryPoint_getName\n\nThat other reflection functions currently either do not work or may *crash*. \n\nOther issues\n------------\n\nIn languages such as C++, if I want to define a struct on the stack I need it's definition\n\n```\nstruct Thing;\n\nint main()\n{\n    // Won't compile we need the *definition* not just a declaration\n    Thing thing;\n    return 0;\n}\n```\n\nIt does not matter that Thing might be defined in another library or object file. For compilation of main, we have to have the definition of Thing. \n\nIn Slang and libraries this is not the case. If I have a file `module-a.slang`\n \n```\nstruct Thing\n{\n    int a; \n    float b;\n};\n```\n\nAnd then I compile another file and include the library that contains Thing I *can* just use the Thing type \n\n```\n\n// I have to say that Thing is externally defined\n[__extern] struct Thing {};\n\nvoid computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)\n{\n    // This is fine in Slang - as long is Thing *is* defined in a referenced library\n    Thing thing;\n    // ... \n}\n```\n\nThis is possible because when linkage occurs the code is actually *Slang IR*, and Slang IR contains the information necessary for the use of the Thing type. \n\nIt also worth noting that if the `-obfuscate` feature is used, all libraries and source must also have `-obfuscate` enabled, for linking to work. \n\n\nExamples\n--------\n\nExamples of compiling of libraries and linking with them can be found within tests/serialization. "
  },
  {
    "path": "Source/External/slang/docs/nvapi-support.md",
    "content": "NVAPI Support\n=============\n\nSlang provides support for [NVAPI](https://developer.nvidia.com/nvapi) in several ways\n\n* Slang allows the use of NVAPI directly, by the inclusion of the `#include \"nvHLSLExtns.h\"` header in your Slang code. Doing so will make all the NVAPI functions directly available and usable within your Slang source code.\n* NVAPI is used to provide features implicitly for certain targets. For example support for [RWByteAddressBuffer atomics](target-compatibility.md) on HLSL based targets is supported currently via NVAPI.\n* Direct and implicit NVAPI usage can be freely mixed. \n\nDirect usage of NVAPI\n=====================\n\nDirect usage of NVAPI just requires the inclusion of the appropriate NVAPI header, typically with `#include \"nvHLSLExtns.h` within your Slang source. As is required by NVAPI before the `#include` it is necessary to specify the slot and perhaps space usage. For example a typical direct NVAPI usage inside a Slang source file might contain something like...\n\n```\n#define NV_SHADER_EXTN_SLOT u0 \n#include \"nvHLSLExtns.h\"\n```\n\nIn order for the include to work, it is necessary for the include path to include the folder that contains the nvHLSLExtns.h and associated headers.\n\nImplicit usage of NVAPI\n=======================\n\nIt is convenient and powerful to be able to directly use NVAPI calls, but will only work on such targets that support the mechansism, even if there is a way to support the functionality some other way.\n\nSlang provides some cross platform features on HLSL based targets that are implemented via NVAPI. For example RWByteAddressBuffer atomics are supported on Vulkan, DX12 and CUDA. On DX12 they are made available via NVAPI, whilst CUDA and Vulkan have direct support. When compiling Slang code that uses RWByteAddressBuffer atomics Slang will emit HLSL code that use NVAPI. In order for the downstream compiler to be able to compile this HLSL it must be able to include the NVAPI header `nvHLSLExtns.h`. \n\nIt worth discussing briefly how this mechanism works. Slang has a 'prelude' mechanism for different source targets. The prelude is a piece of text that is inserted before the source that is output from compiling the input Slang source code. There is a default prelude for HLSL that is something like \n\n```\n#ifdef SLANG_HLSL_ENABLE_NVAPI\n#include \"nvHLSLExtns.h\"\n#endif\n```\n\nIf there are any calls to NVAPI implicitly from Slang source, then the following is emitted before the prelude\n\n```\n#define SLANG_HLSL_ENABLE_NVAPI 1\n#define NV_SHADER_EXTN_SLOT u0\n#define NV_SHADER_EXTN_REGISTER_SPACE space0\n```\n\nThus causing the prelude to include nvHLSLExtns.h, and specifying the slot and potentially the space as is required for inclusion of nvHLSLExtns.h.\n\nThe actual values for the slot and optionally the space, are found by Slang examining the values of those values at the end of preprocessing input Slang source files. \n\nThis means that if you compile Slang source that has implicit use NVAPI, the slot and optionally the space must be defined. This can be achieved with a command line -D, throught the API or through having suitable `#define`s in the Slang source code.\n\nIt is worth noting if you *replace* the default HLSL prelude, and use NVAPI then it will be necessary to have something like the default HLSL prelude part of your custom prelude.\n\nDownstream Compiler Include\n---------------------------\n\nThere is a subtle detail that is perhaps worth noting here around the downstream compiler and `#include`s. When Slang outputs HLSL it typically does not contain any `#include`, because all of the `#include` in the original source code have been handled by Slang. Slang then outputs everything required to compile to the downstream compiler *without* any `#include`. When NVAPI is used explicitly this is still the case - the NVAPI headers are consumed by Slang, and then Slang will output HLSL that does not contain any `#include`.\n\nThe astute reader may have noticed that the default Slang HLSL prelude *does* contain an include, which is enabled via SLANG_HLSL_ENABLE_NVAPI macro which Slang will set with implicit NVAPI use. \n\n```\n#ifdef SLANG_HLSL_ENABLE_NVAPI\n#include \"nvHLSLExtns.h\"\n#endif\n```\n\nThis means that the *downstream* compiler (such as DXC and FXC) must be able to handle this include. Include paths can be specified for downstream compilers via the [-X mechanism](command-line-slangc.md#downstream-arguments). So for example...\n\n```\n-Xfxc -IpathTo/nvapi -Xdxc -IpathTo/nvapi\n```\n\nIn the explicit scenario where `nvHLSLExtns.h` is included in Slang source, the include path must be specified in Slang through the regular mechanisms. \n\nIn a scenario with both implicit and explicit use, both Slang *and* the downstream compiler need to have a suitable path specified. Things can be more complicated if there is mixed implicit/explicit NVAPI usage and in the Slang source the include path is set up such that NVAPI is included with \n\n```\n#include \"nvapi/nvHLSLExtns.h\"\n```\n\nSince Slang and the downstream compilers can specify different include paths, the downstream compiler include path can be such that `#include \"nvHLSLExtns.h\"` works with the default prelude.\n\nAnother way of working around this issue is to alter the prelude for downstream compilers such that it contains an absolute path for the `#include`. This is the mechanism that is currently used with the Slang test infrastructure. \n\nLinks\n-----\n\nMore details on how this works can be found in the following PR\n\n* [Simplify workflow when using NVAPI #1556](https://github.com/shader-slang/slang/pull/1556)\n"
  },
  {
    "path": "Source/External/slang/docs/repro.md",
    "content": "Slang Compilation Reproduction\n==============================\n\nSlang has both API and command line support for reproducing compilations, so called 'repro' functionality.\n\nOne use of the feature is if a compilation fails, or produces an unexpected or wrong result, it provides a simple to use mechanism where the compilation can be repeated or 'reproduced', most often on another machine. Instead of having to describe all the options, and make sure all of the files that are used are copied, and in such a way that it repeats the result, all that is required is for the compilation to be run on the host machine with repro capture enabled, and then that 'repro' used for a compilation on the test machine. There are also some mechanisms where the contents of the orginal compilation can be altered.\n\nThe actual data saved is the contents of the SlangCompileReqest. Currently no state is saved from the SlangSession. Saving and loading a SlangCompileRequest into a new SlangCompileRequest should provide two SlangCompileRequests with the same state, and with the second compile request having access to all the files contents the original request had directly in memory. \n\nThere are a few command line options\n\n* `-dump-repro [filename]` dumps the compilations state (ie post attempting to compile) to the file specified afterwards\n* `-extract-repro [filename]` extracts the contents of the repro file. The contained files are placed in a directory with a name, the same as the repro file minus the extension. Also contains a 'manifest'.\n* `-load-repro [filename]` loads the repro and compiles using it's options. Note this must be the last arg on the command line.\n* `-dump-repro-on-error` if a compilation fails will attempt to save a repro (using a filename generated from first source filename)\n* `-repro-file-system [filename]` makes the repros file contents appear as the file system during a compilation. Does not set any compilation options.\n* `-load-repro-directory [directory]` compiles all of the .slang-repro files found in `directory`\n\nThe `manifest` made available via `-extract-repro` provides some very useful information\n\n* Provides an approximation of the command line that will produce the same compilation under [compile-line]\n* A list of all the unique files held in the repro [files]. It specified their 'unique name' (as used to identify in the repro) and their unique identifier as used by the file system.\n* A list of how paths map to unique files. Listed as the path used to access, followed by the unique name used in the repro\n\nFirst it is worth just describing what is required to reproduce a compilation. Most straightforwardly the options setup for the compilation need to be stored. This would include any flags, and defines, include paths, entry points, input filenames and so forth. Also needed will be the contents of any files that were specified. This might be files on the file system, but could also be 'files' specified as strings through the slang API. Lastly we need any files that were referenced as part of the compilation - this could be include files, or module source files and so forth. All of this information is bundled up together into a file that can then later be loaded and compiled. This is broadly speaking all of the data that is stored within a repro file. \n\nIn order to capture a complete repro file typically a compilation has to be attempted. The state before compilation can be recorded (through the API for example), but it may not be enough to repeat a compilation, as files referenced by the compilation would not yet have been accessed. The repro feature records all of these accesses and contents of such files such that compilation can either be completed or at least to the same point as was reached on the host machine. \n\nOne of the more subtle issues around reproducing a compilation is around filenames. Using the API, a client can specify source files without names, or multiple files with the same name. If files are loaded via `ISlangFileSystem`, they are typically part of a hiearchical file system. This could mean they are referenced relatively. This means there can be distinct files with the same name but differenciated by directory. The files may not easily be reconstructed back into a similar hieararchical file system - as depending on the include paths (or perhaps other mechanisms) the 'files' and their contents could be arranged in a manner very hard to replicate. To work around this the repro feature does not attempt to replicate a hierarchical file system. Instead it gives every file a unique name based on their original name. If there are multiple files with the same name it will 'uniquify' them by appending an index. Doing so means that the contents of the file system can just be held as a flat collection of files. This is not enough to enable repeating the compilation though, as we now need Slang to know which files to reference when they are requested, as they are now no longer part of a hierarchical file system and their names may have been altered. To achieve this the repro functionality stores off a map of all path requests to their contents (or lack there of). Doing so means that the file system still appears to Slang as it did in the original compilation, even with all the files being actually stored using the simpler 'flat' arrangement. \n\nThis means that when a repro is 'extracted' it does so to a directory which holds the files with their unique 'flat' names. The name of the directory is the name of the repro file without it's extension, or if it has no extension, with the postfix '-files'. This directory will be referered to from now on as the `repro directory`.\n\nWhen a repro is loaded, before files are loaded from the repro itself, they will first be looked for via their unique names in the `repro directory`. If they are not there the contents of the repro file will be used. If they are there, their contents will be used instead of the contents in the repro. This provides a simple mechanism to be able to alter the source in a repro. The steps more concretely would be...\n\n1) First extract the repro (say with `-extract-repro`)\n2) Go to the `repro directory` and edit files that you wish to change. You can also just delete files that do not need changing, as they will be loaded from the repro.\n3) Load the repro - it will now load any files requested from the `repro directory`\n\nNow you might want to change the compilation options. Using -load-repro it will compile with the options as given. It is not possible to change those options as part of -load-repro. If you want to change the compilation options (and files), you can use -extract-repro, and look at the manifest which will list a command line that will typically repeat the compilation. Now you can just attach the repro as a file system, and set the command line options as appropriate, based on the command line listed in the manifest. Note! If there is a fairly complex directory hierarchy, it may be necessary to specify the input sources paths *as if* they are held on the original files system. You can see how these map in the manifest. \n\nNote that currently is is disabled to access any new source files - they will be determined as `not found`. This behaviour could be changed such that the regular file system was used, or the ISlangFilesystem set on the API is used as a fallback. \n\nThere currently isn't a mechanism to alter the options of a repro from the command line (other than altering the contents of the source). The reason for this is because of how command lines are processed currently in Slang. A future update could enable specifying a repro and then altering the command line options used. It can be achieved through the API though. Once the repro is loaded via the `spLoadRepro` function, options can be changed as normal. The two major places where option alteration may have surprising behavior are... \n\n1) Altering the include paths - unless this may break the mechanism used to map paths to files stored in the repro file\n2) Altering the ISlangFileSystem. That to make the contents of the file system appear to be that of the repro, slang uses a ISlangFileSystemExt that uses the contents of the repro file and/or the `repro directory`. If you replace the file system this mechanism will no longer work. \n\nThere are currently several API calls for using the repro functionality \n\n```\nSLANG_API SlangResult spEnableReproCapture(\n        SlangCompileRequest* request);\n    \nSLANG_API SlangResult spLoadRepro(\n        SlangCompileRequest* request,\n        ISlangFileSystem* fileSystem,\n        const void* data,\n        size_t size);\n\nSLANG_API SlangResult spSaveRepro(\n        SlangCompileRequest* request,\n        ISlangBlob** outBlob\n    );\n    \nSLANG_API SlangResult spExtractRepro(\n    SlangSession* session, \n    const void* reproData, \n    size_t reproDataSize, \n    ISlangFileSystemExt* fileSystem);    \n\nSLANG_API SlangResult spLoadReproAsFileSystem(\n    SlangSession* session,\n    const void* reproData,\n    size_t reproDataSize,\n    ISlangFileSystem* replaceFileSystem,\n    ISlangFileSystemExt** outFileSystem);\n   \n```\n\nThe fileSystem parameter passed to `spLoadRepro` provides the mechanism for client code to replace the files that are held within the repro. NOTE! That the files will be loaded from this file system with their `unique names` as if they are part of the flat file system. If an attempt to load a file fails, the file within the repro is used. That `spLoadRepro` is typically performed on a new 'unused' SlangCompileRequest. After a call to `spLoadRepro` normal functions to alter the state of the SlangCompileRequest are available. \n\nThe function `spEnableReproCapture` should be set after any ISlangFileSystem has been set (if any), but before any compilation. It ensures that everything that the ISlangFileSystem accesses will be correctly recorded. Note that if a ISlangFileSystem/ISlangFileSystemExt isn't explicitly set (ie the default is used), then a request will automatically be set up to record everything appropriate and a call to this function isn't strictly required.  \n    \nThe function `spExtractRepro` allows for extracting the files used in a request (along with the associated manifest). They files and manifest are stored under the 'unique names' in the root of the user provided ISlangFileSystemExt.     \n    \nThe function `spLoadReproAsFileSystem` creates a file system that can access the contents of the repro with the same paths that were used on the originating system. The ISlangFileSystemExt produced can be set on a request and used for compilation.    \n    \nRepro files are currently stored in a binary format. This format is sensitive to changes in the API, as well as internal state within a SlangCompileRequest. This means that the functionality can only be guarenteed to work with exactly the same version of Slang on the same version of compiler. In practice things are typically not so draconian, and future versions will aim to provide a more clear slang repro versioning system, and work will be performed to make more generally usable. \n\nFinally this version of the repo system does not take into account endianess at all. The system the repro is saved from must have the same endianess as the system loaded on.\n"
  },
  {
    "path": "Source/External/slang/docs/shader-playground.md",
    "content": "Using Slang on Shader Playground\n================================\n\nA fast and simple way to try out Slang is by using the [Shader Playground](http://shader-playground.timjones.io/) website. This site allows easy and interactive testing of shader code across several compilers including Slang without having to install anything on your local machine.\n\nUsing the Slang compiler is as simple as selecting 'Slang' from the box in the top left corner from the [Shader Playground](http://shader-playground.timjones.io/). This selects the Slang language for input, and the Slang compiler for compilation. The output of the compilation is shown in the right hand panel.\n\nThe default 'Output format' is HLSL. For graphics shaders the 'Output format' can be changed to\n\n* DXIL \n* SPIR-V\n* DXBC\n* HLSL\n* GLSL\n\nAdditionally for compute based shaders it can be set to\n\n* C++\n* CUDA\n* PTX\n\nFor binary formats (such as DXIL/SPIR-V/DXBC) the output will be displayed as the applicable disassembly.\n\nNote that C++ and CUDA output include a 'prelude'. The prelude remains the same across compilations, with the code generated for the input Slang source placed at the very end of the output. \n\n"
  },
  {
    "path": "Source/External/slang/docs/stdlib-doc.md",
    "content": "--------------------------------------------------------------------------------\n# `__BuiltinArithmeticType.init`\n\n## Signature \n\n```\n__BuiltinArithmeticType.init(int value);\n```\n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `__BuiltinFloatingPointType.init`\n\n## Signature \n\n```\n__BuiltinFloatingPointType.init(float value);\n```\n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `__BuiltinFloatingPointType.getPi`\n\n## Description\n\nGet the value of the mathematical constant pi in this type.\n\n## Signature \n\n```\n__BuiltinFloatingPointType.This __BuiltinFloatingPointType.getPi();\n```\n\n--------------------------------------------------------------------------------\n# `struct ConstantBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n--------------------------------------------------------------------------------\n# `struct TextureBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n--------------------------------------------------------------------------------\n# `struct ParameterBlock<T>`\n\n## Generic Parameters\n\n* `T`\n\n--------------------------------------------------------------------------------\n# `struct SamplerState`\n\n## Description\n\nSampling state for filtered texture fetches.\n\n--------------------------------------------------------------------------------\n# `struct SamplerComparisonState`\n\n## Description\n\nSampling state for filtered texture fetches that include a comparison operation before filtering.\n\n--------------------------------------------------------------------------------\n# `struct Texture1D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Texture1D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Texture1D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture1D<T>.GetDimensions(out uint width);\nvoid Texture1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             numberOfLevels);\nvoid Texture1D<T>.GetDimensions(out float width);\nvoid Texture1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1D<T>.Load(vector<int,2> location);\n/// See Availability 2\nT Texture1D<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset);\n/// See Availability 3\nT Texture1D<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.subscript`\n\n## Signature \n\n```\nT Texture1D<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location);\n/// See Availability 2\nT Texture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT Texture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT Texture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.SampleBias`\n\n## Signature \n\n```\nT Texture1D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                bias);\nT Texture1D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Texture1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\nfloat Texture1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Texture1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Texture1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT Texture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT Texture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Texture1D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                level);\n/// See Availability 2\nT Texture1D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Texture1D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture1D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWTexture1D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWTexture1D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture1D<T>.GetDimensions(out uint width);\nvoid RWTexture1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             numberOfLevels);\nvoid RWTexture1D<T>.GetDimensions(out float width);\nvoid RWTexture1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1D<T>.Load(vector<int,1> location);\n/// See Availability 2\nT RWTexture1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWTexture1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.subscript`\n\n## Signature \n\n```\nT RWTexture1D<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location);\n/// See Availability 2\nT RWTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RWTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.SampleBias`\n\n## Signature \n\n```\nT RWTexture1D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                bias);\nT RWTexture1D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWTexture1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\nfloat RWTexture1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWTexture1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWTexture1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RWTexture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWTexture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                level);\n/// See Availability 2\nT RWTexture1D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture1D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture1D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture1D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture1D<T>.GetDimensions(out uint width);\nvoid RasterizerOrderedTexture1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture1D<T>.GetDimensions(out float width);\nvoid RasterizerOrderedTexture1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1D<T>.Load(vector<int,1> location);\nT RasterizerOrderedTexture1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture1D<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location);\n/// See Availability 2\nT RasterizerOrderedTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RasterizerOrderedTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RasterizerOrderedTexture1D<T>.Sample(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTexture1D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                bias);\nT RasterizerOrderedTexture1D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\nfloat RasterizerOrderedTexture1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedTexture1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedTexture1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RasterizerOrderedTexture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture1D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedTexture1D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,1>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<T,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<float,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<int,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.Gather(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherRed(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherGreen(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherBlue(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location);\nvector<uint,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1D.GatherAlpha(\n    SamplerState         s,\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Texture1DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Texture1DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture1DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             sampleCount);\nvoid Texture1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Texture1DMS<T>.GetDimensions(\n    out float            width,\n    out float            sampleCount);\nvoid Texture1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture1DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Texture1DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Texture1DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex);\nT Texture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT Texture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture1DMS<T>.subscript`\n\n## Signature \n\n```\nT Texture1DMS<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture1DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture1DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             sampleCount);\nvoid RWTexture1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWTexture1DMS<T>.GetDimensions(\n    out float            width,\n    out float            sampleCount);\nvoid RWTexture1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWTexture1DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex);\nT RWTexture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWTexture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMS<T>.subscript`\n\n## Signature \n\n```\nT RWTexture1DMS<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture1DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture1DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             sampleCount);\nvoid RasterizerOrderedTexture1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture1DMS<T>.GetDimensions(\n    out float            width,\n    out float            sampleCount);\nvoid RasterizerOrderedTexture1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTexture1DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex);\nT RasterizerOrderedTexture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMS<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture1DMS<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Texture1DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Texture1DArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Texture1DArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture1DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements);\nvoid Texture1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid Texture1DArray<T>.GetDimensions(\n    out float            width,\n    out float            elements);\nvoid Texture1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1DArray<T>.Load(vector<int,3> location);\nT Texture1DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,1>        offset);\n/// See Availability 2\nT Texture1DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.subscript`\n\n## Signature \n\n```\nT Texture1DArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nT Texture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT Texture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT Texture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.SampleBias`\n\n## Signature \n\n```\nT Texture1DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias);\nT Texture1DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Texture1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat Texture1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Texture1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Texture1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT Texture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT Texture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT Texture1DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Texture1DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Texture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture1DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWTexture1DArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWTexture1DArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture1DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements);\nvoid RWTexture1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RWTexture1DArray<T>.GetDimensions(\n    out float            width,\n    out float            elements);\nvoid RWTexture1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1DArray<T>.Load(vector<int,2> location);\n/// See Availability 2\nT RWTexture1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWTexture1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.subscript`\n\n## Signature \n\n```\nT RWTexture1DArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nT RWTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RWTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RWTexture1DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias);\nT RWTexture1DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWTexture1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RWTexture1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWTexture1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWTexture1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RWTexture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWTexture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RWTexture1DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture1DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture1DArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture1DArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,1>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture1DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements);\nvoid RasterizerOrderedTexture1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture1DArray<T>.GetDimensions(\n    out float            width,\n    out float            elements);\nvoid RasterizerOrderedTexture1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1DArray<T>.Load(vector<int,2> location);\nT RasterizerOrderedTexture1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture1DArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nT RasterizerOrderedTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RasterizerOrderedTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RasterizerOrderedTexture1DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTexture1DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias);\nT RasterizerOrderedTexture1DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RasterizerOrderedTexture1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedTexture1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedTexture1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RasterizerOrderedTexture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture1DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedTexture1DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<T,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<float,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<int,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture1DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Texture1DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Texture1DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture1DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount);\nvoid Texture1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Texture1DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            elements,\n    out float            sampleCount);\nvoid Texture1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture1DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Texture1DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Texture1DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT Texture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT Texture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture1DMSArray<T>.subscript`\n\n## Signature \n\n```\nT Texture1DMSArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture1DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture1DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RWTexture1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWTexture1DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            elements,\n    out float            sampleCount);\nvoid RWTexture1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWTexture1DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RWTexture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWTexture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture1DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RWTexture1DMSArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture1DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture1DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RasterizerOrderedTexture1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture1DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            elements,\n    out float            sampleCount);\nvoid RasterizerOrderedTexture1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTexture1DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RasterizerOrderedTexture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture1DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture1DMSArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Texture2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Texture2D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Texture2D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid Texture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid Texture2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid Texture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2D<T>.Load(vector<int,3> location);\nT Texture2D<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT Texture2D<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.subscript`\n\n## Signature \n\n```\nT Texture2D<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nT Texture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT Texture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT Texture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.SampleBias`\n\n## Signature \n\n```\nT Texture2D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias);\nT Texture2D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Texture2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat Texture2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Texture2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Texture2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT Texture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT Texture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Texture2D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT Texture2D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Texture2D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWTexture2D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWTexture2D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid RWTexture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid RWTexture2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid RWTexture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2D<T>.Load(vector<int,2> location);\n/// See Availability 2\nT RWTexture2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWTexture2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.subscript`\n\n## Signature \n\n```\nT RWTexture2D<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nT RWTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RWTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.SampleBias`\n\n## Signature \n\n```\nT RWTexture2D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias);\nT RWTexture2D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWTexture2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RWTexture2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWTexture2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWTexture2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RWTexture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWTexture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RWTexture2D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture2D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture2D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid RasterizerOrderedTexture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid RasterizerOrderedTexture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2D<T>.Load(vector<int,2> location);\nT RasterizerOrderedTexture2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture2D<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nT RasterizerOrderedTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RasterizerOrderedTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RasterizerOrderedTexture2D<T>.Sample(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTexture2D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias);\nT RasterizerOrderedTexture2D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RasterizerOrderedTexture2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedTexture2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedTexture2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RasterizerOrderedTexture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture2D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedTexture2D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,2>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.Gather(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherRed(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherGreen(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherBlue(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2D.GatherAlpha(\n    SamplerState         s,\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Texture2DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Texture2DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture2DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid Texture2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Texture2DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid Texture2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture2DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Texture2DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Texture2DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT Texture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT Texture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture2DMS<T>.subscript`\n\n## Signature \n\n```\nT Texture2DMS<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture2DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture2DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid RWTexture2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWTexture2DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid RWTexture2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWTexture2DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RWTexture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWTexture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMS<T>.subscript`\n\n## Signature \n\n```\nT RWTexture2DMS<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture2DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture2DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid RasterizerOrderedTexture2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture2DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid RasterizerOrderedTexture2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTexture2DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RasterizerOrderedTexture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMS<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture2DMS<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Texture2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Texture2DArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Texture2DArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid Texture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid Texture2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid Texture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2DArray<T>.Load(vector<int,4> location);\nT Texture2DArray<T>.Load(\n    vector<int,4>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT Texture2DArray<T>.Load(\n    vector<int,4>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.subscript`\n\n## Signature \n\n```\nT Texture2DArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT Texture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT Texture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT Texture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.SampleBias`\n\n## Signature \n\n```\nT Texture2DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\nT Texture2DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Texture2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat Texture2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Texture2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Texture2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT Texture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT Texture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT Texture2DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Texture2DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Texture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWTexture2DArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWTexture2DArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid RWTexture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RWTexture2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid RWTexture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2DArray<T>.Load(vector<int,3> location);\n/// See Availability 2\nT RWTexture2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWTexture2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.subscript`\n\n## Signature \n\n```\nT RWTexture2DArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT RWTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RWTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RWTexture2DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\nT RWTexture2DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWTexture2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RWTexture2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWTexture2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWTexture2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RWTexture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWTexture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RWTexture2DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture2DArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture2DArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,2>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid RasterizerOrderedTexture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid RasterizerOrderedTexture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2DArray<T>.Load(vector<int,3> location);\nT RasterizerOrderedTexture2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture2DArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT RasterizerOrderedTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RasterizerOrderedTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RasterizerOrderedTexture2DArray<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTexture2DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\nT RasterizerOrderedTexture2DArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RasterizerOrderedTexture2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedTexture2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedTexture2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RasterizerOrderedTexture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture2DArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedTexture2DArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedTexture2DArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Texture2DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Texture2DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture2DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid Texture2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Texture2DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid Texture2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture2DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Texture2DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Texture2DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT Texture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT Texture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture2DMSArray<T>.subscript`\n\n## Signature \n\n```\nT Texture2DMSArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture2DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture2DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RWTexture2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWTexture2DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid RWTexture2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWTexture2DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RWTexture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWTexture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture2DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RWTexture2DMSArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture2DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture2DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RasterizerOrderedTexture2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture2DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid RasterizerOrderedTexture2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTexture2DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RasterizerOrderedTexture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture2DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture2DMSArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Texture3D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Texture3D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Texture3D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture3D<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth);\nvoid Texture3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             numberOfLevels);\nvoid Texture3D<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth);\nvoid Texture3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture3D<T>.Load(vector<int,4> location);\nT Texture3D<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT Texture3D<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.subscript`\n\n## Signature \n\n```\nT Texture3D<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT Texture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 3\nT Texture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp);\nT Texture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.SampleBias`\n\n## Signature \n\n```\nT Texture3D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\nT Texture3D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Texture3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat Texture3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Texture3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Texture3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\nT Texture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset);\n/// See Availability 2\nT Texture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Texture3D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture3D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT Texture3D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Texture3D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Texture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Texture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Texture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Texture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Texture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture3D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWTexture3D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWTexture3D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture3D<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth);\nvoid RWTexture3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             numberOfLevels);\nvoid RWTexture3D<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth);\nvoid RWTexture3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture3D<T>.Load(vector<int,3> location);\n/// See Availability 2\nT RWTexture3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset);\n/// See Availability 3\nT RWTexture3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.subscript`\n\n## Signature \n\n```\nT RWTexture3D<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT RWTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 3\nT RWTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp);\nT RWTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.SampleBias`\n\n## Signature \n\n```\nT RWTexture3D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\nT RWTexture3D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWTexture3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RWTexture3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWTexture3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWTexture3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\nT RWTexture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset);\n/// See Availability 2\nT RWTexture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture3D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RWTexture3D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture3D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWTexture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture3D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture3D<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture3D<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture3D<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth);\nvoid RasterizerOrderedTexture3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture3D<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth);\nvoid RasterizerOrderedTexture3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture3D<T>.Load(vector<int,3> location);\nT RasterizerOrderedTexture3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture3D<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT RasterizerOrderedTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 3\nT RasterizerOrderedTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp);\nT RasterizerOrderedTexture3D<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTexture3D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\nT RasterizerOrderedTexture3D<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedTexture3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RasterizerOrderedTexture3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedTexture3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedTexture3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\nT RasterizerOrderedTexture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture3D<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture3D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedTexture3D<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture3D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTexture3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTexture3D.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Texture3DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Texture3DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Texture3DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount);\nvoid Texture3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Texture3DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount);\nvoid Texture3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Texture3DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Texture3DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Texture3DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Texture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT Texture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT Texture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Texture3DMS<T>.subscript`\n\n## Signature \n\n```\nT Texture3DMS<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWTexture3DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWTexture3DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWTexture3DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount);\nvoid RWTexture3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWTexture3DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount);\nvoid RWTexture3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWTexture3DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWTexture3DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWTexture3DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWTexture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RWTexture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT RWTexture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWTexture3DMS<T>.subscript`\n\n## Signature \n\n```\nT RWTexture3DMS<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTexture3DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTexture3DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount);\nvoid RasterizerOrderedTexture3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTexture3DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount);\nvoid RasterizerOrderedTexture3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTexture3DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTexture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RasterizerOrderedTexture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedTexture3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTexture3DMS<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedTexture3DMS<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct TextureCube<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat TextureCube<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat TextureCube<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.GetDimensions`\n\n## Signature \n\n```\nvoid TextureCube<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid TextureCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid TextureCube<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid TextureCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT TextureCube<T>.Load(vector<int,4> location);\nT TextureCube<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT TextureCube<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT TextureCube<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT TextureCube<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                clamp);\nT TextureCube<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.SampleBias`\n\n## Signature \n\n```\nT TextureCube<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.SampleCmp`\n\n## Signature \n\n```\nfloat TextureCube<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\nfloat TextureCube<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.SampleGrad`\n\n## Signature \n\n```\nT TextureCube<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `TextureCube<T>.SampleLevel`\n\n## Signature \n\n```\nT TextureCube<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension TextureCube`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension TextureCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension TextureCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension TextureCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTextureCube<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTextureCube<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTextureCube<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTextureCube<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid RasterizerOrderedTextureCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTextureCube<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid RasterizerOrderedTextureCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTextureCube<T>.Load(vector<int,3> location);\nT RasterizerOrderedTextureCube<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedTextureCube<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTextureCube<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location);\n/// See Availability 2\nT RasterizerOrderedTextureCube<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                clamp);\nT RasterizerOrderedTextureCube<T>.Sample(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTextureCube<T>.SampleBias(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedTextureCube<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\nfloat RasterizerOrderedTextureCube<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.SampleGrad`\n\n## Signature \n\n```\nT RasterizerOrderedTextureCube<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube<T>.SampleLevel`\n\n## Signature \n\n```\nT RasterizerOrderedTextureCube<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,3>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCube`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<T,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<float,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<int,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.Gather(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherRed(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherGreen(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherBlue(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location);\nvector<uint,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCube.GatherAlpha(\n    SamplerState         s,\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct TextureCubeMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n\n--------------------------------------------------------------------------------\n# `TextureCubeMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid TextureCubeMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid TextureCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid TextureCubeMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid TextureCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `TextureCubeMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> TextureCubeMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `TextureCubeMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT TextureCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT TextureCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT TextureCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTextureCubeMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTextureCubeMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid RasterizerOrderedTextureCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTextureCubeMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid RasterizerOrderedTextureCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTextureCubeMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTextureCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RasterizerOrderedTextureCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedTextureCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `struct TextureCubeArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Sample`\n* `SampleBias`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat TextureCubeArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat TextureCubeArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid TextureCubeArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid TextureCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid TextureCubeArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid TextureCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT TextureCubeArray<T>.Sample(\n    SamplerState         s,\n    vector<float,4>      location);\n/// See Availability 2\nT TextureCubeArray<T>.Sample(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                clamp);\nT TextureCubeArray<T>.Sample(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.SampleBias`\n\n## Signature \n\n```\nT TextureCubeArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.SampleGrad`\n\n## Signature \n\n```\nT TextureCubeArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray<T>.SampleLevel`\n\n## Signature \n\n```\nT TextureCubeArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension TextureCubeArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension TextureCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension TextureCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension TextureCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `TextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> TextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTextureCubeArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Sample`\n* `SampleBias`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedTextureCubeArray<T>.CalculateLevelOfDetail(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedTextureCubeArray<T>.CalculateLevelOfDetailUnclamped(\n    SamplerState         s,\n    vector<float,3>      location);\n```\n\n## Parameters\n\n* `s`\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTextureCubeArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid RasterizerOrderedTextureCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTextureCubeArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid RasterizerOrderedTextureCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedTextureCubeArray<T>.Sample(\n    SamplerState         s,\n    vector<float,4>      location);\n/// See Availability 2\nT RasterizerOrderedTextureCubeArray<T>.Sample(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                clamp);\nT RasterizerOrderedTextureCubeArray<T>.Sample(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedTextureCubeArray<T>.SampleBias(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.SampleGrad`\n\n## Signature \n\n```\nT RasterizerOrderedTextureCubeArray<T>.SampleGrad(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray<T>.SampleLevel`\n\n## Signature \n\n```\nT RasterizerOrderedTextureCubeArray<T>.SampleLevel(\n    SamplerState         s,\n    vector<float,4>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `s`\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCubeArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedTextureCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.Gather(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherRed(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherGreen(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherBlue(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location);\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedTextureCubeArray.GatherAlpha(\n    SamplerState         s,\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct TextureCubeMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n\n--------------------------------------------------------------------------------\n# `TextureCubeMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid TextureCubeMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid TextureCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid TextureCubeMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid TextureCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `TextureCubeMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> TextureCubeMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedTextureCubeMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedTextureCubeMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RasterizerOrderedTextureCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedTextureCubeMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid RasterizerOrderedTextureCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedTextureCubeMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedTextureCubeMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `struct Sampler1D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Sampler1D<T>.CalculateLevelOfDetail(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Sampler1D<T>.CalculateLevelOfDetailUnclamped(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler1D<T>.GetDimensions(out uint width);\nvoid Sampler1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             numberOfLevels);\nvoid Sampler1D<T>.GetDimensions(out float width);\nvoid Sampler1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1D<T>.Load(vector<int,2> location);\n/// See Availability 2\nT Sampler1D<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset);\n/// See Availability 3\nT Sampler1D<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.subscript`\n\n## Signature \n\n```\nT Sampler1D<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1D<T>.Sample(vector<float,1> location);\n/// See Availability 2\nT Sampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT Sampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT Sampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.SampleBias`\n\n## Signature \n\n```\nT Sampler1D<T>.SampleBias(\n    vector<float,1>      location,\n    float                bias);\nT Sampler1D<T>.SampleBias(\n    vector<float,1>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Sampler1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\nfloat Sampler1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Sampler1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Sampler1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT Sampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT Sampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Sampler1D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1D<T>.SampleLevel(\n    vector<float,1>      location,\n    float                level);\n/// See Availability 2\nT Sampler1D<T>.SampleLevel(\n    vector<float,1>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1D.Gather(vector<float,1> location);\nvector<T,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1D.GatherRed(vector<float,1> location);\nvector<T,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1D.GatherGreen(vector<float,1> location);\nvector<T,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1D.GatherBlue(vector<float,1> location);\nvector<T,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1D.GatherAlpha(vector<float,1> location);\nvector<T,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1D.Gather(vector<float,1> location);\nvector<float,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1D.GatherRed(vector<float,1> location);\nvector<float,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1D.GatherGreen(vector<float,1> location);\nvector<float,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1D.GatherBlue(vector<float,1> location);\nvector<float,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1D.GatherAlpha(vector<float,1> location);\nvector<float,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1D.Gather(vector<float,1> location);\nvector<int,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1D.GatherRed(vector<float,1> location);\nvector<int,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1D.GatherGreen(vector<float,1> location);\nvector<int,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1D.GatherBlue(vector<float,1> location);\nvector<int,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1D.GatherAlpha(vector<float,1> location);\nvector<int,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1D.Gather(vector<float,1> location);\nvector<uint,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherRed(vector<float,1> location);\nvector<uint,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherGreen(vector<float,1> location);\nvector<uint,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherBlue(vector<float,1> location);\nvector<uint,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherAlpha(vector<float,1> location);\nvector<uint,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler1D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWSampler1D<T>.CalculateLevelOfDetail(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWSampler1D<T>.CalculateLevelOfDetailUnclamped(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler1D<T>.GetDimensions(out uint width);\nvoid RWSampler1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             numberOfLevels);\nvoid RWSampler1D<T>.GetDimensions(out float width);\nvoid RWSampler1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1D<T>.Load(vector<int,1> location);\n/// See Availability 2\nT RWSampler1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWSampler1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.subscript`\n\n## Signature \n\n```\nT RWSampler1D<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1D<T>.Sample(vector<float,1> location);\n/// See Availability 2\nT RWSampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWSampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RWSampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.SampleBias`\n\n## Signature \n\n```\nT RWSampler1D<T>.SampleBias(\n    vector<float,1>      location,\n    float                bias);\nT RWSampler1D<T>.SampleBias(\n    vector<float,1>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWSampler1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\nfloat RWSampler1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWSampler1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWSampler1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RWSampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWSampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1D<T>.SampleLevel(\n    vector<float,1>      location,\n    float                level);\n/// See Availability 2\nT RWSampler1D<T>.SampleLevel(\n    vector<float,1>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1D.Gather(vector<float,1> location);\nvector<T,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherRed(vector<float,1> location);\nvector<T,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherGreen(vector<float,1> location);\nvector<T,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherBlue(vector<float,1> location);\nvector<T,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherAlpha(vector<float,1> location);\nvector<T,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1D.Gather(vector<float,1> location);\nvector<float,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherRed(vector<float,1> location);\nvector<float,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherGreen(vector<float,1> location);\nvector<float,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherBlue(vector<float,1> location);\nvector<float,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherAlpha(vector<float,1> location);\nvector<float,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1D.Gather(vector<float,1> location);\nvector<int,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherRed(vector<float,1> location);\nvector<int,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherGreen(vector<float,1> location);\nvector<int,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherBlue(vector<float,1> location);\nvector<int,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherAlpha(vector<float,1> location);\nvector<int,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1D.Gather(vector<float,1> location);\nvector<uint,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherRed(vector<float,1> location);\nvector<uint,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherGreen(vector<float,1> location);\nvector<uint,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherBlue(vector<float,1> location);\nvector<uint,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherAlpha(vector<float,1> location);\nvector<uint,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler1D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler1D<T>.CalculateLevelOfDetail(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler1D<T>.CalculateLevelOfDetailUnclamped(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler1D<T>.GetDimensions(out uint width);\nvoid RasterizerOrderedSampler1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler1D<T>.GetDimensions(out float width);\nvoid RasterizerOrderedSampler1D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1D<T>.Load(vector<int,1> location);\nT RasterizerOrderedSampler1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler1D<T>.Load(\n    vector<int,1>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler1D<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1D<T>.Sample(vector<float,1> location);\n/// See Availability 2\nT RasterizerOrderedSampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RasterizerOrderedSampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RasterizerOrderedSampler1D<T>.Sample(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSampler1D<T>.SampleBias(\n    vector<float,1>      location,\n    float                bias);\nT RasterizerOrderedSampler1D<T>.SampleBias(\n    vector<float,1>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\nfloat RasterizerOrderedSampler1D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedSampler1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedSampler1D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,1>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RasterizerOrderedSampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler1D<T>.SampleGrad(\n    vector<float,1>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1D<T>.SampleLevel(\n    vector<float,1>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedSampler1D<T>.SampleLevel(\n    vector<float,1>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.Gather(vector<float,1> location);\nvector<T,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherRed(vector<float,1> location);\nvector<T,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherGreen(vector<float,1> location);\nvector<T,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherBlue(vector<float,1> location);\nvector<T,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherAlpha(vector<float,1> location);\nvector<T,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.Gather(vector<float,1> location);\nvector<float,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherRed(vector<float,1> location);\nvector<float,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherGreen(vector<float,1> location);\nvector<float,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherBlue(vector<float,1> location);\nvector<float,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherAlpha(vector<float,1> location);\nvector<float,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.Gather(vector<float,1> location);\nvector<int,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherRed(vector<float,1> location);\nvector<int,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherGreen(vector<float,1> location);\nvector<int,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherBlue(vector<float,1> location);\nvector<int,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherAlpha(vector<float,1> location);\nvector<int,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.Gather(vector<float,1> location);\nvector<uint,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.Gather(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherRed(vector<float,1> location);\nvector<uint,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherRed(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherGreen(vector<float,1> location);\nvector<uint,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherGreen(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherBlue(vector<float,1> location);\nvector<uint,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherBlue(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherAlpha(vector<float,1> location);\nvector<uint,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1D.GatherAlpha(\n    vector<float,1>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Sampler1DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler1DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             sampleCount);\nvoid Sampler1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Sampler1DMS<T>.GetDimensions(\n    out float            width,\n    out float            sampleCount);\nvoid Sampler1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Sampler1DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex);\nT Sampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT Sampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMS<T>.subscript`\n\n## Signature \n\n```\nT Sampler1DMS<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler1DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler1DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             sampleCount);\nvoid RWSampler1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWSampler1DMS<T>.GetDimensions(\n    out float            width,\n    out float            sampleCount);\nvoid RWSampler1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWSampler1DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex);\nT RWSampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWSampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMS<T>.subscript`\n\n## Signature \n\n```\nT RWSampler1DMS<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler1DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler1DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             sampleCount);\nvoid RasterizerOrderedSampler1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler1DMS<T>.GetDimensions(\n    out float            width,\n    out float            sampleCount);\nvoid RasterizerOrderedSampler1DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSampler1DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex);\nT RasterizerOrderedSampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler1DMS<T>.Load(\n    vector<int,1>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMS<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler1DMS<T>.subscript(uint location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Sampler1DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Sampler1DArray<T>.CalculateLevelOfDetail(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Sampler1DArray<T>.CalculateLevelOfDetailUnclamped(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler1DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements);\nvoid Sampler1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid Sampler1DArray<T>.GetDimensions(\n    out float            width,\n    out float            elements);\nvoid Sampler1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1DArray<T>.Load(vector<int,3> location);\nT Sampler1DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,1>        offset);\n/// See Availability 2\nT Sampler1DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.subscript`\n\n## Signature \n\n```\nT Sampler1DArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1DArray<T>.Sample(vector<float,2> location);\n/// See Availability 2\nT Sampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT Sampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT Sampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.SampleBias`\n\n## Signature \n\n```\nT Sampler1DArray<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias);\nT Sampler1DArray<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Sampler1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat Sampler1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Sampler1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Sampler1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT Sampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT Sampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1DArray<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT Sampler1DArray<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1DArray.Gather(vector<float,2> location);\nvector<T,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherRed(vector<float,2> location);\nvector<T,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherGreen(vector<float,2> location);\nvector<T,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherBlue(vector<float,2> location);\nvector<T,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherAlpha(vector<float,2> location);\nvector<T,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1DArray.Gather(vector<float,2> location);\nvector<float,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherRed(vector<float,2> location);\nvector<float,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherGreen(vector<float,2> location);\nvector<float,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherBlue(vector<float,2> location);\nvector<float,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherAlpha(vector<float,2> location);\nvector<float,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1DArray.Gather(vector<float,2> location);\nvector<int,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherRed(vector<float,2> location);\nvector<int,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherGreen(vector<float,2> location);\nvector<int,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherBlue(vector<float,2> location);\nvector<int,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherAlpha(vector<float,2> location);\nvector<int,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1DArray.Gather(vector<float,2> location);\nvector<uint,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherRed(vector<float,2> location);\nvector<uint,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherGreen(vector<float,2> location);\nvector<uint,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherBlue(vector<float,2> location);\nvector<uint,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherAlpha(vector<float,2> location);\nvector<uint,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler1DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWSampler1DArray<T>.CalculateLevelOfDetail(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWSampler1DArray<T>.CalculateLevelOfDetailUnclamped(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler1DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements);\nvoid RWSampler1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RWSampler1DArray<T>.GetDimensions(\n    out float            width,\n    out float            elements);\nvoid RWSampler1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1DArray<T>.Load(vector<int,2> location);\n/// See Availability 2\nT RWSampler1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWSampler1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.subscript`\n\n## Signature \n\n```\nT RWSampler1DArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1DArray<T>.Sample(vector<float,2> location);\n/// See Availability 2\nT RWSampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RWSampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RWSampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RWSampler1DArray<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias);\nT RWSampler1DArray<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWSampler1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RWSampler1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWSampler1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWSampler1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RWSampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWSampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1DArray<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RWSampler1DArray<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1DArray.Gather(vector<float,2> location);\nvector<T,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherRed(vector<float,2> location);\nvector<T,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherGreen(vector<float,2> location);\nvector<T,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherBlue(vector<float,2> location);\nvector<T,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<T,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1DArray.Gather(vector<float,2> location);\nvector<float,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherRed(vector<float,2> location);\nvector<float,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherGreen(vector<float,2> location);\nvector<float,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherBlue(vector<float,2> location);\nvector<float,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<float,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1DArray.Gather(vector<float,2> location);\nvector<int,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherRed(vector<float,2> location);\nvector<int,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherGreen(vector<float,2> location);\nvector<int,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherBlue(vector<float,2> location);\nvector<int,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<int,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.Gather(vector<float,2> location);\nvector<uint,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherRed(vector<float,2> location);\nvector<uint,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherGreen(vector<float,2> location);\nvector<uint,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherBlue(vector<float,2> location);\nvector<uint,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<uint,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler1DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler1DArray<T>.CalculateLevelOfDetail(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler1DArray<T>.CalculateLevelOfDetailUnclamped(vector<float,1> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler1DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements);\nvoid RasterizerOrderedSampler1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler1DArray<T>.GetDimensions(\n    out float            width,\n    out float            elements);\nvoid RasterizerOrderedSampler1DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1DArray<T>.Load(vector<int,2> location);\nT RasterizerOrderedSampler1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler1DArray<T>.Load(\n    vector<int,2>        location,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler1DArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1DArray<T>.Sample(vector<float,2> location);\n/// See Availability 2\nT RasterizerOrderedSampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 3\nT RasterizerOrderedSampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp);\nT RasterizerOrderedSampler1DArray<T>.Sample(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSampler1DArray<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias);\nT RasterizerOrderedSampler1DArray<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RasterizerOrderedSampler1DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedSampler1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedSampler1DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY);\nT RasterizerOrderedSampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler1DArray<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,1>      gradX,\n    vector<float,1>      gradY,\n    vector<int,1>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1DArray<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedSampler1DArray<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level,\n    vector<int,1>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.Gather(vector<float,2> location);\nvector<T,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherRed(vector<float,2> location);\nvector<T,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherGreen(vector<float,2> location);\nvector<T,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherBlue(vector<float,2> location);\nvector<T,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<T,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.Gather(vector<float,2> location);\nvector<float,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherRed(vector<float,2> location);\nvector<float,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherGreen(vector<float,2> location);\nvector<float,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherBlue(vector<float,2> location);\nvector<float,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<float,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.Gather(vector<float,2> location);\nvector<int,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherRed(vector<float,2> location);\nvector<int,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherGreen(vector<float,2> location);\nvector<int,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherBlue(vector<float,2> location);\nvector<int,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<int,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler1DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.Gather(vector<float,2> location);\nvector<uint,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.Gather(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherRed(vector<float,2> location);\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherRed(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherGreen(vector<float,2> location);\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherGreen(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherBlue(vector<float,2> location);\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherBlue(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherAlpha(vector<float,2> location);\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler1DArray.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,1>        offset1,\n    vector<int,1>        offset2,\n    vector<int,1>        offset3,\n    vector<int,1>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Sampler1DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler1DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount);\nvoid Sampler1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Sampler1DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            elements,\n    out float            sampleCount);\nvoid Sampler1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Sampler1DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT Sampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT Sampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler1DMSArray<T>.subscript`\n\n## Signature \n\n```\nT Sampler1DMSArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler1DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler1DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RWSampler1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWSampler1DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            elements,\n    out float            sampleCount);\nvoid RWSampler1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWSampler1DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RWSampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RWSampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler1DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RWSampler1DMSArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler1DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler1DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RasterizerOrderedSampler1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler1DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            elements,\n    out float            sampleCount);\nvoid RasterizerOrderedSampler1DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSampler1DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RasterizerOrderedSampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler1DMSArray<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,1>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler1DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler1DMSArray<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Sampler2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Sampler2D<T>.CalculateLevelOfDetail(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Sampler2D<T>.CalculateLevelOfDetailUnclamped(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid Sampler2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid Sampler2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid Sampler2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2D<T>.Load(vector<int,3> location);\nT Sampler2D<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT Sampler2D<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.subscript`\n\n## Signature \n\n```\nT Sampler2D<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2D<T>.Sample(vector<float,2> location);\n/// See Availability 2\nT Sampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT Sampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT Sampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.SampleBias`\n\n## Signature \n\n```\nT Sampler2D<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias);\nT Sampler2D<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Sampler2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat Sampler2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Sampler2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Sampler2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT Sampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT Sampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Sampler2D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2D<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT Sampler2D<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<T,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<float,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<int,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWSampler2D<T>.CalculateLevelOfDetail(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWSampler2D<T>.CalculateLevelOfDetailUnclamped(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid RWSampler2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid RWSampler2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid RWSampler2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2D<T>.Load(vector<int,2> location);\n/// See Availability 2\nT RWSampler2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWSampler2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.subscript`\n\n## Signature \n\n```\nT RWSampler2D<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2D<T>.Sample(vector<float,2> location);\n/// See Availability 2\nT RWSampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWSampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RWSampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.SampleBias`\n\n## Signature \n\n```\nT RWSampler2D<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias);\nT RWSampler2D<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWSampler2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RWSampler2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWSampler2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWSampler2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RWSampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWSampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2D<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RWSampler2D<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler2D<T>.CalculateLevelOfDetail(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler2D<T>.CalculateLevelOfDetailUnclamped(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid RasterizerOrderedSampler2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid RasterizerOrderedSampler2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2D<T>.Load(vector<int,2> location);\nT RasterizerOrderedSampler2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler2D<T>.Load(\n    vector<int,2>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler2D<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2D<T>.Sample(vector<float,2> location);\n/// See Availability 2\nT RasterizerOrderedSampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RasterizerOrderedSampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RasterizerOrderedSampler2D<T>.Sample(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSampler2D<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias);\nT RasterizerOrderedSampler2D<T>.SampleBias(\n    vector<float,2>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\nfloat RasterizerOrderedSampler2D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedSampler2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedSampler2D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,2>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RasterizerOrderedSampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler2D<T>.SampleGrad(\n    vector<float,2>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2D<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedSampler2D<T>.SampleLevel(\n    vector<float,2>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2D.Gather(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.Gather(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2D.GatherRed(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherRed(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2D.GatherGreen(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherGreen(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2D.GatherBlue(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherBlue(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2D.GatherAlpha(vector<float,2> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2D.GatherAlpha(\n    vector<float,2>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Sampler2DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler2DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid Sampler2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Sampler2DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid Sampler2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Sampler2DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT Sampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT Sampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMS<T>.subscript`\n\n## Signature \n\n```\nT Sampler2DMS<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler2DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler2DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid RWSampler2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWSampler2DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid RWSampler2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWSampler2DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RWSampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWSampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMS<T>.subscript`\n\n## Signature \n\n```\nT RWSampler2DMS<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler2DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler2DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid RasterizerOrderedSampler2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler2DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid RasterizerOrderedSampler2DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSampler2DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex);\nT RasterizerOrderedSampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler2DMS<T>.Load(\n    vector<int,2>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMS<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler2DMS<T>.subscript(vector<uint,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Sampler2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Sampler2DArray<T>.CalculateLevelOfDetail(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Sampler2DArray<T>.CalculateLevelOfDetailUnclamped(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid Sampler2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid Sampler2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid Sampler2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2DArray<T>.Load(vector<int,4> location);\nT Sampler2DArray<T>.Load(\n    vector<int,4>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT Sampler2DArray<T>.Load(\n    vector<int,4>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.subscript`\n\n## Signature \n\n```\nT Sampler2DArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2DArray<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT Sampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT Sampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT Sampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.SampleBias`\n\n## Signature \n\n```\nT Sampler2DArray<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\nT Sampler2DArray<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Sampler2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat Sampler2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Sampler2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Sampler2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT Sampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT Sampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2DArray<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT Sampler2DArray<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<T,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<float,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<int,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> Sampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWSampler2DArray<T>.CalculateLevelOfDetail(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWSampler2DArray<T>.CalculateLevelOfDetailUnclamped(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid RWSampler2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RWSampler2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid RWSampler2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2DArray<T>.Load(vector<int,3> location);\n/// See Availability 2\nT RWSampler2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWSampler2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.subscript`\n\n## Signature \n\n```\nT RWSampler2DArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2DArray<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT RWSampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RWSampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RWSampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RWSampler2DArray<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\nT RWSampler2DArray<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWSampler2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RWSampler2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWSampler2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWSampler2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RWSampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWSampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2DArray<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RWSampler2DArray<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RWSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler2DArray<T>.CalculateLevelOfDetail(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler2DArray<T>.CalculateLevelOfDetailUnclamped(vector<float,2> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid RasterizerOrderedSampler2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid RasterizerOrderedSampler2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2DArray<T>.Load(vector<int,3> location);\nT RasterizerOrderedSampler2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler2DArray<T>.Load(\n    vector<int,3>        location,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler2DArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2DArray<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT RasterizerOrderedSampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nT RasterizerOrderedSampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp);\nT RasterizerOrderedSampler2DArray<T>.Sample(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSampler2DArray<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\nT RasterizerOrderedSampler2DArray<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RasterizerOrderedSampler2DArray<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedSampler2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedSampler2DArray<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY);\nT RasterizerOrderedSampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler2DArray<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,2>      gradX,\n    vector<float,2>      gradY,\n    vector<int,2>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2DArray<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedSampler2DArray<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2DArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<T,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<float,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<int,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler2DArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2DArray.Gather(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.Gather(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherRed(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherRed(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherGreen(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherGreen(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherBlue(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherBlue(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherAlpha(vector<float,3> location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset,\n    out uint             status);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4);\n/// See Availability 3\nvector<uint,4> RasterizerOrderedSampler2DArray.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,2>        offset1,\n    vector<int,2>        offset2,\n    vector<int,2>        offset3,\n    vector<int,2>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Sampler2DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler2DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid Sampler2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Sampler2DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid Sampler2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Sampler2DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT Sampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT Sampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler2DMSArray<T>.subscript`\n\n## Signature \n\n```\nT Sampler2DMSArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler2DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler2DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RWSampler2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWSampler2DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid RWSampler2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWSampler2DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RWSampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RWSampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler2DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RWSampler2DMSArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler2DMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler2DMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RasterizerOrderedSampler2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler2DMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid RasterizerOrderedSampler2DMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSampler2DMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMSArray<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RasterizerOrderedSampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler2DMSArray<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,2>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler2DMSArray<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler2DMSArray<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct Sampler3D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat Sampler3D<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat Sampler3D<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler3D<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth);\nvoid Sampler3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             numberOfLevels);\nvoid Sampler3D<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth);\nvoid Sampler3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler3D<T>.Load(vector<int,4> location);\nT Sampler3D<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT Sampler3D<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.subscript`\n\n## Signature \n\n```\nT Sampler3D<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler3D<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT Sampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 3\nT Sampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp);\nT Sampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.SampleBias`\n\n## Signature \n\n```\nT Sampler3D<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\nT Sampler3D<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat Sampler3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat Sampler3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat Sampler3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat Sampler3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\nT Sampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset);\n/// See Availability 2\nT Sampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `Sampler3D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler3D<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT Sampler3D<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension Sampler3D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler3D.Gather(vector<float,3> location);\nvector<T,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler3D.GatherRed(vector<float,3> location);\nvector<T,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler3D.GatherGreen(vector<float,3> location);\nvector<T,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler3D.GatherBlue(vector<float,3> location);\nvector<T,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> Sampler3D.GatherAlpha(vector<float,3> location);\nvector<T,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler3D.Gather(vector<float,3> location);\nvector<float,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler3D.GatherRed(vector<float,3> location);\nvector<float,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler3D.GatherGreen(vector<float,3> location);\nvector<float,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler3D.GatherBlue(vector<float,3> location);\nvector<float,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> Sampler3D.GatherAlpha(vector<float,3> location);\nvector<float,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler3D.Gather(vector<float,3> location);\nvector<int,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler3D.GatherRed(vector<float,3> location);\nvector<int,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler3D.GatherGreen(vector<float,3> location);\nvector<int,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler3D.GatherBlue(vector<float,3> location);\nvector<int,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> Sampler3D.GatherAlpha(vector<float,3> location);\nvector<int,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension Sampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler3D.Gather(vector<float,3> location);\nvector<uint,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherRed(vector<float,3> location);\nvector<uint,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherGreen(vector<float,3> location);\nvector<uint,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherBlue(vector<float,3> location);\nvector<uint,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `Sampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherAlpha(vector<float,3> location);\nvector<uint,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> Sampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler3D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RWSampler3D<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RWSampler3D<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler3D<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth);\nvoid RWSampler3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             numberOfLevels);\nvoid RWSampler3D<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth);\nvoid RWSampler3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler3D<T>.Load(vector<int,3> location);\n/// See Availability 2\nT RWSampler3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset);\n/// See Availability 3\nT RWSampler3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** \n2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.subscript`\n\n## Signature \n\n```\nT RWSampler3D<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler3D<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT RWSampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 3\nT RWSampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp);\nT RWSampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.SampleBias`\n\n## Signature \n\n```\nT RWSampler3D<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\nT RWSampler3D<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RWSampler3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RWSampler3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RWSampler3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RWSampler3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\nT RWSampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset);\n/// See Availability 2\nT RWSampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler3D<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RWSampler3D<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler3D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler3D.Gather(vector<float,3> location);\nvector<T,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherRed(vector<float,3> location);\nvector<T,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherGreen(vector<float,3> location);\nvector<T,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherBlue(vector<float,3> location);\nvector<T,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherAlpha(vector<float,3> location);\nvector<T,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler3D.Gather(vector<float,3> location);\nvector<float,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherRed(vector<float,3> location);\nvector<float,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherGreen(vector<float,3> location);\nvector<float,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherBlue(vector<float,3> location);\nvector<float,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherAlpha(vector<float,3> location);\nvector<float,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler3D.Gather(vector<float,3> location);\nvector<int,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherRed(vector<float,3> location);\nvector<int,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherGreen(vector<float,3> location);\nvector<int,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherBlue(vector<float,3> location);\nvector<int,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherAlpha(vector<float,3> location);\nvector<int,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RWSampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler3D.Gather(vector<float,3> location);\nvector<uint,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherRed(vector<float,3> location);\nvector<uint,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherGreen(vector<float,3> location);\nvector<uint,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherBlue(vector<float,3> location);\nvector<uint,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RWSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherAlpha(vector<float,3> location);\nvector<uint,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RWSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler3D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `subscript`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler3D<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler3D<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler3D<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth);\nvoid RasterizerOrderedSampler3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler3D<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth);\nvoid RasterizerOrderedSampler3D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler3D<T>.Load(vector<int,3> location);\nT RasterizerOrderedSampler3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler3D<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler3D<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler3D<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT RasterizerOrderedSampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 3\nT RasterizerOrderedSampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp);\nT RasterizerOrderedSampler3D<T>.Sample(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSampler3D<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\nT RasterizerOrderedSampler3D<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedSampler3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\nfloat RasterizerOrderedSampler3D<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\n/// See Availability 1\nfloat RasterizerOrderedSampler3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n/// See Availability 2\nfloat RasterizerOrderedSampler3D<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.SampleGrad`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\nT RasterizerOrderedSampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler3D<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY,\n    vector<int,3>        offset,\n    float                lodClamp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n* `offset`\n* `lodClamp`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D<T>.SampleLevel`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler3D<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n/// See Availability 2\nT RasterizerOrderedSampler3D<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level,\n    vector<int,3>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `level`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler3D`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.Gather(vector<float,3> location);\nvector<T,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherRed(vector<float,3> location);\nvector<T,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherGreen(vector<float,3> location);\nvector<T,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherBlue(vector<float,3> location);\nvector<T,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherAlpha(vector<float,3> location);\nvector<T,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.Gather(vector<float,3> location);\nvector<float,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherRed(vector<float,3> location);\nvector<float,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherGreen(vector<float,3> location);\nvector<float,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherBlue(vector<float,3> location);\nvector<float,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherAlpha(vector<float,3> location);\nvector<float,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.Gather(vector<float,3> location);\nvector<int,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherRed(vector<float,3> location);\nvector<int,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherGreen(vector<float,3> location);\nvector<int,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherBlue(vector<float,3> location);\nvector<int,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherAlpha(vector<float,3> location);\nvector<int,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSampler3D`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.Gather(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherRed(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherGreen(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherBlue(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3D.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherAlpha(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSampler3D.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct Sampler3DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Sampler3DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Sampler3DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount);\nvoid Sampler3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid Sampler3DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount);\nvoid Sampler3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `Sampler3DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> Sampler3DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `Sampler3DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Sampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT Sampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT Sampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Sampler3DMS<T>.subscript`\n\n## Signature \n\n```\nT Sampler3DMS<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RWSampler3DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWSampler3DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWSampler3DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount);\nvoid RWSampler3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RWSampler3DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount);\nvoid RWSampler3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RWSampler3DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RWSampler3DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RWSampler3DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWSampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RWSampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT RWSampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWSampler3DMS<T>.subscript`\n\n## Signature \n\n```\nT RWSampler3DMS<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSampler3DMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3DMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSampler3DMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount);\nvoid RasterizerOrderedSampler3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             depth,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSampler3DMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount);\nvoid RasterizerOrderedSampler3DMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            depth,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `depth`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3DMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSampler3DMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3DMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RasterizerOrderedSampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedSampler3DMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSampler3DMS<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedSampler3DMS<T>.subscript(vector<uint,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `struct SamplerCube<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat SamplerCube<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat SamplerCube<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.GetDimensions`\n\n## Signature \n\n```\nvoid SamplerCube<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid SamplerCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid SamplerCube<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid SamplerCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT SamplerCube<T>.Load(vector<int,4> location);\nT SamplerCube<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT SamplerCube<T>.Load(\n    vector<int,4>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT SamplerCube<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT SamplerCube<T>.Sample(\n    vector<float,3>      location,\n    float                clamp);\nT SamplerCube<T>.Sample(\n    vector<float,3>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.SampleBias`\n\n## Signature \n\n```\nT SamplerCube<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.SampleCmp`\n\n## Signature \n\n```\nfloat SamplerCube<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\nfloat SamplerCube<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.SampleGrad`\n\n## Signature \n\n```\nT SamplerCube<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `SamplerCube<T>.SampleLevel`\n\n## Signature \n\n```\nT SamplerCube<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCube`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCube.Gather(vector<float,3> location);\nvector<T,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCube.GatherRed(vector<float,3> location);\nvector<T,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCube.GatherGreen(vector<float,3> location);\nvector<T,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCube.GatherBlue(vector<float,3> location);\nvector<T,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCube.GatherAlpha(vector<float,3> location);\nvector<T,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCube.Gather(vector<float,3> location);\nvector<float,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCube.GatherRed(vector<float,3> location);\nvector<float,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCube.GatherGreen(vector<float,3> location);\nvector<float,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCube.GatherBlue(vector<float,3> location);\nvector<float,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCube.GatherAlpha(vector<float,3> location);\nvector<float,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCube.Gather(vector<float,3> location);\nvector<int,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCube.GatherRed(vector<float,3> location);\nvector<int,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCube.GatherGreen(vector<float,3> location);\nvector<int,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCube.GatherBlue(vector<float,3> location);\nvector<int,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCube.GatherAlpha(vector<float,3> location);\nvector<int,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCube.Gather(vector<float,3> location);\nvector<uint,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherRed(vector<float,3> location);\nvector<uint,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherGreen(vector<float,3> location);\nvector<uint,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherBlue(vector<float,3> location);\nvector<uint,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherAlpha(vector<float,3> location);\nvector<uint,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSamplerCube<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Load`\n* `Sample`\n* `SampleBias`\n* `SampleCmp`\n* `SampleCmpLevelZero`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSamplerCube<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSamplerCube<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSamplerCube<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid RasterizerOrderedSamplerCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSamplerCube<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid RasterizerOrderedSamplerCube<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSamplerCube<T>.Load(vector<int,3> location);\nT RasterizerOrderedSamplerCube<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedSamplerCube<T>.Load(\n    vector<int,3>        location,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSamplerCube<T>.Sample(vector<float,3> location);\n/// See Availability 2\nT RasterizerOrderedSamplerCube<T>.Sample(\n    vector<float,3>      location,\n    float                clamp);\nT RasterizerOrderedSamplerCube<T>.Sample(\n    vector<float,3>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSamplerCube<T>.SampleBias(\n    vector<float,3>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.SampleCmp`\n\n## Signature \n\n```\nfloat RasterizerOrderedSamplerCube<T>.SampleCmp(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.SampleCmpLevelZero`\n\n## Signature \n\n```\nfloat RasterizerOrderedSamplerCube<T>.SampleCmpLevelZero(\n    SamplerComparisonState s,\n    vector<float,3>      location,\n    float                compareValue);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `s`\n* `location`\n* `compareValue`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.SampleGrad`\n\n## Signature \n\n```\nT RasterizerOrderedSamplerCube<T>.SampleGrad(\n    vector<float,3>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube<T>.SampleLevel`\n\n## Signature \n\n```\nT RasterizerOrderedSamplerCube<T>.SampleLevel(\n    vector<float,3>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCube`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.Gather(vector<float,3> location);\nvector<T,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherRed(vector<float,3> location);\nvector<T,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherGreen(vector<float,3> location);\nvector<T,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherBlue(vector<float,3> location);\nvector<T,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherAlpha(vector<float,3> location);\nvector<T,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.Gather(vector<float,3> location);\nvector<float,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherRed(vector<float,3> location);\nvector<float,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherGreen(vector<float,3> location);\nvector<float,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherBlue(vector<float,3> location);\nvector<float,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherAlpha(vector<float,3> location);\nvector<float,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.Gather(vector<float,3> location);\nvector<int,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherRed(vector<float,3> location);\nvector<int,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherGreen(vector<float,3> location);\nvector<int,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherBlue(vector<float,3> location);\nvector<int,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherAlpha(vector<float,3> location);\nvector<int,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCube`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.Gather(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.Gather(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherRed(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherRed(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherGreen(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherGreen(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherBlue(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherBlue(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCube.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherAlpha(vector<float,3> location);\nvector<uint,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCube.GatherAlpha(\n    vector<float,3>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct SamplerCubeMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid SamplerCubeMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid SamplerCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid SamplerCubeMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid SamplerCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> SamplerCubeMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT SamplerCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT SamplerCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT SamplerCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSamplerCubeMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n* `Load`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeMS<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSamplerCubeMS<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount);\nvoid RasterizerOrderedSamplerCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSamplerCubeMS<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            sampleCount);\nvoid RasterizerOrderedSamplerCubeMS<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeMS<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSamplerCubeMS<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeMS<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSamplerCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex);\nT RasterizerOrderedSamplerCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset);\n/// See Availability 2\nT RasterizerOrderedSamplerCubeMS<T>.Load(\n    vector<int,3>        location,\n    int                  sampleIndex,\n    vector<int,3>        offset,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `sampleIndex`\n* `offset`\n* `status`\n\n--------------------------------------------------------------------------------\n# `struct SamplerCubeArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Sample`\n* `SampleBias`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat SamplerCubeArray<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat SamplerCubeArray<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid SamplerCubeArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid SamplerCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid SamplerCubeArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid SamplerCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT SamplerCubeArray<T>.Sample(vector<float,4> location);\n/// See Availability 2\nT SamplerCubeArray<T>.Sample(\n    vector<float,4>      location,\n    float                clamp);\nT SamplerCubeArray<T>.Sample(\n    vector<float,4>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.SampleBias`\n\n## Signature \n\n```\nT SamplerCubeArray<T>.SampleBias(\n    vector<float,4>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.SampleGrad`\n\n## Signature \n\n```\nT SamplerCubeArray<T>.SampleGrad(\n    vector<float,4>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray<T>.SampleLevel`\n\n## Signature \n\n```\nT SamplerCubeArray<T>.SampleLevel(\n    vector<float,4>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCubeArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCubeArray.Gather(vector<float,4> location);\nvector<T,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherRed(vector<float,4> location);\nvector<T,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<T,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<T,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<T,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCubeArray.Gather(vector<float,4> location);\nvector<float,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherRed(vector<float,4> location);\nvector<float,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<float,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<float,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<float,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCubeArray.Gather(vector<float,4> location);\nvector<int,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherRed(vector<float,4> location);\nvector<int,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<int,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<int,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<int,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension SamplerCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.Gather(vector<float,4> location);\nvector<uint,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherRed(vector<float,4> location);\nvector<uint,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<uint,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<uint,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<uint,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> SamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSamplerCubeArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `CalculateLevelOfDetail`\n* `CalculateLevelOfDetailUnclamped`\n* `GetDimensions`\n* `Sample`\n* `SampleBias`\n* `SampleGrad`\n* `SampleLevel`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.CalculateLevelOfDetail`\n\n## Signature \n\n```\nfloat RasterizerOrderedSamplerCubeArray<T>.CalculateLevelOfDetail(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.CalculateLevelOfDetailUnclamped`\n\n## Signature \n\n```\nfloat RasterizerOrderedSamplerCubeArray<T>.CalculateLevelOfDetailUnclamped(vector<float,3> location);\n```\n\n## Parameters\n\n* `location`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSamplerCubeArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid RasterizerOrderedSamplerCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSamplerCubeArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid RasterizerOrderedSamplerCubeArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.Sample`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedSamplerCubeArray<T>.Sample(vector<float,4> location);\n/// See Availability 2\nT RasterizerOrderedSamplerCubeArray<T>.Sample(\n    vector<float,4>      location,\n    float                clamp);\nT RasterizerOrderedSamplerCubeArray<T>.Sample(\n    vector<float,4>      location,\n    float                clamp,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `clamp`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.SampleBias`\n\n## Signature \n\n```\nT RasterizerOrderedSamplerCubeArray<T>.SampleBias(\n    vector<float,4>      location,\n    float                bias);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `bias`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.SampleGrad`\n\n## Signature \n\n```\nT RasterizerOrderedSamplerCubeArray<T>.SampleGrad(\n    vector<float,4>      location,\n    vector<float,3>      gradX,\n    vector<float,3>      gradY);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `location`\n* `gradX`\n* `gradY`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray<T>.SampleLevel`\n\n## Signature \n\n```\nT RasterizerOrderedSamplerCubeArray<T>.SampleLevel(\n    vector<float,4>      location,\n    float                level);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `location`\n* `level`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCubeArray`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.Gather(vector<float,4> location);\nvector<T,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherRed(vector<float,4> location);\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<T,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.Gather(vector<float,4> location);\nvector<float,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherRed(vector<float,4> location);\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<float,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.Gather(vector<float,4> location);\nvector<int,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherRed(vector<float,4> location);\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<int,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `extension RasterizerOrderedSamplerCubeArray`\n\n## Methods\n\n* `Gather`\n* `GatherRed`\n* `GatherGreen`\n* `GatherBlue`\n* `GatherAlpha`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.Gather`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.Gather(vector<float,4> location);\nvector<uint,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.Gather(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherRed`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherRed(vector<float,4> location);\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherRed(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherGreen`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherGreen(vector<float,4> location);\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherGreen(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherBlue`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherBlue(vector<float,4> location);\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherBlue(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeArray.GatherAlpha`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(vector<float,4> location);\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset,\n    out uint             status);\n/// See Availability 1\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedSamplerCubeArray.GatherAlpha(\n    vector<float,4>      location,\n    vector<int,3>        offset1,\n    vector<int,3>        offset2,\n    vector<int,3>        offset3,\n    vector<int,3>        offset4,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `offset`\n* `status`\n* `offset1`\n* `offset2`\n* `offset3`\n* `offset4`\n\n--------------------------------------------------------------------------------\n# `struct SamplerCubeMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid SamplerCubeMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid SamplerCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid SamplerCubeMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid SamplerCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `SamplerCubeMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> SamplerCubeMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedSamplerCubeMSArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `GetSamplePosition`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeMSArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedSamplerCubeMSArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount);\nvoid RasterizerOrderedSamplerCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             sampleCount,\n    out uint             numberOfLevels);\nvoid RasterizerOrderedSamplerCubeMSArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount);\nvoid RasterizerOrderedSamplerCubeMSArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            sampleCount,\n    out float            numberOfLevels);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** \n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `sampleCount`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedSamplerCubeMSArray<T>.GetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> RasterizerOrderedSamplerCubeMSArray<T>.GetSamplePosition(int s);\n```\n\n## Parameters\n\n* `s`\n\n--------------------------------------------------------------------------------\n# `bit_cast`\n\n## Signature \n\n```\nT bit_cast<T, U>(U value);\n```\n\n## Parameters\n\n* `T`\n* `U`\n* `value`\n\n--------------------------------------------------------------------------------\n# `createDynamicObject`\n\n## Signature \n\n```\nT createDynamicObject<T, U>(\n    uint                 typeId,\n    U                    value);\n```\n\n## Parameters\n\n* `T`\n* `U`\n* `typeId`\n* `value`\n\n--------------------------------------------------------------------------------\n# `reinterpret`\n\n## Signature \n\n```\nT reinterpret<T, U>(U value);\n```\n\n## Parameters\n\n* `T`\n* `U`\n* `value`\n\n--------------------------------------------------------------------------------\n# `getStringHash`\n\n## Description\n\nGiven a string returns an integer hash of that string.\n\n## Signature \n\n```\nint getStringHash(String string);\n```\n\n## Parameters\n\n* `string`\n\n--------------------------------------------------------------------------------\n# `beginInvocationInterlock`\n\n## Description\n\nMark beginning of \"interlocked\" operations in a fragment shader.\n\n## Signature \n\n```\nvoid beginInvocationInterlock();\n```\n\n## Availability\n\n**GLSL** `GLSL420`, `GL_ARB_fragment_shader_interlock` **HLSL** \n\n--------------------------------------------------------------------------------\n# `endInvocationInterlock`\n\n## Description\n\nMark end of \"interlocked\" operations in a fragment shader.\n\n## Signature \n\n```\nvoid endInvocationInterlock();\n```\n\n## Availability\n\n**GLSL** `GLSL420`, `GL_ARB_fragment_shader_interlock` **HLSL** \n\n--------------------------------------------------------------------------------\n# enum _AttributeTargets\n\n## Values \n\n* _Struct_\n* _Var_\n* _Function_\n--------------------------------------------------------------------------------\n# `struct AppendStructuredBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `Append`\n* `GetDimensions`\n\n--------------------------------------------------------------------------------\n# `AppendStructuredBuffer<T>.Append`\n\n## Signature \n\n```\nvoid AppendStructuredBuffer<T>.Append(T value);\n```\n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `AppendStructuredBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid AppendStructuredBuffer<T>.GetDimensions(\n    out uint             numStructs,\n    out uint             stride);\n```\n\n## Parameters\n\n* `numStructs`\n* `stride`\n\n--------------------------------------------------------------------------------\n# `struct ByteAddressBuffer`\n\n## Methods\n\n* `GetDimensions`\n* `Load2`\n* `Load3`\n* `Load4`\n\n--------------------------------------------------------------------------------\n# `ByteAddressBuffer.GetDimensions`\n\n## Signature \n\n```\nvoid ByteAddressBuffer.GetDimensions(out uint dim);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dim`\n\n--------------------------------------------------------------------------------\n# `ByteAddressBuffer.Load2`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,2> ByteAddressBuffer.Load2(int location);\n/// See Availability 2\nvector<uint,2> ByteAddressBuffer.Load2(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `ByteAddressBuffer.Load3`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,3> ByteAddressBuffer.Load3(int location);\n/// See Availability 2\nvector<uint,3> ByteAddressBuffer.Load3(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `ByteAddressBuffer.Load4`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> ByteAddressBuffer.Load4(int location);\n/// See Availability 2\nvector<uint,4> ByteAddressBuffer.Load4(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `ByteAddressBuffer.Load`\n\n## Signature \n\n```\n/// See Availability 1\nuint ByteAddressBuffer.Load(int location);\n/// See Availability 2\nuint ByteAddressBuffer.Load(\n    int                  location,\n    out uint             status);\nT ByteAddressBuffer.Load<T>(int location);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `struct StructuredBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `StructuredBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid StructuredBuffer<T>.GetDimensions(\n    out uint             numStructs,\n    out uint             stride);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `numStructs`\n* `stride`\n\n--------------------------------------------------------------------------------\n# `StructuredBuffer<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT StructuredBuffer<T>.Load(int location);\n/// See Availability 2\nT StructuredBuffer<T>.Load(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `StructuredBuffer<T>.subscript`\n\n## Signature \n\n```\nT StructuredBuffer<T>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct ConsumeStructuredBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `Consume`\n* `GetDimensions`\n\n--------------------------------------------------------------------------------\n# `ConsumeStructuredBuffer<T>.Consume`\n\n## Signature \n\n```\nT ConsumeStructuredBuffer<T>.Consume();\n```\n\n--------------------------------------------------------------------------------\n# `ConsumeStructuredBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid ConsumeStructuredBuffer<T>.GetDimensions(\n    out uint             numStructs,\n    out uint             stride);\n```\n\n## Parameters\n\n* `numStructs`\n* `stride`\n\n--------------------------------------------------------------------------------\n# `struct InputPatch<T, N:int>`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `InputPatch<T, N:int>.subscript`\n\n## Signature \n\n```\nT InputPatch<T, N:int>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct OutputPatch<T, N:int>`\n\n## Generic Parameters\n\n* `T`\n* `N`\n\n## Methods\n\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `OutputPatch<T, N:int>.subscript`\n\n## Signature \n\n```\nT OutputPatch<T, N:int>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct RWByteAddressBuffer`\n\n## Methods\n\n* `GetDimensions`\n* `Load2`\n* `Load3`\n* `Load4`\n* `InterlockedAddF32`\n* `InterlockedAddI64`\n* `InterlockedCompareExchangeU64`\n* `InterlockedMaxU64`\n* `InterlockedMinU64`\n* `InterlockedAndU64`\n* `InterlockedOrU64`\n* `InterlockedXorU64`\n* `InterlockedExchangeU64`\n* `InterlockedAdd64`\n* `InterlockedCompareExchange64`\n* `InterlockedAdd`\n* `InterlockedAnd`\n* `InterlockedCompareExchange`\n* `InterlockedCompareStore`\n* `InterlockedExchange`\n* `InterlockedMax`\n* `InterlockedMin`\n* `InterlockedOr`\n* `InterlockedXor`\n* `Store2`\n* `Store3`\n* `Store4`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.GetDimensions`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.GetDimensions(out uint dim);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dim`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Load2`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,2> RWByteAddressBuffer.Load2(int location);\n/// See Availability 2\nvector<uint,2> RWByteAddressBuffer.Load2(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Load3`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,3> RWByteAddressBuffer.Load3(int location);\n/// See Availability 2\nvector<uint,3> RWByteAddressBuffer.Load3(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Load4`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RWByteAddressBuffer.Load4(int location);\n/// See Availability 2\nvector<uint,4> RWByteAddressBuffer.Load4(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Load`\n\n## Signature \n\n```\n/// See Availability 1\nuint RWByteAddressBuffer.Load(int location);\n/// See Availability 2\nuint RWByteAddressBuffer.Load(\n    int                  location,\n    out uint             status);\nT RWByteAddressBuffer.Load<T>(int location);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedAddF32`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedAddF32(\n    uint                 byteAddress,\n    float                valueToAdd,\n    out float            originalValue);\nvoid RWByteAddressBuffer.InterlockedAddF32(\n    uint                 byteAddress,\n    float                valueToAdd);\n```\n\n## Availability\n\n**HLSL** `NVAPI` **CUDA** `SM 2.0` \n\n## Parameters\n\n* `byteAddress`\n* `valueToAdd`\n* `originalValue`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedAddI64`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedAddI64(\n    uint                 byteAddress,\n    int64_t              valueToAdd,\n    out int64_t          originalValue);\nvoid RWByteAddressBuffer.InterlockedAddI64(\n    uint                 byteAddress,\n    int64_t              valueToAdd);\n```\n\n## Availability\n\n**HLSL** **CUDA** `SM 6.0` \n\n## Parameters\n\n* `byteAddress`\n* `valueToAdd`\n* `originalValue`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedCompareExchangeU64`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedCompareExchangeU64(\n    uint                 byteAddress,\n    uint64_t             compareValue,\n    uint64_t             value,\n    out uint64_t         outOriginalValue);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `byteAddress`\n* `compareValue`\n* `value`\n* `outOriginalValue`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedMaxU64`\n\n## Signature \n\n```\nuint64_t RWByteAddressBuffer.InterlockedMaxU64(\n    uint                 byteAddress,\n    uint64_t             value);\n```\n\n## Availability\n\n**HLSL** **CUDA** `SM 3.5` \n\n## Parameters\n\n* `byteAddress`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedMinU64`\n\n## Signature \n\n```\nuint64_t RWByteAddressBuffer.InterlockedMinU64(\n    uint                 byteAddress,\n    uint64_t             value);\n```\n\n## Availability\n\n**HLSL** **CUDA** `SM 3.5` \n\n## Parameters\n\n* `byteAddress`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedAndU64`\n\n## Signature \n\n```\nuint64_t RWByteAddressBuffer.InterlockedAndU64(\n    uint                 byteAddress,\n    uint64_t             value);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `byteAddress`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedOrU64`\n\n## Signature \n\n```\nuint64_t RWByteAddressBuffer.InterlockedOrU64(\n    uint                 byteAddress,\n    uint64_t             value);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `byteAddress`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedXorU64`\n\n## Signature \n\n```\nuint64_t RWByteAddressBuffer.InterlockedXorU64(\n    uint                 byteAddress,\n    uint64_t             value);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `byteAddress`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedExchangeU64`\n\n## Signature \n\n```\nuint64_t RWByteAddressBuffer.InterlockedExchangeU64(\n    uint                 byteAddress,\n    uint64_t             value);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `byteAddress`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedAdd64`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedAdd64(\n    uint                 byteAddress,\n    int64_t              valueToAdd,\n    out int64_t          outOriginalValue);\nvoid RWByteAddressBuffer.InterlockedAdd64(\n    uint                 byteAddress,\n    uint64_t             valueToAdd,\n    out uint64_t         outOriginalValue);\n```\n\n## Parameters\n\n* `byteAddress`\n* `valueToAdd`\n* `outOriginalValue`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedCompareExchange64`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedCompareExchange64(\n    uint                 byteAddress,\n    int64_t              compareValue,\n    int64_t              value,\n    out int64_t          outOriginalValue);\nvoid RWByteAddressBuffer.InterlockedCompareExchange64(\n    uint                 byteAddress,\n    uint64_t             compareValue,\n    uint64_t             value,\n    out uint64_t         outOriginalValue);\n```\n\n## Parameters\n\n* `byteAddress`\n* `compareValue`\n* `value`\n* `outOriginalValue`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedAdd`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedAdd(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RWByteAddressBuffer.InterlockedAdd(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedAnd`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedAnd(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RWByteAddressBuffer.InterlockedAnd(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedCompareExchange`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedCompareExchange(\n    uint                 dest,\n    uint                 compare_value,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `compare_value`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedCompareStore`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedCompareStore(\n    uint                 dest,\n    uint                 compare_value,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `compare_value`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedExchange`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedExchange(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedMax`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedMax(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RWByteAddressBuffer.InterlockedMax(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedMin`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedMin(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RWByteAddressBuffer.InterlockedMin(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedOr`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedOr(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RWByteAddressBuffer.InterlockedOr(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.InterlockedXor`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.InterlockedXor(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RWByteAddressBuffer.InterlockedXor(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Store2`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.Store2(\n    uint                 address,\n    vector<uint,2>       value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `address`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Store3`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.Store3(\n    uint                 address,\n    vector<uint,3>       value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `address`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Store4`\n\n## Signature \n\n```\nvoid RWByteAddressBuffer.Store4(\n    uint                 address,\n    vector<uint,4>       value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `address`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RWByteAddressBuffer.Store`\n\n## Signature \n\n```\n/// See Availability 1\nvoid RWByteAddressBuffer.Store(\n    uint                 address,\n    uint                 value);\n/// See Availability 2\nvoid RWByteAddressBuffer.Store<T>(\n    int                  offset,\n    T                    value);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `address`\n* `value`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedByteAddressBuffer`\n\n## Methods\n\n* `GetDimensions`\n* `Load2`\n* `Load3`\n* `Load4`\n* `InterlockedAdd`\n* `InterlockedAnd`\n* `InterlockedCompareExchange`\n* `InterlockedCompareStore`\n* `InterlockedExchange`\n* `InterlockedMax`\n* `InterlockedMin`\n* `InterlockedOr`\n* `InterlockedXor`\n* `Store2`\n* `Store3`\n* `Store4`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.GetDimensions(out uint dim);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dim`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Load2`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,2> RasterizerOrderedByteAddressBuffer.Load2(int location);\n/// See Availability 2\nvector<uint,2> RasterizerOrderedByteAddressBuffer.Load2(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Load3`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,3> RasterizerOrderedByteAddressBuffer.Load3(int location);\n/// See Availability 2\nvector<uint,3> RasterizerOrderedByteAddressBuffer.Load3(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Load4`\n\n## Signature \n\n```\n/// See Availability 1\nvector<uint,4> RasterizerOrderedByteAddressBuffer.Load4(int location);\n/// See Availability 2\nvector<uint,4> RasterizerOrderedByteAddressBuffer.Load4(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Load`\n\n## Signature \n\n```\n/// See Availability 1\nuint RasterizerOrderedByteAddressBuffer.Load(int location);\n/// See Availability 2\nuint RasterizerOrderedByteAddressBuffer.Load(\n    int                  location,\n    out uint             status);\nT RasterizerOrderedByteAddressBuffer.Load<T>(int location);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedAdd`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedAdd(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RasterizerOrderedByteAddressBuffer.InterlockedAdd(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedAnd`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedAnd(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RasterizerOrderedByteAddressBuffer.InterlockedAnd(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedCompareExchange`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedCompareExchange(\n    uint                 dest,\n    uint                 compare_value,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `compare_value`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedCompareStore`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedCompareStore(\n    uint                 dest,\n    uint                 compare_value,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `compare_value`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedExchange`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedExchange(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedMax`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedMax(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RasterizerOrderedByteAddressBuffer.InterlockedMax(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedMin`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedMin(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RasterizerOrderedByteAddressBuffer.InterlockedMin(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedOr`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedOr(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RasterizerOrderedByteAddressBuffer.InterlockedOr(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.InterlockedXor`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.InterlockedXor(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\nvoid RasterizerOrderedByteAddressBuffer.InterlockedXor(\n    uint                 dest,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Store2`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.Store2(\n    uint                 address,\n    vector<uint,2>       value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `address`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Store3`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.Store3(\n    uint                 address,\n    vector<uint,3>       value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `address`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Store4`\n\n## Signature \n\n```\nvoid RasterizerOrderedByteAddressBuffer.Store4(\n    uint                 address,\n    vector<uint,4>       value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `address`\n* `value`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedByteAddressBuffer.Store`\n\n## Signature \n\n```\n/// See Availability 1\nvoid RasterizerOrderedByteAddressBuffer.Store(\n    uint                 address,\n    uint                 value);\n/// See Availability 2\nvoid RasterizerOrderedByteAddressBuffer.Store<T>(\n    int                  offset,\n    T                    value);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `address`\n* `value`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `struct RWStructuredBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `DecrementCounter`\n* `GetDimensions`\n* `IncrementCounter`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWStructuredBuffer<T>.DecrementCounter`\n\n## Signature \n\n```\nuint RWStructuredBuffer<T>.DecrementCounter();\n```\n\n--------------------------------------------------------------------------------\n# `RWStructuredBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWStructuredBuffer<T>.GetDimensions(\n    out uint             numStructs,\n    out uint             stride);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `numStructs`\n* `stride`\n\n--------------------------------------------------------------------------------\n# `RWStructuredBuffer<T>.IncrementCounter`\n\n## Signature \n\n```\nuint RWStructuredBuffer<T>.IncrementCounter();\n```\n\n--------------------------------------------------------------------------------\n# `RWStructuredBuffer<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWStructuredBuffer<T>.Load(int location);\n/// See Availability 2\nT RWStructuredBuffer<T>.Load(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWStructuredBuffer<T>.subscript`\n\n## Signature \n\n```\nT RWStructuredBuffer<T>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedStructuredBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `DecrementCounter`\n* `GetDimensions`\n* `IncrementCounter`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedStructuredBuffer<T>.DecrementCounter`\n\n## Signature \n\n```\nuint RasterizerOrderedStructuredBuffer<T>.DecrementCounter();\n```\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedStructuredBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedStructuredBuffer<T>.GetDimensions(\n    out uint             numStructs,\n    out uint             stride);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `numStructs`\n* `stride`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedStructuredBuffer<T>.IncrementCounter`\n\n## Signature \n\n```\nuint RasterizerOrderedStructuredBuffer<T>.IncrementCounter();\n```\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedStructuredBuffer<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedStructuredBuffer<T>.Load(int location);\n/// See Availability 2\nT RasterizerOrderedStructuredBuffer<T>.Load(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedStructuredBuffer<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedStructuredBuffer<T>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct PointStream<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `Append`\n* `RestartStrip`\n\n--------------------------------------------------------------------------------\n# `PointStream<T>.Append`\n\n## Signature \n\n```\nvoid PointStream<T>.Append(T value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `PointStream<T>.RestartStrip`\n\n## Signature \n\n```\nvoid PointStream<T>.RestartStrip();\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n--------------------------------------------------------------------------------\n# `struct LineStream<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `Append`\n* `RestartStrip`\n\n--------------------------------------------------------------------------------\n# `LineStream<T>.Append`\n\n## Signature \n\n```\nvoid LineStream<T>.Append(T value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `LineStream<T>.RestartStrip`\n\n## Signature \n\n```\nvoid LineStream<T>.RestartStrip();\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n--------------------------------------------------------------------------------\n# `struct TriangleStream<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `Append`\n* `RestartStrip`\n\n--------------------------------------------------------------------------------\n# `TriangleStream<T>.Append`\n\n## Signature \n\n```\nvoid TriangleStream<T>.Append(T value);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `TriangleStream<T>.RestartStrip`\n\n## Signature \n\n```\nvoid TriangleStream<T>.RestartStrip();\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n--------------------------------------------------------------------------------\n# `abort`\n\n## Signature \n\n```\nvoid abort();\n```\n\n--------------------------------------------------------------------------------\n# `abs`\n\n## Signature \n\n```\n/// See Availability 1\nT abs<T>(T x);\n/// See Availability 2\nvector<T,N> abs<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> abs<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `acos`\n\n## Signature \n\n```\n/// See Availability 1\nT acos<T>(T x);\n/// See Availability 2\nvector<T,N> acos<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> acos<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `all`\n\n## Signature \n\n```\n/// See Availability 1\nbool all<T>(T x);\nbool all<T, N:int>(vector<T,N> x);\n/// See Availability 2\nbool all<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `AllMemoryBarrier`\n\n## Signature \n\n```\nvoid AllMemoryBarrier();\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `AllMemoryBarrierWithGroupSync`\n\n## Signature \n\n```\nvoid AllMemoryBarrierWithGroupSync();\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `any`\n\n## Signature \n\n```\n/// See Availability 1\nbool any<T>(T x);\nbool any<T, N:int>(vector<T,N> x);\n/// See Availability 2\nbool any<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `asdouble`\n\n## Signature \n\n```\ndouble asdouble(\n    uint                 lowbits,\n    uint                 highbits);\n```\n\n## Availability\n\n**GLSL** `GL_ARB_gpu_shader5` **HLSL** **SPIRV** \n\n## Parameters\n\n* `lowbits`\n* `highbits`\n\n--------------------------------------------------------------------------------\n# `asfloat`\n\n## Signature \n\n```\n/// See Availability 1\nfloat asfloat(int x);\nfloat asfloat(uint x);\nvector<float,N> asfloat<N:int>(vector<int,N> x);\nvector<float,N> asfloat<N:int>(vector<uint,N> x);\n/// See Availability 2\nmatrix<float,N,M> asfloat<N:int, M:int>(matrix<int,N,M> x);\nmatrix<float,N,M> asfloat<N:int, M:int>(matrix<uint,N,M> x);\nfloat asfloat(float x);\nvector<float,N> asfloat<N:int>(vector<float,N> x);\nmatrix<float,N,M> asfloat<N:int, M:int>(matrix<float,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `asin`\n\n## Signature \n\n```\n/// See Availability 1\nT asin<T>(T x);\n/// See Availability 2\nvector<T,N> asin<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> asin<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `asint`\n\n## Signature \n\n```\n/// See Availability 1\nint asint(float x);\nint asint(uint x);\nvector<int,N> asint<N:int>(vector<float,N> x);\nvector<int,N> asint<N:int>(vector<uint,N> x);\n/// See Availability 2\nmatrix<int,N,M> asint<N:int, M:int>(matrix<float,N,M> x);\nmatrix<int,N,M> asint<N:int, M:int>(matrix<uint,N,M> x);\nint asint(int x);\nvector<int,N> asint<N:int>(vector<int,N> x);\nmatrix<int,N,M> asint<N:int, M:int>(matrix<int,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `asuint`\n\n## Signature \n\n```\n/// See Availability 1\nvoid asuint(\n    double               value,\n    out uint             lowbits,\n    out uint             highbits);\n/// See Availability 2\nuint asuint(float x);\nuint asuint(int x);\nvector<uint,N> asuint<N:int>(vector<float,N> x);\nvector<uint,N> asuint<N:int>(vector<int,N> x);\n/// See Availability 3\nmatrix<uint,N,M> asuint<N:int, M:int>(matrix<float,N,M> x);\nmatrix<uint,N,M> asuint<N:int, M:int>(matrix<int,N,M> x);\nuint asuint(uint x);\nvector<uint,N> asuint<N:int>(vector<uint,N> x);\nmatrix<uint,N,M> asuint<N:int, M:int>(matrix<uint,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** `GL_ARB_gpu_shader5` **HLSL** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `N`\n* `M`\n* `value`\n* `lowbits`\n* `highbits`\n* `x`\n\n--------------------------------------------------------------------------------\n# `asuint16`\n\n## Signature \n\n```\n/// See Availability 1\nuint16_t asuint16(uint16_t value);\nvector<uint16_t,N> asuint16<N:int>(vector<uint16_t,N> value);\nmatrix<uint16_t,R,C> asuint16<R:int, C:int>(matrix<uint16_t,R,C> value);\nuint16_t asuint16(int16_t value);\nvector<uint16_t,N> asuint16<N:int>(vector<int16_t,N> value);\nmatrix<uint16_t,R,C> asuint16<R:int, C:int>(matrix<int16_t,R,C> value);\n/// See Availability 2\nuint16_t asuint16(half value);\n/// See Availability 1\nvector<uint16_t,N> asuint16<N:int>(vector<half,N> value);\nmatrix<uint16_t,R,C> asuint16<R:int, C:int>(matrix<half,R,C> value);\n```\n\n## Availability\n\n1. **HLSL** \n2. **GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `N`\n* `R`\n* `C`\n* `value`\n\n--------------------------------------------------------------------------------\n# `asint16`\n\n## Signature \n\n```\n/// See Availability 1\nint16_t asint16(int16_t value);\nvector<int16_t,N> asint16<N:int>(vector<int16_t,N> value);\nmatrix<int16_t,R,C> asint16<R:int, C:int>(matrix<int16_t,R,C> value);\nint16_t asint16(uint16_t value);\nvector<int16_t,N> asint16<N:int>(vector<uint16_t,N> value);\nmatrix<int16_t,R,C> asint16<R:int, C:int>(matrix<uint16_t,R,C> value);\n/// See Availability 2\nint16_t asint16(half value);\n/// See Availability 1\nvector<int16_t,N> asint16<N:int>(vector<half,N> value);\nmatrix<int16_t,R,C> asint16<R:int, C:int>(matrix<half,R,C> value);\n```\n\n## Availability\n\n1. **HLSL** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `N`\n* `R`\n* `C`\n* `value`\n\n--------------------------------------------------------------------------------\n# `asfloat16`\n\n## Signature \n\n```\n/// See Availability 1\nhalf asfloat16(half value);\nvector<half,N> asfloat16<N:int>(vector<half,N> value);\nmatrix<half,R,C> asfloat16<R:int, C:int>(matrix<half,R,C> value);\n/// See Availability 2\nhalf asfloat16(uint16_t value);\n/// See Availability 1\nvector<half,N> asfloat16<N:int>(vector<uint16_t,N> value);\nmatrix<half,R,C> asfloat16<R:int, C:int>(matrix<uint16_t,R,C> value);\n/// See Availability 3\nhalf asfloat16(int16_t value);\n/// See Availability 1\nvector<half,N> asfloat16<N:int>(vector<int16_t,N> value);\nmatrix<half,R,C> asfloat16<R:int, C:int>(matrix<int16_t,R,C> value);\n```\n\n## Availability\n\n1. **HLSL** \n2. **GLSL** **HLSL** **CUDA** \n3. **HLSL** **CUDA** \n\n## Parameters\n\n* `N`\n* `R`\n* `C`\n* `value`\n\n--------------------------------------------------------------------------------\n# `atan`\n\n## Signature \n\n```\n/// See Availability 1\nT atan<T>(T x);\n/// See Availability 2\nvector<T,N> atan<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> atan<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `atan2`\n\n## Signature \n\n```\n/// See Availability 1\nT atan2<T>(\n    T                    y,\n    T                    x);\n/// See Availability 2\nvector<T,N> atan2<T, N:int>(\n    vector<T,N>          y,\n    vector<T,N>          x);\n/// See Availability 3\nmatrix<T,N,M> atan2<T, N:int, M:int>(\n    matrix<T,N,M>        y,\n    matrix<T,N,M>        x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `y`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ceil`\n\n## Signature \n\n```\n/// See Availability 1\nT ceil<T>(T x);\n/// See Availability 2\nvector<T,N> ceil<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> ceil<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `CheckAccessFullyMapped`\n\n## Signature \n\n```\nbool CheckAccessFullyMapped(uint status);\n```\n\n## Parameters\n\n* `status`\n\n--------------------------------------------------------------------------------\n# `clamp`\n\n## Signature \n\n```\n/// See Availability 1\nT clamp<T>(\n    T                    x,\n    T                    minBound,\n    T                    maxBound);\nvector<T,N> clamp<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          minBound,\n    vector<T,N>          maxBound);\n/// See Availability 2\nmatrix<T,N,M> clamp<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        minBound,\n    matrix<T,N,M>        maxBound);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `minBound`\n* `maxBound`\n\n--------------------------------------------------------------------------------\n# `clip`\n\n## Signature \n\n```\nvoid clip<T>(T x);\nvoid clip<T, N:int>(vector<T,N> x);\nvoid clip<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `cos`\n\n## Signature \n\n```\n/// See Availability 1\nT cos<T>(T x);\n/// See Availability 2\nvector<T,N> cos<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> cos<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `cosh`\n\n## Signature \n\n```\n/// See Availability 1\nT cosh<T>(T x);\n/// See Availability 2\nvector<T,N> cosh<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> cosh<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `countbits`\n\n## Signature \n\n```\nuint countbits(uint value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CPP** **CUDA** \n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `cross`\n\n## Signature \n\n```\nvector<T,3> cross<T>(\n    vector<T,3>          left,\n    vector<T,3>          right);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `left`\n* `right`\n\n--------------------------------------------------------------------------------\n# `D3DCOLORtoUBYTE4`\n\n## Signature \n\n```\nvector<int,4> D3DCOLORtoUBYTE4(vector<float,4> color);\n```\n\n## Parameters\n\n* `color`\n\n--------------------------------------------------------------------------------\n# `ddx`\n\n## Signature \n\n```\n/// See Availability 1\nT ddx<T>(T x);\nvector<T,N> ddx<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> ddx<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ddx_coarse`\n\n## Signature \n\n```\n/// See Availability 1\nT ddx_coarse<T>(T x);\nvector<T,N> ddx_coarse<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> ddx_coarse<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** `GL_ARB_derivative_control` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ddx_fine`\n\n## Signature \n\n```\n/// See Availability 1\nT ddx_fine<T>(T x);\nvector<T,N> ddx_fine<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> ddx_fine<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** `GL_ARB_derivative_control` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ddy`\n\n## Signature \n\n```\n/// See Availability 1\nT ddy<T>(T x);\nvector<T,N> ddy<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> ddy<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ddy_coarse`\n\n## Signature \n\n```\n/// See Availability 1\nT ddy_coarse<T>(T x);\nvector<T,N> ddy_coarse<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> ddy_coarse<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** `GL_ARB_derivative_control` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ddy_fine`\n\n## Signature \n\n```\n/// See Availability 1\nT ddy_fine<T>(T x);\nvector<T,N> ddy_fine<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> ddy_fine<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** `GL_ARB_derivative_control` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `degrees`\n\n## Signature \n\n```\n/// See Availability 1\nT degrees<T>(T x);\nvector<T,N> degrees<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> degrees<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `determinant`\n\n## Signature \n\n```\nT determinant<T, N:int>(matrix<T,N,N> m);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `N`\n* `m`\n\n--------------------------------------------------------------------------------\n# `DeviceMemoryBarrier`\n\n## Signature \n\n```\nvoid DeviceMemoryBarrier();\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `DeviceMemoryBarrierWithGroupSync`\n\n## Signature \n\n```\nvoid DeviceMemoryBarrierWithGroupSync();\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n--------------------------------------------------------------------------------\n# `distance`\n\n## Signature \n\n```\nT distance<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `N`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `dot`\n\n## Signature \n\n```\nT dot<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `dst`\n\n## Signature \n\n```\nvector<T,4> dst<T>(\n    vector<T,4>          x,\n    vector<T,4>          y);\n```\n\n## Parameters\n\n* `T`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `EvaluateAttributeAtCentroid`\n\n## Signature \n\n```\n/// See Availability 1\nT EvaluateAttributeAtCentroid<T>(T x);\nvector<T,N> EvaluateAttributeAtCentroid<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> EvaluateAttributeAtCentroid<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `EvaluateAttributeAtSample`\n\n## Signature \n\n```\n/// See Availability 1\nT EvaluateAttributeAtSample<T>(\n    T                    x,\n    uint                 sampleindex);\nvector<T,N> EvaluateAttributeAtSample<T, N:int>(\n    vector<T,N>          x,\n    uint                 sampleindex);\n/// See Availability 2\nmatrix<T,N,M> EvaluateAttributeAtSample<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    uint                 sampleindex);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `sampleindex`\n\n--------------------------------------------------------------------------------\n# `EvaluateAttributeSnapped`\n\n## Signature \n\n```\n/// See Availability 1\nT EvaluateAttributeSnapped<T>(\n    T                    x,\n    vector<int,2>        offset);\nvector<T,N> EvaluateAttributeSnapped<T, N:int>(\n    vector<T,N>          x,\n    vector<int,2>        offset);\n/// See Availability 2\nmatrix<T,N,M> EvaluateAttributeSnapped<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    vector<int,2>        offset);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `offset`\n\n--------------------------------------------------------------------------------\n# `exp`\n\n## Signature \n\n```\n/// See Availability 1\nT exp<T>(T x);\n/// See Availability 2\nvector<T,N> exp<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> exp<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `exp2`\n\n## Signature \n\n```\n/// See Availability 1\nT exp2<T>(T x);\n/// See Availability 2\nvector<T,N> exp2<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> exp2<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `f32tof16`\n\n## Signature \n\n```\n/// See Availability 1\nuint f32tof16(float value);\n/// See Availability 2\nvector<uint,N> f32tof16<N:int>(vector<float,N> value);\n```\n\n## Availability\n\n1. **GLSL** `GLSL420` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `N`\n* `value`\n\n--------------------------------------------------------------------------------\n# `f16tof32`\n\n## Signature \n\n```\n/// See Availability 1\nfloat f16tof32(uint value);\n/// See Availability 2\nvector<float,N> f16tof32<N:int>(vector<uint,N> value);\n/// See Availability 3\nfloat f16tof32(half value);\n/// See Availability 4\nvector<float,N> f16tof32<N:int>(vector<half,N> value);\n```\n\n## Availability\n\n1. **GLSL** `GLSL420` **HLSL** \n2. **HLSL** \n3. **GLSL** `GLSL420` **HLSL** **CUDA** \n4. **HLSL** **CUDA** \n\n## Parameters\n\n* `N`\n* `value`\n\n--------------------------------------------------------------------------------\n# `f32tof16_`\n\n## Signature \n\n```\n/// See Availability 1\nhalf f32tof16_(float value);\n/// See Availability 2\nvector<half,N> f32tof16_<N:int>(vector<float,N> value);\n```\n\n## Availability\n\n1. **GLSL** `GLSL420` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `N`\n* `value`\n\n--------------------------------------------------------------------------------\n# `faceforward`\n\n## Signature \n\n```\nvector<T,N> faceforward<T, N:int>(\n    vector<T,N>          n,\n    vector<T,N>          i,\n    vector<T,N>          ng);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `n`\n* `i`\n* `ng`\n\n--------------------------------------------------------------------------------\n# `firstbithigh`\n\n## Signature \n\n```\n/// See Availability 1\nint firstbithigh(int value);\n/// See Availability 2\nvector<int,N> firstbithigh<N:int>(vector<int,N> value);\n/// See Availability 1\nuint firstbithigh(uint value);\n/// See Availability 2\nvector<uint,N> firstbithigh<N:int>(vector<uint,N> value);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `N`\n* `value`\n\n--------------------------------------------------------------------------------\n# `firstbitlow`\n\n## Signature \n\n```\n/// See Availability 1\nint firstbitlow(int value);\n/// See Availability 2\nvector<int,N> firstbitlow<N:int>(vector<int,N> value);\n/// See Availability 1\nuint firstbitlow(uint value);\n/// See Availability 2\nvector<uint,N> firstbitlow<N:int>(vector<uint,N> value);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `N`\n* `value`\n\n--------------------------------------------------------------------------------\n# `floor`\n\n## Signature \n\n```\n/// See Availability 1\nT floor<T>(T x);\n/// See Availability 2\nvector<T,N> floor<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> floor<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `fma`\n\n## Signature \n\n```\n/// See Availability 1\ndouble fma(\n    double               a,\n    double               b,\n    double               c);\n/// See Availability 2\nvector<double,N> fma<N:int>(\n    vector<double,N>     a,\n    vector<double,N>     b,\n    vector<double,N>     c);\n/// See Availability 3\nmatrix<double,N,M> fma<N:int, M:int>(\n    matrix<double,N,M>   a,\n    matrix<double,N,M>   b,\n    matrix<double,N,M>   c);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `N`\n* `M`\n* `a`\n* `b`\n* `c`\n\n--------------------------------------------------------------------------------\n# `fmod`\n\n## Signature \n\n```\n/// See Availability 1\nT fmod<T>(\n    T                    x,\n    T                    y);\n/// See Availability 2\nvector<T,N> fmod<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\nmatrix<T,N,M> fmod<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        y);\n```\n\n## Availability\n\n1. **HLSL** **CPP** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `frac`\n\n## Signature \n\n```\n/// See Availability 1\nT frac<T>(T x);\n/// See Availability 2\nvector<T,N> frac<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> frac<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `frexp`\n\n## Signature \n\n```\n/// See Availability 1\nT frexp<T>(\n    T                    x,\n    out T                exp);\nvector<T,N> frexp<T, N:int>(\n    vector<T,N>          x,\n    out vector<T,N>      exp);\n/// See Availability 2\nmatrix<T,N,M> frexp<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    out matrix<T,N,M>    exp);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `exp`\n\n--------------------------------------------------------------------------------\n# `fwidth`\n\n## Signature \n\n```\n/// See Availability 1\nT fwidth<T>(T x);\n/// See Availability 2\nvector<T,N> fwidth<T, N:int>(vector<T,N> x);\n/// See Availability 1\nmatrix<T,N,M> fwidth<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **HLSL** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `GetAttributeAtVertex`\n\n## Description\n\n Get the value of a vertex attribute at a specific vertex.\n\n The `GetAttributeAtVertex()` function can be used in a fragment shader\n to get the value of the given `attribute` at the vertex of the primitive\n that corresponds to the given `vertexIndex`.\n\n Note that the `attribute` must have been a declared varying input to\n the fragment shader with the `nointerpolation` modifier.\n\n This function can be applied to scalars, vectors, and matrices of\n built-in scalar types.\n\n Note: these functions are not curently implemented for Vulkan/SPIR-V output.\n\n## Signature \n\n```\nT GetAttributeAtVertex<T>(\n    T                    attribute,\n    uint                 vertexIndex);\nvector<T,N> GetAttributeAtVertex<T, N:int>(\n    vector<T,N>          attribute,\n    uint                 vertexIndex);\nmatrix<T,N,M> GetAttributeAtVertex<T, N:int, M:int>(\n    matrix<T,N,M>        attribute,\n    uint                 vertexIndex);\n```\n\n## Availability\n\n**GLSL** `GLSL450`, `GL_NV_fragment_shader_barycentric` **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `attribute`\n* `vertexIndex`\n\n--------------------------------------------------------------------------------\n# `GetRenderTargetSampleCount`\n\n## Signature \n\n```\nuint GetRenderTargetSampleCount();\n```\n\n--------------------------------------------------------------------------------\n# `GetRenderTargetSamplePosition`\n\n## Signature \n\n```\nvector<float,2> GetRenderTargetSamplePosition(int Index);\n```\n\n## Parameters\n\n* `Index`\n\n--------------------------------------------------------------------------------\n# `GroupMemoryBarrier`\n\n## Signature \n\n```\nvoid GroupMemoryBarrier();\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `GroupMemoryBarrierWithGroupSync`\n\n## Signature \n\n```\nvoid GroupMemoryBarrierWithGroupSync();\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `InterlockedAdd`\n\n## Signature \n\n```\nvoid InterlockedAdd(\n    int                  dest,\n    int                  value);\nvoid InterlockedAdd(\n    uint                 dest,\n    uint                 value);\nvoid InterlockedAdd(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedAdd(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedAnd`\n\n## Signature \n\n```\nvoid InterlockedAnd(\n    int                  dest,\n    int                  value);\nvoid InterlockedAnd(\n    uint                 dest,\n    uint                 value);\nvoid InterlockedAnd(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedAnd(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedCompareExchange`\n\n## Signature \n\n```\nvoid InterlockedCompareExchange(\n    int                  dest,\n    int                  compare_value,\n    int                  value,\n    out int              original_value);\nvoid InterlockedCompareExchange(\n    uint                 dest,\n    uint                 compare_value,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `compare_value`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedCompareStore`\n\n## Signature \n\n```\nvoid InterlockedCompareStore(\n    int                  dest,\n    int                  compare_value,\n    int                  value);\nvoid InterlockedCompareStore(\n    uint                 dest,\n    uint                 compare_value,\n    uint                 value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `compare_value`\n* `value`\n\n--------------------------------------------------------------------------------\n# `InterlockedExchange`\n\n## Signature \n\n```\nvoid InterlockedExchange(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedExchange(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedMax`\n\n## Signature \n\n```\nvoid InterlockedMax(\n    int                  dest,\n    int                  value);\nvoid InterlockedMax(\n    uint                 dest,\n    uint                 value);\nvoid InterlockedMax(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedMax(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedMin`\n\n## Signature \n\n```\nvoid InterlockedMin(\n    int                  dest,\n    int                  value);\nvoid InterlockedMin(\n    uint                 dest,\n    uint                 value);\nvoid InterlockedMin(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedMin(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedOr`\n\n## Signature \n\n```\nvoid InterlockedOr(\n    int                  dest,\n    int                  value);\nvoid InterlockedOr(\n    uint                 dest,\n    uint                 value);\nvoid InterlockedOr(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedOr(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `InterlockedXor`\n\n## Signature \n\n```\nvoid InterlockedXor(\n    int                  dest,\n    int                  value);\nvoid InterlockedXor(\n    uint                 dest,\n    uint                 value);\nvoid InterlockedXor(\n    int                  dest,\n    int                  value,\n    out int              original_value);\nvoid InterlockedXor(\n    uint                 dest,\n    uint                 value,\n    out uint             original_value);\n```\n\n## Availability\n\n**GLSL** **HLSL** **CUDA** \n\n## Parameters\n\n* `dest`\n* `value`\n* `original_value`\n\n--------------------------------------------------------------------------------\n# `isfinite`\n\n## Signature \n\n```\n/// See Availability 1\nbool isfinite<T>(T x);\n/// See Availability 2\nvector<bool,N> isfinite<T, N:int>(vector<T,N> x);\nmatrix<bool,N,M> isfinite<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **HLSL** **CPP** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `isinf`\n\n## Signature \n\n```\n/// See Availability 1\nbool isinf<T>(T x);\n/// See Availability 2\nvector<bool,N> isinf<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<bool,N,M> isinf<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CPP** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `isnan`\n\n## Signature \n\n```\n/// See Availability 1\nbool isnan<T>(T x);\n/// See Availability 2\nvector<bool,N> isnan<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<bool,N,M> isnan<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CPP** **CUDA** \n2. **GLSL** **HLSL** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `ldexp`\n\n## Signature \n\n```\n/// See Availability 1\nT ldexp<T>(\n    T                    x,\n    T                    exp);\nvector<T,N> ldexp<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          exp);\n/// See Availability 2\nmatrix<T,N,M> ldexp<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        exp);\n```\n\n## Availability\n\n1. **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `exp`\n\n--------------------------------------------------------------------------------\n# `length`\n\n## Signature \n\n```\nT length<T, N:int>(vector<T,N> x);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `N`\n* `x`\n\n--------------------------------------------------------------------------------\n# `lerp`\n\n## Signature \n\n```\n/// See Availability 1\nT lerp<T>(\n    T                    x,\n    T                    y,\n    T                    s);\nvector<T,N> lerp<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y,\n    vector<T,N>          s);\n/// See Availability 2\nmatrix<T,N,M> lerp<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        y,\n    matrix<T,N,M>        s);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `y`\n* `s`\n\n--------------------------------------------------------------------------------\n# `lit`\n\n## Signature \n\n```\nvector<float,4> lit(\n    float                n_dot_l,\n    float                n_dot_h,\n    float                m);\n```\n\n## Parameters\n\n* `n_dot_l`\n* `n_dot_h`\n* `m`\n\n--------------------------------------------------------------------------------\n# `log`\n\n## Signature \n\n```\n/// See Availability 1\nT log<T>(T x);\n/// See Availability 2\nvector<T,N> log<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> log<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `log10`\n\n## Signature \n\n```\n/// See Availability 1\nT log10<T>(T x);\n/// See Availability 2\nvector<T,N> log10<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> log10<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `log2`\n\n## Signature \n\n```\n/// See Availability 1\nT log2<T>(T x);\n/// See Availability 2\nvector<T,N> log2<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> log2<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `mad`\n\n## Signature \n\n```\n/// See Availability 1\nT mad<T>(\n    T                    mvalue,\n    T                    avalue,\n    T                    bvalue);\n/// See Availability 2\nvector<T,N> mad<T, N:int>(\n    vector<T,N>          mvalue,\n    vector<T,N>          avalue,\n    vector<T,N>          bvalue);\n/// See Availability 3\nmatrix<T,N,M> mad<T, N:int, M:int>(\n    matrix<T,N,M>        mvalue,\n    matrix<T,N,M>        avalue,\n    matrix<T,N,M>        bvalue);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mvalue`\n* `avalue`\n* `bvalue`\n\n--------------------------------------------------------------------------------\n# `max`\n\n## Signature \n\n```\n/// See Availability 1\nT max<T>(\n    T                    x,\n    T                    y);\n/// See Availability 2\nvector<T,N> max<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\n/// See Availability 3\nmatrix<T,N,M> max<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        y);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `min`\n\n## Signature \n\n```\n/// See Availability 1\nT min<T>(\n    T                    x,\n    T                    y);\n/// See Availability 2\nvector<T,N> min<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\n/// See Availability 3\nmatrix<T,N,M> min<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        y);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `modf`\n\n## Signature \n\n```\n/// See Availability 1\nT modf<T>(\n    T                    x,\n    out T                ip);\n/// See Availability 2\nvector<T,N> modf<T, N:int>(\n    vector<T,N>          x,\n    out vector<T,N>      ip);\n/// See Availability 1\nmatrix<T,N,M> modf<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    out matrix<T,N,M>    ip);\n```\n\n## Availability\n\n1. **HLSL** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `ip`\n\n--------------------------------------------------------------------------------\n# `msad4`\n\n## Signature \n\n```\nvector<uint,4> msad4(\n    uint                 reference,\n    vector<uint,2>       source,\n    vector<uint,4>       accum);\n```\n\n## Parameters\n\n* `reference`\n* `source`\n* `accum`\n\n--------------------------------------------------------------------------------\n# `mul`\n\n## Signature \n\n```\n/// See Availability 1\nT mul<T>(\n    T                    x,\n    T                    y);\nvector<T,N> mul<T, N:int>(\n    vector<T,N>          x,\n    T                    y);\nvector<T,N> mul<T, N:int>(\n    T                    x,\n    vector<T,N>          y);\nmatrix<T,N,M> mul<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    T                    y);\nmatrix<T,N,M> mul<T, N:int, M:int>(\n    T                    x,\n    matrix<T,N,M>        y);\n/// See Availability 2\nT mul<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\nvector<T,M> mul<T, N:int, M:int>(\n    vector<T,N>          left,\n    matrix<T,N,M>        right);\nvector<T,N> mul<T, N:int, M:int>(\n    matrix<T,N,M>        left,\n    vector<T,M>          right);\nmatrix<T,R,C> mul<T, R:int, N:int, C:int>(\n    matrix<T,R,N>        right,\n    matrix<T,N,C>        left);\n```\n\n## Availability\n\n1. **HLSL** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `R`\n* `C`\n* `x`\n* `y`\n* `left`\n* `right`\n\n--------------------------------------------------------------------------------\n# `noise`\n\n## Signature \n\n```\nfloat noise(float x);\nfloat noise<N:int>(vector<float,N> x);\n```\n\n## Parameters\n\n* `N`\n* `x`\n\n--------------------------------------------------------------------------------\n# `NonUniformResourceIndex`\n\n## Signature \n\n```\nuint NonUniformResourceIndex(uint index);\nint NonUniformResourceIndex(int index);\n```\n\n## Availability\n\n**GLSL** `GL_EXT_nonuniform_qualifier` **HLSL** \n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `normalize`\n\n## Signature \n\n```\nvector<T,N> normalize<T, N:int>(vector<T,N> x);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `N`\n* `x`\n\n--------------------------------------------------------------------------------\n# `pow`\n\n## Signature \n\n```\n/// See Availability 1\nT pow<T>(\n    T                    x,\n    T                    y);\n/// See Availability 2\nvector<T,N> pow<T, N:int>(\n    vector<T,N>          x,\n    vector<T,N>          y);\n/// See Availability 3\nmatrix<T,N,M> pow<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    matrix<T,N,M>        y);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `y`\n\n--------------------------------------------------------------------------------\n# `Process2DQuadTessFactorsAvg`\n\n## Signature \n\n```\nvoid Process2DQuadTessFactorsAvg(\n    in vector<float,4>   RawEdgeFactors,\n    in vector<float,2>   InsideScale,\n    out vector<float,4>  RoundedEdgeTessFactors,\n    out vector<float,2>  RoundedInsideTessFactors,\n    out vector<float,2>  UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `Process2DQuadTessFactorsMax`\n\n## Signature \n\n```\nvoid Process2DQuadTessFactorsMax(\n    in vector<float,4>   RawEdgeFactors,\n    in vector<float,2>   InsideScale,\n    out vector<float,4>  RoundedEdgeTessFactors,\n    out vector<float,2>  RoundedInsideTessFactors,\n    out vector<float,2>  UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `Process2DQuadTessFactorsMin`\n\n## Signature \n\n```\nvoid Process2DQuadTessFactorsMin(\n    in vector<float,4>   RawEdgeFactors,\n    in vector<float,2>   InsideScale,\n    out vector<float,4>  RoundedEdgeTessFactors,\n    out vector<float,2>  RoundedInsideTessFactors,\n    out vector<float,2>  UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `ProcessIsolineTessFactors`\n\n## Signature \n\n```\nvoid ProcessIsolineTessFactors(\n    in float             RawDetailFactor,\n    in float             RawDensityFactor,\n    out float            RoundedDetailFactor,\n    out float            RoundedDensityFactor);\n```\n\n## Parameters\n\n* `RawDetailFactor`\n* `RawDensityFactor`\n* `RoundedDetailFactor`\n* `RoundedDensityFactor`\n\n--------------------------------------------------------------------------------\n# `ProcessQuadTessFactorsAvg`\n\n## Signature \n\n```\nvoid ProcessQuadTessFactorsAvg(\n    in vector<float,4>   RawEdgeFactors,\n    in float             InsideScale,\n    out vector<float,4>  RoundedEdgeTessFactors,\n    out vector<float,2>  RoundedInsideTessFactors,\n    out vector<float,2>  UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `ProcessQuadTessFactorsMax`\n\n## Signature \n\n```\nvoid ProcessQuadTessFactorsMax(\n    in vector<float,4>   RawEdgeFactors,\n    in float             InsideScale,\n    out vector<float,4>  RoundedEdgeTessFactors,\n    out vector<float,2>  RoundedInsideTessFactors,\n    out vector<float,2>  UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `ProcessQuadTessFactorsMin`\n\n## Signature \n\n```\nvoid ProcessQuadTessFactorsMin(\n    in vector<float,4>   RawEdgeFactors,\n    in float             InsideScale,\n    out vector<float,4>  RoundedEdgeTessFactors,\n    out vector<float,2>  RoundedInsideTessFactors,\n    out vector<float,2>  UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `ProcessTriTessFactorsAvg`\n\n## Signature \n\n```\nvoid ProcessTriTessFactorsAvg(\n    in vector<float,3>   RawEdgeFactors,\n    in float             InsideScale,\n    out vector<float,3>  RoundedEdgeTessFactors,\n    out float            RoundedInsideTessFactor,\n    out float            UnroundedInsideTessFactor);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactor`\n* `UnroundedInsideTessFactor`\n\n--------------------------------------------------------------------------------\n# `ProcessTriTessFactorsMax`\n\n## Signature \n\n```\nvoid ProcessTriTessFactorsMax(\n    in vector<float,3>   RawEdgeFactors,\n    in float             InsideScale,\n    out vector<float,3>  RoundedEdgeTessFactors,\n    out float            RoundedInsideTessFactor,\n    out float            UnroundedInsideTessFactor);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactor`\n* `UnroundedInsideTessFactor`\n\n--------------------------------------------------------------------------------\n# `ProcessTriTessFactorsMin`\n\n## Signature \n\n```\nvoid ProcessTriTessFactorsMin(\n    in vector<float,3>   RawEdgeFactors,\n    in float             InsideScale,\n    out vector<float,3>  RoundedEdgeTessFactors,\n    out float            RoundedInsideTessFactors,\n    out float            UnroundedInsideTessFactors);\n```\n\n## Parameters\n\n* `RawEdgeFactors`\n* `InsideScale`\n* `RoundedEdgeTessFactors`\n* `RoundedInsideTessFactors`\n* `UnroundedInsideTessFactors`\n\n--------------------------------------------------------------------------------\n# `radians`\n\n## Signature \n\n```\n/// See Availability 1\nT radians<T>(T x);\nvector<T,N> radians<T, N:int>(vector<T,N> x);\n/// See Availability 2\nmatrix<T,N,M> radians<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `rcp`\n\n## Signature \n\n```\nT rcp<T>(T x);\nvector<T,N> rcp<T, N:int>(vector<T,N> x);\nmatrix<T,N,M> rcp<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `reflect`\n\n## Signature \n\n```\nvector<T,N> reflect<T, N:int>(\n    vector<T,N>          i,\n    vector<T,N>          n);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `N`\n* `i`\n* `n`\n\n--------------------------------------------------------------------------------\n# `refract`\n\n## Signature \n\n```\nvector<T,N> refract<T, N:int>(\n    vector<T,N>          i,\n    vector<T,N>          n,\n    T                    eta);\n```\n\n## Availability\n\n**GLSL** **HLSL** **SPIRV** \n\n## Parameters\n\n* `T`\n* `N`\n* `i`\n* `n`\n* `eta`\n\n--------------------------------------------------------------------------------\n# `reversebits`\n\n## Signature \n\n```\n/// See Availability 1\nuint reversebits(uint value);\n/// See Availability 2\nvector<uint,N> reversebits<N:int>(vector<uint,N> value);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **CPP** **CUDA** \n2. **GLSL** **HLSL** \n\n## Parameters\n\n* `N`\n* `value`\n\n--------------------------------------------------------------------------------\n# `round`\n\n## Signature \n\n```\n/// See Availability 1\nT round<T>(T x);\n/// See Availability 2\nvector<T,N> round<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> round<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `rsqrt`\n\n## Signature \n\n```\n/// See Availability 1\nT rsqrt<T>(T x);\n/// See Availability 2\nvector<T,N> rsqrt<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> rsqrt<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `saturate`\n\n## Signature \n\n```\nT saturate<T>(T x);\nvector<T,N> saturate<T, N:int>(vector<T,N> x);\nmatrix<T,N,M> saturate<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `sign`\n\n## Signature \n\n```\n/// See Availability 1\nint sign<T>(T x);\n/// See Availability 2\nvector<int,N> sign<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<int,N,M> sign<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `sin`\n\n## Signature \n\n```\n/// See Availability 1\nT sin<T>(T x);\n/// See Availability 2\nvector<T,N> sin<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> sin<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `sincos`\n\n## Signature \n\n```\n/// See Availability 1\nvoid sincos<T>(\n    T                    x,\n    out T                s,\n    out T                c);\n/// See Availability 2\nvoid sincos<T, N:int>(\n    vector<T,N>          x,\n    out vector<T,N>      s,\n    out vector<T,N>      c);\nvoid sincos<T, N:int, M:int>(\n    matrix<T,N,M>        x,\n    out matrix<T,N,M>    s,\n    out matrix<T,N,M>    c);\n```\n\n## Availability\n\n1. **HLSL** **CUDA** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n* `s`\n* `c`\n\n--------------------------------------------------------------------------------\n# `sinh`\n\n## Signature \n\n```\n/// See Availability 1\nT sinh<T>(T x);\n/// See Availability 2\nvector<T,N> sinh<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> sinh<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `smoothstep`\n\n## Signature \n\n```\n/// See Availability 1\nT smoothstep<T>(\n    T                    min,\n    T                    max,\n    T                    x);\nvector<T,N> smoothstep<T, N:int>(\n    vector<T,N>          min,\n    vector<T,N>          max,\n    vector<T,N>          x);\n/// See Availability 2\nmatrix<T,N,M> smoothstep<T, N:int, M:int>(\n    matrix<T,N,M>        min,\n    matrix<T,N,M>        max,\n    matrix<T,N,M>        x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `min`\n* `max`\n* `x`\n\n--------------------------------------------------------------------------------\n# `sqrt`\n\n## Signature \n\n```\n/// See Availability 1\nT sqrt<T>(T x);\n/// See Availability 2\nvector<T,N> sqrt<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> sqrt<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `step`\n\n## Signature \n\n```\n/// See Availability 1\nT step<T>(\n    T                    y,\n    T                    x);\nvector<T,N> step<T, N:int>(\n    vector<T,N>          y,\n    vector<T,N>          x);\n/// See Availability 2\nmatrix<T,N,M> step<T, N:int, M:int>(\n    matrix<T,N,M>        y,\n    matrix<T,N,M>        x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `y`\n* `x`\n\n--------------------------------------------------------------------------------\n# `tan`\n\n## Signature \n\n```\n/// See Availability 1\nT tan<T>(T x);\n/// See Availability 2\nvector<T,N> tan<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> tan<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `tanh`\n\n## Signature \n\n```\n/// See Availability 1\nT tanh<T>(T x);\n/// See Availability 2\nvector<T,N> tanh<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> tanh<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `transpose`\n\n## Signature \n\n```\nmatrix<T,M,N> transpose<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n**GLSL** **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `trunc`\n\n## Signature \n\n```\n/// See Availability 1\nT trunc<T>(T x);\n/// See Availability 2\nvector<T,N> trunc<T, N:int>(vector<T,N> x);\n/// See Availability 3\nmatrix<T,N,M> trunc<T, N:int, M:int>(matrix<T,N,M> x);\n```\n\n## Availability\n\n1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** \n2. **GLSL** **HLSL** **SPIRV** \n3. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `x`\n\n--------------------------------------------------------------------------------\n# `WaveGetConvergedMask`\n\n## Signature \n\n```\nuint WaveGetConvergedMask();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WaveGetActiveMask`\n\n## Signature \n\n```\nuint WaveGetActiveMask();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** \n\n--------------------------------------------------------------------------------\n# `WaveMaskIsFirstLane`\n\n## Signature \n\n```\nbool WaveMaskIsFirstLane(uint mask);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n\n--------------------------------------------------------------------------------\n# `WaveMaskAllTrue`\n\n## Signature \n\n```\nbool WaveMaskAllTrue(\n    uint                 mask,\n    bool                 condition);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n* `condition`\n\n--------------------------------------------------------------------------------\n# `WaveMaskAnyTrue`\n\n## Signature \n\n```\nbool WaveMaskAnyTrue(\n    uint                 mask,\n    bool                 condition);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n* `condition`\n\n--------------------------------------------------------------------------------\n# `WaveMaskBallot`\n\n## Signature \n\n```\nuint WaveMaskBallot(\n    uint                 mask,\n    bool                 condition);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n* `condition`\n\n--------------------------------------------------------------------------------\n# `WaveMaskCountBits`\n\n## Signature \n\n```\nuint WaveMaskCountBits(\n    uint                 mask,\n    bool                 value);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n* `value`\n\n--------------------------------------------------------------------------------\n# `AllMemoryBarrierWithWaveMaskSync`\n\n## Signature \n\n```\nvoid AllMemoryBarrierWithWaveMaskSync(uint mask);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n\n--------------------------------------------------------------------------------\n# `GroupMemoryBarrierWithWaveMaskSync`\n\n## Signature \n\n```\nvoid GroupMemoryBarrierWithWaveMaskSync(uint mask);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n\n--------------------------------------------------------------------------------\n# `AllMemoryBarrierWithWaveSync`\n\n## Signature \n\n```\nvoid AllMemoryBarrierWithWaveSync();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** \n\n--------------------------------------------------------------------------------\n# `GroupMemoryBarrierWithWaveSync`\n\n## Signature \n\n```\nvoid GroupMemoryBarrierWithWaveSync();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WaveMaskBroadcastLaneAt`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskBroadcastLaneAt<T>(\n    uint                 mask,\n    T                    value,\n    int                  lane);\nvector<T,N> WaveMaskBroadcastLaneAt<T, N:int>(\n    uint                 mask,\n    vector<T,N>          value,\n    int                  lane);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskBroadcastLaneAt<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        value,\n    int                  lane);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `value`\n* `lane`\n\n--------------------------------------------------------------------------------\n# `WaveMaskReadLaneAt`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskReadLaneAt<T>(\n    uint                 mask,\n    T                    value,\n    int                  lane);\nvector<T,N> WaveMaskReadLaneAt<T, N:int>(\n    uint                 mask,\n    vector<T,N>          value,\n    int                  lane);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskReadLaneAt<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        value,\n    int                  lane);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `value`\n* `lane`\n\n--------------------------------------------------------------------------------\n# `WaveMaskShuffle`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskShuffle<T>(\n    uint                 mask,\n    T                    value,\n    int                  lane);\nvector<T,N> WaveMaskShuffle<T, N:int>(\n    uint                 mask,\n    vector<T,N>          value,\n    int                  lane);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskShuffle<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        value,\n    int                  lane);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `value`\n* `lane`\n\n--------------------------------------------------------------------------------\n# `WaveMaskPrefixCountBits`\n\n## Signature \n\n```\nuint WaveMaskPrefixCountBits(\n    uint                 mask,\n    bool                 value);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n## Parameters\n\n* `mask`\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveMaskBitAnd`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskBitAnd<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskBitAnd<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskBitAnd<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskBitOr`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskBitOr<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskBitOr<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskBitOr<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskBitXor`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskBitXor<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskBitXor<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskBitXor<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskMax`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskMax<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskMax<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskMax<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskMin`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskMin<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskMin<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskMin<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskProduct`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskProduct<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskProduct<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskProduct<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskSum`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskSum<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskSum<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskSum<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskAllEqual`\n\n## Signature \n\n```\n/// See Availability 1\nbool WaveMaskAllEqual<T>(\n    uint                 mask,\n    T                    value);\nbool WaveMaskAllEqual<T, N:int>(\n    uint                 mask,\n    vector<T,N>          value);\n/// See Availability 2\nbool WaveMaskAllEqual<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        value);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** **CUDA** `SM 7.0` \n2. **HLSL** **CUDA** `SM 7.0` \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveMaskPrefixProduct`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskPrefixProduct<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskPrefixProduct<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskPrefixProduct<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskPrefixSum`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskPrefixSum<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskPrefixSum<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskPrefixSum<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskReadLaneFirst`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskReadLaneFirst<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskReadLaneFirst<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskReadLaneFirst<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskMatch`\n\n## Signature \n\n```\nuint WaveMaskMatch<T>(\n    uint                 mask,\n    T                    value);\nuint WaveMaskMatch<T, N:int>(\n    uint                 mask,\n    vector<T,N>          value);\nuint WaveMaskMatch<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        value);\n```\n\n## Availability\n\n**HLSL** **CUDA** `SM 7.0` \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveMaskPrefixBitAnd`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskPrefixBitAnd<T>(\n    uint                 mask,\n    T                    expr);\n/// See Availability 2\nvector<T,N> WaveMaskPrefixBitAnd<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 3\nmatrix<T,N,M> WaveMaskPrefixBitAnd<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n3. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskPrefixBitOr`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskPrefixBitOr<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskPrefixBitOr<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskPrefixBitOr<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveMaskPrefixBitXor`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMaskPrefixBitXor<T>(\n    uint                 mask,\n    T                    expr);\nvector<T,N> WaveMaskPrefixBitXor<T, N:int>(\n    uint                 mask,\n    vector<T,N>          expr);\n/// See Availability 2\nmatrix<T,N,M> WaveMaskPrefixBitXor<T, N:int, M:int>(\n    uint                 mask,\n    matrix<T,N,M>        expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `mask`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `QuadReadLaneAt`\n\n## Signature \n\n```\nT QuadReadLaneAt<T>(\n    T                    sourceValue,\n    uint                 quadLaneID);\nvector<T,N> QuadReadLaneAt<T, N:int>(\n    vector<T,N>          sourceValue,\n    uint                 quadLaneID);\nmatrix<T,N,M> QuadReadLaneAt<T, N:int, M:int>(\n    matrix<T,N,M>        sourceValue,\n    uint                 quadLaneID);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `sourceValue`\n* `quadLaneID`\n\n--------------------------------------------------------------------------------\n# `QuadReadAcrossX`\n\n## Signature \n\n```\nT QuadReadAcrossX<T>(T localValue);\nvector<T,N> QuadReadAcrossX<T, N:int>(vector<T,N> localValue);\nmatrix<T,N,M> QuadReadAcrossX<T, N:int, M:int>(matrix<T,N,M> localValue);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `localValue`\n\n--------------------------------------------------------------------------------\n# `QuadReadAcrossY`\n\n## Signature \n\n```\nT QuadReadAcrossY<T>(T localValue);\nvector<T,N> QuadReadAcrossY<T, N:int>(vector<T,N> localValue);\nmatrix<T,N,M> QuadReadAcrossY<T, N:int, M:int>(matrix<T,N,M> localValue);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `localValue`\n\n--------------------------------------------------------------------------------\n# `QuadReadAcrossDiagonal`\n\n## Signature \n\n```\nT QuadReadAcrossDiagonal<T>(T localValue);\nvector<T,N> QuadReadAcrossDiagonal<T, N:int>(vector<T,N> localValue);\nmatrix<T,N,M> QuadReadAcrossDiagonal<T, N:int, M:int>(matrix<T,N,M> localValue);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `localValue`\n\n--------------------------------------------------------------------------------\n# `WaveActiveBitAnd`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveBitAnd<T>(T expr);\nvector<T,N> WaveActiveBitAnd<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveBitAnd<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveBitOr`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveBitOr<T>(T expr);\nvector<T,N> WaveActiveBitOr<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveBitOr<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveBitXor`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveBitXor<T>(T expr);\nvector<T,N> WaveActiveBitXor<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveBitXor<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveMax`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveMax<T>(T expr);\nvector<T,N> WaveActiveMax<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveMax<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveMin`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveMin<T>(T expr);\nvector<T,N> WaveActiveMin<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveMin<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveProduct`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveProduct<T>(T expr);\nvector<T,N> WaveActiveProduct<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveProduct<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveSum`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveActiveSum<T>(T expr);\nvector<T,N> WaveActiveSum<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveActiveSum<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveActiveAllEqual`\n\n## Signature \n\n```\n/// See Availability 1\nbool WaveActiveAllEqual<T>(T value);\nbool WaveActiveAllEqual<T, N:int>(vector<T,N> value);\n/// See Availability 2\nbool WaveActiveAllEqual<T, N:int, M:int>(matrix<T,N,M> value);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveActiveAllTrue`\n\n## Signature \n\n```\nbool WaveActiveAllTrue(bool condition);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** \n\n## Parameters\n\n* `condition`\n\n--------------------------------------------------------------------------------\n# `WaveActiveAnyTrue`\n\n## Signature \n\n```\nbool WaveActiveAnyTrue(bool condition);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** \n\n## Parameters\n\n* `condition`\n\n--------------------------------------------------------------------------------\n# `WaveActiveBallot`\n\n## Signature \n\n```\nvector<uint,4> WaveActiveBallot(bool condition);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** \n\n## Parameters\n\n* `condition`\n\n--------------------------------------------------------------------------------\n# `WaveActiveCountBits`\n\n## Signature \n\n```\nuint WaveActiveCountBits(bool value);\n```\n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveGetLaneCount`\n\n## Signature \n\n```\nuint WaveGetLaneCount();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WaveGetLaneIndex`\n\n## Signature \n\n```\nuint WaveGetLaneIndex();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WaveIsFirstLane`\n\n## Signature \n\n```\nbool WaveIsFirstLane();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** \n\n--------------------------------------------------------------------------------\n# `_WaveCountBits`\n\n## Signature \n\n```\nuint _WaveCountBits(vector<uint,4> value);\n```\n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `WavePrefixProduct`\n\n## Signature \n\n```\n/// See Availability 1\nT WavePrefixProduct<T>(T expr);\nvector<T,N> WavePrefixProduct<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WavePrefixProduct<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WavePrefixSum`\n\n## Signature \n\n```\n/// See Availability 1\nT WavePrefixSum<T>(T expr);\nvector<T,N> WavePrefixSum<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WavePrefixSum<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveReadLaneFirst`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveReadLaneFirst<T>(T expr);\nvector<T,N> WaveReadLaneFirst<T, N:int>(vector<T,N> expr);\n/// See Availability 2\nmatrix<T,N,M> WaveReadLaneFirst<T, N:int, M:int>(matrix<T,N,M> expr);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n\n--------------------------------------------------------------------------------\n# `WaveBroadcastLaneAt`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveBroadcastLaneAt<T>(\n    T                    value,\n    int                  lane);\nvector<T,N> WaveBroadcastLaneAt<T, N:int>(\n    vector<T,N>          value,\n    int                  lane);\n/// See Availability 2\nmatrix<T,N,M> WaveBroadcastLaneAt<T, N:int, M:int>(\n    matrix<T,N,M>        value,\n    int                  lane);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n* `lane`\n\n--------------------------------------------------------------------------------\n# `WaveReadLaneAt`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveReadLaneAt<T>(\n    T                    value,\n    int                  lane);\nvector<T,N> WaveReadLaneAt<T, N:int>(\n    vector<T,N>          value,\n    int                  lane);\n/// See Availability 2\nmatrix<T,N,M> WaveReadLaneAt<T, N:int, M:int>(\n    matrix<T,N,M>        value,\n    int                  lane);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n* `lane`\n\n--------------------------------------------------------------------------------\n# `WaveShuffle`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveShuffle<T>(\n    T                    value,\n    int                  lane);\nvector<T,N> WaveShuffle<T, N:int>(\n    vector<T,N>          value,\n    int                  lane);\n/// See Availability 2\nmatrix<T,N,M> WaveShuffle<T, N:int, M:int>(\n    matrix<T,N,M>        value,\n    int                  lane);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n* `lane`\n\n--------------------------------------------------------------------------------\n# `WavePrefixCountBits`\n\n## Signature \n\n```\nuint WavePrefixCountBits(bool value);\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** \n\n## Parameters\n\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveGetConvergedMulti`\n\n## Signature \n\n```\nvector<uint,4> WaveGetConvergedMulti();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WaveGetActiveMulti`\n\n## Signature \n\n```\nvector<uint,4> WaveGetActiveMulti();\n```\n\n## Availability\n\n**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** \n\n--------------------------------------------------------------------------------\n# `WaveMatch`\n\n## Signature \n\n```\nvector<uint,4> WaveMatch<T>(T value);\nvector<uint,4> WaveMatch<T, N:int>(vector<T,N> value);\nvector<uint,4> WaveMatch<T, N:int, M:int>(matrix<T,N,M> value);\n```\n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n\n--------------------------------------------------------------------------------\n# `WaveMultiPrefixCountBits`\n\n## Signature \n\n```\nuint WaveMultiPrefixCountBits(\n    bool                 value,\n    vector<uint,4>       mask);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `value`\n* `mask`\n\n--------------------------------------------------------------------------------\n# `WaveMultiPrefixBitAnd`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMultiPrefixBitAnd<T>(\n    T                    expr,\n    vector<uint,4>       mask);\nvector<T,N> WaveMultiPrefixBitAnd<T, N:int>(\n    vector<T,N>          expr,\n    vector<uint,4>       mask);\n/// See Availability 2\nmatrix<T,N,M> WaveMultiPrefixBitAnd<T, N:int, M:int>(\n    matrix<T,N,M>        expr,\n    vector<uint,4>       mask);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n* `mask`\n\n--------------------------------------------------------------------------------\n# `WaveMultiPrefixBitOr`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMultiPrefixBitOr<T>(\n    T                    expr,\n    vector<uint,4>       mask);\nvector<T,N> WaveMultiPrefixBitOr<T, N:int>(\n    vector<T,N>          expr,\n    vector<uint,4>       mask);\n/// See Availability 2\nmatrix<T,N,M> WaveMultiPrefixBitOr<T, N:int, M:int>(\n    matrix<T,N,M>        expr,\n    vector<uint,4>       mask);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n* `mask`\n\n--------------------------------------------------------------------------------\n# `WaveMultiPrefixBitXor`\n\n## Signature \n\n```\n/// See Availability 1\nT WaveMultiPrefixBitXor<T>(\n    T                    expr,\n    vector<uint,4>       mask);\nvector<T,N> WaveMultiPrefixBitXor<T, N:int>(\n    vector<T,N>          expr,\n    vector<uint,4>       mask);\n/// See Availability 2\nmatrix<T,N,M> WaveMultiPrefixBitXor<T, N:int, M:int>(\n    matrix<T,N,M>        expr,\n    vector<uint,4>       mask);\n```\n\n## Availability\n\n1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** \n2. **HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `expr`\n* `mask`\n\n--------------------------------------------------------------------------------\n# `WaveMultiPrefixProduct`\n\n## Signature \n\n```\nT WaveMultiPrefixProduct<T>(\n    T                    value,\n    vector<uint,4>       mask);\nvector<T,N> WaveMultiPrefixProduct<T, N:int>(\n    vector<T,N>          value,\n    vector<uint,4>       mask);\nmatrix<T,N,M> WaveMultiPrefixProduct<T, N:int, M:int>(\n    matrix<T,N,M>        value,\n    vector<uint,4>       mask);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n* `mask`\n\n--------------------------------------------------------------------------------\n# `WaveMultiPrefixSum`\n\n## Signature \n\n```\nT WaveMultiPrefixSum<T>(\n    T                    value,\n    vector<uint,4>       mask);\nvector<T,N> WaveMultiPrefixSum<T, N:int>(\n    vector<T,N>          value,\n    vector<uint,4>       mask);\nmatrix<T,N,M> WaveMultiPrefixSum<T, N:int, M:int>(\n    matrix<T,N,M>        value,\n    vector<uint,4>       mask);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `T`\n* `N`\n* `M`\n* `value`\n* `mask`\n\n--------------------------------------------------------------------------------\n# `struct Buffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `Buffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid Buffer<T>.GetDimensions(out uint dim);\n```\n\n## Parameters\n\n* `dim`\n\n--------------------------------------------------------------------------------\n# `Buffer<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT Buffer<T>.Load(int location);\n/// See Availability 2\nT Buffer<T>.Load(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `Buffer<T>.subscript`\n\n## Signature \n\n```\nT Buffer<T>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct RWBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RWBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RWBuffer<T>.GetDimensions(out uint dim);\n```\n\n## Parameters\n\n* `dim`\n\n--------------------------------------------------------------------------------\n# `RWBuffer<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RWBuffer<T>.Load(int location);\n/// See Availability 2\nT RWBuffer<T>.Load(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RWBuffer<T>.subscript`\n\n## Signature \n\n```\nT RWBuffer<T>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# `struct RasterizerOrderedBuffer<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n* `Load`\n* `subscript`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedBuffer<T>.GetDimensions`\n\n## Signature \n\n```\nvoid RasterizerOrderedBuffer<T>.GetDimensions(out uint dim);\n```\n\n## Parameters\n\n* `dim`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedBuffer<T>.Load`\n\n## Signature \n\n```\n/// See Availability 1\nT RasterizerOrderedBuffer<T>.Load(int location);\n/// See Availability 2\nT RasterizerOrderedBuffer<T>.Load(\n    int                  location,\n    out uint             status);\n```\n\n## Availability\n\n1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** \n2. **HLSL** \n\n## Parameters\n\n* `location`\n* `status`\n\n--------------------------------------------------------------------------------\n# `RasterizerOrderedBuffer<T>.subscript`\n\n## Signature \n\n```\nT RasterizerOrderedBuffer<T>.subscript(uint index);\n```\n\n## Parameters\n\n* `index`\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_NONE\n\n```\nuint RAY_FLAG_NONE\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_FORCE_OPAQUE\n\n```\nuint RAY_FLAG_FORCE_OPAQUE\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_FORCE_NON_OPAQUE\n\n```\nuint RAY_FLAG_FORCE_NON_OPAQUE\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH\n\n```\nuint RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_SKIP_CLOSEST_HIT_SHADER\n\n```\nuint RAY_FLAG_SKIP_CLOSEST_HIT_SHADER\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_CULL_BACK_FACING_TRIANGLES\n\n```\nuint RAY_FLAG_CULL_BACK_FACING_TRIANGLES\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_CULL_FRONT_FACING_TRIANGLES\n\n```\nuint RAY_FLAG_CULL_FRONT_FACING_TRIANGLES\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_CULL_OPAQUE\n\n```\nuint RAY_FLAG_CULL_OPAQUE\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_CULL_NON_OPAQUE\n\n```\nuint RAY_FLAG_CULL_NON_OPAQUE\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_SKIP_TRIANGLES\n\n```\nuint RAY_FLAG_SKIP_TRIANGLES\n```\n\n--------------------------------------------------------------------------------\n# RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES\n\n```\nuint RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES\n```\n\n--------------------------------------------------------------------------------\n# `struct RayDesc`\n\n## Fields\n\n* `Origin`\n* `TMin`\n* `Direction`\n* `TMax`\n\n--------------------------------------------------------------------------------\n# `struct RaytracingAccelerationStructure`\n\n--------------------------------------------------------------------------------\n# `struct BuiltInTriangleIntersectionAttributes`\n\n## Fields\n\n* `barycentrics`\n\n--------------------------------------------------------------------------------\n# `CallShader`\n\n## Signature \n\n```\nvoid CallShader<Payload>(\n    uint                 shaderIndex,\n    inout Payload        payload);\n```\n\n## Parameters\n\n* `Payload`\n* `shaderIndex`\n* `payload`\n\n--------------------------------------------------------------------------------\n# `TraceRay`\n\n## Signature \n\n```\nvoid TraceRay<payload_t>(\n    RaytracingAccelerationStructure AccelerationStructure,\n    uint                 RayFlags,\n    uint                 InstanceInclusionMask,\n    uint                 RayContributionToHitGroupIndex,\n    uint                 MultiplierForGeometryContributionToHitGroupIndex,\n    uint                 MissShaderIndex,\n    RayDesc              Ray,\n    inout payload_t      Payload);\n```\n\n## Availability\n\n**HLSL** **CUDA** \n\n## Parameters\n\n* `payload_t`\n* `AccelerationStructure`\n* `RayFlags`\n* `InstanceInclusionMask`\n* `RayContributionToHitGroupIndex`\n* `MultiplierForGeometryContributionToHitGroupIndex`\n* `MissShaderIndex`\n* `Ray`\n* `Payload`\n\n--------------------------------------------------------------------------------\n# `TraceMotionRay`\n\n## Signature \n\n```\nvoid TraceMotionRay<payload_t>(\n    RaytracingAccelerationStructure AccelerationStructure,\n    uint                 RayFlags,\n    uint                 InstanceInclusionMask,\n    uint                 RayContributionToHitGroupIndex,\n    uint                 MultiplierForGeometryContributionToHitGroupIndex,\n    uint                 MissShaderIndex,\n    RayDesc              Ray,\n    float                CurrentTime,\n    inout payload_t      Payload);\n```\n\n## Parameters\n\n* `payload_t`\n* `AccelerationStructure`\n* `RayFlags`\n* `InstanceInclusionMask`\n* `RayContributionToHitGroupIndex`\n* `MultiplierForGeometryContributionToHitGroupIndex`\n* `MissShaderIndex`\n* `Ray`\n* `CurrentTime`\n* `Payload`\n\n--------------------------------------------------------------------------------\n# `ReportHit`\n\n## Signature \n\n```\nbool ReportHit<A>(\n    float                tHit,\n    uint                 hitKind,\n    A                    attributes);\n```\n\n## Parameters\n\n* `A`\n* `tHit`\n* `hitKind`\n* `attributes`\n\n--------------------------------------------------------------------------------\n# `IgnoreHit`\n\n## Signature \n\n```\nvoid IgnoreHit();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `AcceptHitAndEndSearch`\n\n## Signature \n\n```\nvoid AcceptHitAndEndSearch();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `DispatchRaysIndex`\n\n## Signature \n\n```\nvector<uint,3> DispatchRaysIndex();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `DispatchRaysDimensions`\n\n## Signature \n\n```\nvector<uint,3> DispatchRaysDimensions();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WorldRayOrigin`\n\n## Signature \n\n```\nvector<float,3> WorldRayOrigin();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `WorldRayDirection`\n\n## Signature \n\n```\nvector<float,3> WorldRayDirection();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `RayTMin`\n\n## Signature \n\n```\nfloat RayTMin();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `RayTCurrent`\n\n## Signature \n\n```\nfloat RayTCurrent();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `RayFlags`\n\n## Signature \n\n```\nuint RayFlags();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `InstanceIndex`\n\n## Signature \n\n```\nuint InstanceIndex();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `InstanceID`\n\n## Signature \n\n```\nuint InstanceID();\n```\n\n## Availability\n\n**GLSL** `__glslRayTracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `PrimitiveIndex`\n\n## Signature \n\n```\nuint PrimitiveIndex();\n```\n\n## Availability\n\n**GLSL** `__glslRayTracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `ObjectRayOrigin`\n\n## Signature \n\n```\nvector<float,3> ObjectRayOrigin();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `ObjectRayDirection`\n\n## Signature \n\n```\nvector<float,3> ObjectRayDirection();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# `ObjectToWorld3x4`\n\n## Signature \n\n```\nmatrix<float,3,4> ObjectToWorld3x4();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** \n\n--------------------------------------------------------------------------------\n# `WorldToObject3x4`\n\n## Signature \n\n```\nmatrix<float,3,4> WorldToObject3x4();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** \n\n--------------------------------------------------------------------------------\n# `ObjectToWorld4x3`\n\n## Signature \n\n```\nmatrix<float,4,3> ObjectToWorld4x3();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** \n\n--------------------------------------------------------------------------------\n# `WorldToObject4x3`\n\n## Signature \n\n```\nmatrix<float,4,3> WorldToObject4x3();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayCurrentTime`\n\n## Signature \n\n```\nfloat RayCurrentTime();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_NV_ray_tracing_motion_blur` **HLSL** \n\n--------------------------------------------------------------------------------\n# `ObjectToWorld`\n\n## Signature \n\n```\nmatrix<float,3,4> ObjectToWorld();\n```\n\n--------------------------------------------------------------------------------\n# `WorldToObject`\n\n## Signature \n\n```\nmatrix<float,3,4> WorldToObject();\n```\n\n--------------------------------------------------------------------------------\n# `HitKind`\n\n## Signature \n\n```\nuint HitKind();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** \n\n--------------------------------------------------------------------------------\n# HIT_KIND_TRIANGLE_FRONT_FACE\n\n```\nuint HIT_KIND_TRIANGLE_FRONT_FACE\n```\n\n--------------------------------------------------------------------------------\n# HIT_KIND_TRIANGLE_BACK_FACE\n\n```\nuint HIT_KIND_TRIANGLE_BACK_FACE\n```\n\n--------------------------------------------------------------------------------\n# `dot4add_u8packed`\n\n## Signature \n\n```\nuint dot4add_u8packed(\n    uint                 left,\n    uint                 right,\n    uint                 acc);\n```\n\n## Parameters\n\n* `left`\n* `right`\n* `acc`\n\n--------------------------------------------------------------------------------\n# `dot4add_i8packed`\n\n## Signature \n\n```\nint dot4add_i8packed(\n    uint                 left,\n    uint                 right,\n    int                  acc);\n```\n\n## Parameters\n\n* `left`\n* `right`\n* `acc`\n\n--------------------------------------------------------------------------------\n# `dot2add`\n\n## Signature \n\n```\nfloat dot2add(\n    vector<float,2>      left,\n    vector<float,2>      right,\n    float                acc);\n```\n\n## Parameters\n\n* `left`\n* `right`\n* `acc`\n\n--------------------------------------------------------------------------------\n# `SetMeshOutputCounts`\n\n## Signature \n\n```\nvoid SetMeshOutputCounts(\n    uint                 vertexCount,\n    uint                 primitiveCount);\n```\n\n## Parameters\n\n* `vertexCount`\n* `primitiveCount`\n\n--------------------------------------------------------------------------------\n# `DispatchMesh`\n\n## Signature \n\n```\nvoid DispatchMesh<P>(\n    uint                 threadGroupCountX,\n    uint                 threadGroupCountY,\n    uint                 threadGroupCountZ,\n    P                    meshPayload);\n```\n\n## Parameters\n\n* `P`\n* `threadGroupCountX`\n* `threadGroupCountY`\n* `threadGroupCountZ`\n* `meshPayload`\n\n--------------------------------------------------------------------------------\n# `struct SAMPLER_FEEDBACK_MIN_MIP`\n\n*Implements:* `__BuiltinSamplerFeedbackType`\n\n--------------------------------------------------------------------------------\n# `struct SAMPLER_FEEDBACK_MIP_REGION_USED`\n\n*Implements:* `__BuiltinSamplerFeedbackType`\n\n--------------------------------------------------------------------------------\n# `struct FeedbackTexture2D<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2D<T>.GetDimensions`\n\n## Signature \n\n```\nvoid FeedbackTexture2D<T>.GetDimensions(\n    out uint             width,\n    out uint             height);\nvoid FeedbackTexture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             numberOfLevels);\nvoid FeedbackTexture2D<T>.GetDimensions(\n    out float            width,\n    out float            height);\nvoid FeedbackTexture2D<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            numberOfLevels);\n```\n\n## Parameters\n\n* `width`\n* `height`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2D<T>.WriteSamplerFeedbackLevel`\n\n## Signature \n\n```\nvoid FeedbackTexture2D<T>.WriteSamplerFeedbackLevel<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location,\n    float                lod);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `tex`\n* `samp`\n* `location`\n* `lod`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2D<T>.WriteSamplerFeedback`\n\n## Signature \n\n```\nvoid FeedbackTexture2D<T>.WriteSamplerFeedback<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location,\n    float                clamp);\nvoid FeedbackTexture2D<T>.WriteSamplerFeedback<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `tex`\n* `samp`\n* `location`\n* `clamp`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2D<T>.WriteSamplerFeedbackBias`\n\n## Signature \n\n```\nvoid FeedbackTexture2D<T>.WriteSamplerFeedbackBias<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location,\n    float                bias,\n    float                clamp);\nvoid FeedbackTexture2D<T>.WriteSamplerFeedbackBias<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location,\n    float                bias);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `tex`\n* `samp`\n* `location`\n* `bias`\n* `clamp`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2D<T>.WriteSamplerFeedbackGrad`\n\n## Signature \n\n```\nvoid FeedbackTexture2D<T>.WriteSamplerFeedbackGrad<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location,\n    vector<float,2>      ddx,\n    vector<float,2>      ddy,\n    float                clamp);\nvoid FeedbackTexture2D<T>.WriteSamplerFeedbackGrad<S>(\n    Texture2D            tex,\n    SamplerState         samp,\n    vector<float,2>      location,\n    vector<float,2>      ddx,\n    vector<float,2>      ddy);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `tex`\n* `samp`\n* `location`\n* `ddx`\n* `ddy`\n* `clamp`\n\n--------------------------------------------------------------------------------\n# `struct FeedbackTexture2DArray<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `GetDimensions`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2DArray<T>.GetDimensions`\n\n## Signature \n\n```\nvoid FeedbackTexture2DArray<T>.GetDimensions(\n    out uint             width,\n    out uint             height,\n    out uint             elements);\nvoid FeedbackTexture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out uint             width,\n    out uint             height,\n    out uint             elements,\n    out uint             numberOfLevels);\nvoid FeedbackTexture2DArray<T>.GetDimensions(\n    out float            width,\n    out float            height,\n    out float            elements);\nvoid FeedbackTexture2DArray<T>.GetDimensions(\n    uint                 mipLevel,\n    out float            width,\n    out float            height,\n    out float            elements,\n    out float            numberOfLevels);\n```\n\n## Parameters\n\n* `width`\n* `height`\n* `elements`\n* `mipLevel`\n* `numberOfLevels`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2DArray<T>.WriteSamplerFeedbackLevel`\n\n## Signature \n\n```\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedbackLevel<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location,\n    float                lod);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `texArray`\n* `samp`\n* `location`\n* `lod`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2DArray<T>.WriteSamplerFeedback`\n\n## Signature \n\n```\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedback<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location,\n    float                clamp);\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedback<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `texArray`\n* `samp`\n* `location`\n* `clamp`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2DArray<T>.WriteSamplerFeedbackBias`\n\n## Signature \n\n```\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedbackBias<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location,\n    float                bias,\n    float                clamp);\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedbackBias<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location,\n    float                bias);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `texArray`\n* `samp`\n* `location`\n* `bias`\n* `clamp`\n\n--------------------------------------------------------------------------------\n# `FeedbackTexture2DArray<T>.WriteSamplerFeedbackGrad`\n\n## Signature \n\n```\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedbackGrad<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location,\n    vector<float,3>      ddx,\n    vector<float,3>      ddy,\n    float                clamp);\nvoid FeedbackTexture2DArray<T>.WriteSamplerFeedbackGrad<S>(\n    Texture2DArray       texArray,\n    SamplerState         samp,\n    vector<float,3>      location,\n    vector<float,3>      ddx,\n    vector<float,3>      ddy);\n```\n\n## Availability\n\n**HLSL** **CPP** \n\n## Parameters\n\n* `S`\n* `texArray`\n* `samp`\n* `location`\n* `ddx`\n* `ddy`\n* `clamp`\n\n--------------------------------------------------------------------------------\n# `GeometryIndex`\n\n## Signature \n\n```\nuint GeometryIndex();\n```\n\n## Availability\n\n**GLSL** `GL_EXT_ray_tracing` **HLSL** \n\n--------------------------------------------------------------------------------\n# COMMITTED_NOTHING\n\n```\nuint COMMITTED_NOTHING\n```\n\n--------------------------------------------------------------------------------\n# COMMITTED_TRIANGLE_HIT\n\n```\nuint COMMITTED_TRIANGLE_HIT\n```\n\n--------------------------------------------------------------------------------\n# COMMITTED_PROCEDURAL_PRIMITIVE_HIT\n\n```\nuint COMMITTED_PROCEDURAL_PRIMITIVE_HIT\n```\n\n--------------------------------------------------------------------------------\n# CANDIDATE_NON_OPAQUE_TRIANGLE\n\n```\nuint CANDIDATE_NON_OPAQUE_TRIANGLE\n```\n\n--------------------------------------------------------------------------------\n# CANDIDATE_PROCEDURAL_PRIMITIVE\n\n```\nuint CANDIDATE_PROCEDURAL_PRIMITIVE\n```\n\n--------------------------------------------------------------------------------\n# `struct RayQuery<rayFlags:uint>`\n\n## Generic Parameters\n\n* `rayFlags`\n\n## Methods\n\n* `init`\n* `TraceRayInline`\n* `Proceed`\n* `Abort`\n* `CandidateType`\n* `CandidateObjectToWorld3x4`\n* `CandidateObjectToWorld4x3`\n* `CandidateWorldToObject3x4`\n* `CandidateWorldToObject4x3`\n* `CandidateInstanceIndex`\n* `CandidateInstanceID`\n* `CandidateGeometryIndex`\n* `CandidatePrimitiveIndex`\n* `CandidateInstanceContributionToHitGroupIndex`\n* `CandidateObjectRayOrigin`\n* `CandidateObjectRayDirection`\n* `CandidateProceduralPrimitiveNonOpaque`\n* `CandidateTriangleFrontFace`\n* `CandidateTriangleBarycentrics`\n* `CandidateTriangleRayT`\n* `CommitNonOpaqueTriangleHit`\n* `CommitProceduralPrimitiveHit`\n* `CommittedStatus`\n* `CommittedObjectToWorld3x4`\n* `CommittedObjectToWorld4x3`\n* `CommittedWorldToObject3x4`\n* `CommittedWorldToObject4x3`\n* `CommittedRayT`\n* `CommittedInstanceIndex`\n* `CommittedInstanceID`\n* `CommittedGeometryIndex`\n* `CommittedPrimitiveIndex`\n* `CommittedInstanceContributionToHitGroupIndex`\n* `CommittedObjectRayOrigin`\n* `CommittedObjectRayDirection`\n* `CommittedTriangleFrontFace`\n* `CommittedTriangleBarycentrics`\n* `RayFlags`\n* `WorldRayOrigin`\n* `WorldRayDirection`\n* `RayTMin`\n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.init`\n\n## Signature \n\n```\nRayQuery<rayFlags:uint>.init();\n```\n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.TraceRayInline`\n\n## Signature \n\n```\nvoid RayQuery<rayFlags:uint>.TraceRayInline(\n    RaytracingAccelerationStructure accelerationStructure,\n    uint                 rayFlags,\n    uint                 instanceInclusionMask,\n    RayDesc              ray);\n```\n\n## Parameters\n\n* `accelerationStructure`\n* `rayFlags`\n* `instanceInclusionMask`\n* `ray`\n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.Proceed`\n\n## Signature \n\n```\nbool RayQuery<rayFlags:uint>.Proceed();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.Abort`\n\n## Signature \n\n```\nvoid RayQuery<rayFlags:uint>.Abort();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateType`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CandidateType();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateObjectToWorld3x4`\n\n## Signature \n\n```\nmatrix<float,3,4> RayQuery<rayFlags:uint>.CandidateObjectToWorld3x4();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateObjectToWorld4x3`\n\n## Signature \n\n```\nmatrix<float,4,3> RayQuery<rayFlags:uint>.CandidateObjectToWorld4x3();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateWorldToObject3x4`\n\n## Signature \n\n```\nmatrix<float,3,4> RayQuery<rayFlags:uint>.CandidateWorldToObject3x4();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateWorldToObject4x3`\n\n## Signature \n\n```\nmatrix<float,4,3> RayQuery<rayFlags:uint>.CandidateWorldToObject4x3();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateInstanceIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CandidateInstanceIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateInstanceID`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CandidateInstanceID();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateGeometryIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CandidateGeometryIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidatePrimitiveIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CandidatePrimitiveIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateInstanceContributionToHitGroupIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CandidateInstanceContributionToHitGroupIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateObjectRayOrigin`\n\n## Signature \n\n```\nvector<float,3> RayQuery<rayFlags:uint>.CandidateObjectRayOrigin();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateObjectRayDirection`\n\n## Signature \n\n```\nvector<float,3> RayQuery<rayFlags:uint>.CandidateObjectRayDirection();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateProceduralPrimitiveNonOpaque`\n\n## Signature \n\n```\nbool RayQuery<rayFlags:uint>.CandidateProceduralPrimitiveNonOpaque();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateTriangleFrontFace`\n\n## Signature \n\n```\nbool RayQuery<rayFlags:uint>.CandidateTriangleFrontFace();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateTriangleBarycentrics`\n\n## Signature \n\n```\nvector<float,2> RayQuery<rayFlags:uint>.CandidateTriangleBarycentrics();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CandidateTriangleRayT`\n\n## Signature \n\n```\nfloat RayQuery<rayFlags:uint>.CandidateTriangleRayT();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommitNonOpaqueTriangleHit`\n\n## Signature \n\n```\nvoid RayQuery<rayFlags:uint>.CommitNonOpaqueTriangleHit();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommitProceduralPrimitiveHit`\n\n## Signature \n\n```\nvoid RayQuery<rayFlags:uint>.CommitProceduralPrimitiveHit(float t);\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n## Parameters\n\n* `t`\n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedStatus`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CommittedStatus();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedObjectToWorld3x4`\n\n## Signature \n\n```\nmatrix<float,3,4> RayQuery<rayFlags:uint>.CommittedObjectToWorld3x4();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedObjectToWorld4x3`\n\n## Signature \n\n```\nmatrix<float,4,3> RayQuery<rayFlags:uint>.CommittedObjectToWorld4x3();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedWorldToObject3x4`\n\n## Signature \n\n```\nmatrix<float,3,4> RayQuery<rayFlags:uint>.CommittedWorldToObject3x4();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedWorldToObject4x3`\n\n## Signature \n\n```\nmatrix<float,4,3> RayQuery<rayFlags:uint>.CommittedWorldToObject4x3();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedRayT`\n\n## Signature \n\n```\nfloat RayQuery<rayFlags:uint>.CommittedRayT();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedInstanceIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CommittedInstanceIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedInstanceID`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CommittedInstanceID();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedGeometryIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CommittedGeometryIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedPrimitiveIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CommittedPrimitiveIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedInstanceContributionToHitGroupIndex`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.CommittedInstanceContributionToHitGroupIndex();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedObjectRayOrigin`\n\n## Signature \n\n```\nvector<float,3> RayQuery<rayFlags:uint>.CommittedObjectRayOrigin();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedObjectRayDirection`\n\n## Signature \n\n```\nvector<float,3> RayQuery<rayFlags:uint>.CommittedObjectRayDirection();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedTriangleFrontFace`\n\n## Signature \n\n```\nbool RayQuery<rayFlags:uint>.CommittedTriangleFrontFace();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.CommittedTriangleBarycentrics`\n\n## Signature \n\n```\nvector<float,2> RayQuery<rayFlags:uint>.CommittedTriangleBarycentrics();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.RayFlags`\n\n## Signature \n\n```\nuint RayQuery<rayFlags:uint>.RayFlags();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.WorldRayOrigin`\n\n## Signature \n\n```\nvector<float,3> RayQuery<rayFlags:uint>.WorldRayOrigin();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.WorldRayDirection`\n\n## Signature \n\n```\nvector<float,3> RayQuery<rayFlags:uint>.WorldRayDirection();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `RayQuery<rayFlags:uint>.RayTMin`\n\n## Signature \n\n```\nfloat RayQuery<rayFlags:uint>.RayTMin();\n```\n\n## Availability\n\n**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** \n\n--------------------------------------------------------------------------------\n# `struct VkSubpassInput<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `SubpassLoad`\n\n--------------------------------------------------------------------------------\n# `VkSubpassInput<T>.SubpassLoad`\n\n## Signature \n\n```\nT VkSubpassInput<T>.SubpassLoad();\n```\n\n--------------------------------------------------------------------------------\n# `struct VkSubpassInputMS<T>`\n\n## Generic Parameters\n\n* `T`\n\n## Methods\n\n* `SubpassLoad`\n\n--------------------------------------------------------------------------------\n# `VkSubpassInputMS<T>.SubpassLoad`\n\n## Signature \n\n```\nT VkSubpassInputMS<T>.SubpassLoad(int sampleIndex);\n```\n\n## Parameters\n\n* `sampleIndex`\n\n"
  },
  {
    "path": "Source/External/slang/docs/target-compatibility.md",
    "content": "Slang Target Compatibility \n==========================\n\nShader Model (SM) numbers are D3D Shader Model versions, unless explicitly stated otherwise.\nOpenGL compatibility is not listed here, because OpenGL isn't an officially supported target. \n\nItems with a + means that the feature is anticipated to be added in the future.\nItems with ^ means there is some discussion about support later in the document for this target.\n\n| Feature                     |    D3D11     |    D3D12     |     VK     |      CUDA     |    CPU\n|-----------------------------|--------------|--------------|------------|---------------|---------------\n| Half Type                   |     No       |     Yes ^    |   Yes      |     Yes ^     |    No +\n| Double Type                 |     Yes      |     Yes      |   Yes      |     Yes       |    Yes\n| Double Intrinsics           |     No       |   Limited +  |  Limited   |     Most      |    Yes\n| u/int8_t Type               |     No       |   No         |   Yes ^    |     Yes       |    Yes\n| u/int16_t Type              |     No       |   Yes ^      |   Yes ^    |     Yes       |    Yes\n| u/int64_t Type              |     No       |   Yes ^      |   Yes      |     Yes       |    Yes\n| u/int64_t Intrinsics        |     No       |   No         |   Yes      |     Yes       |    Yes\n| int matrix                  |     Yes      |   Yes        |   No +     |     Yes       |    Yes\n| tex.GetDimension            |     Yes      |   Yes        |   Yes      |     No        |    Yes\n| SM6.0 Wave Intrinsics       |     No       |   Yes        |  Partial   |     Yes ^     |    No\n| SM6.0 Quad Intrinsics       |     No       |   Yes        |   No +     |     No        |    No\n| SM6.5 Wave Intrinsics       |     No       |   Yes ^      |   No +     |     Yes ^     |    No\n| WaveMask Intrinsics         |     Yes ^    |   Yes ^      |   Yes +    |     Yes       |    No\n| WaveShuffle                 |     No       |   Limited ^  |   Yes      |     Yes       |    No\n| Tesselation                 |     Yes ^    |   Yes ^      |   No +     |     No        |    No\n| Graphics Pipeline           |     Yes      |   Yes        |   Yes      |     No        |    No\n| Ray Tracing DXR 1.0         |     No       |   Yes ^      |   Yes ^    |     No        |    No\n| Ray Tracing DXR 1.1         |     No       |   Yes        |   No +     |     No        |    No\n| Native Bindless             |     No       |    No        |   No       |     Yes       |    Yes\n| Buffer bounds               |     Yes      |   Yes        |   Yes      |   Limited ^   |    Limited ^\n| Resource bounds             |     Yes      |   Yes        |   Yes      | Yes (optional)|    Yes\n| Atomics                     |     Yes      |   Yes        |   Yes      |     Yes       |    Yes\n| Group shared mem/Barriers   |     Yes      |   Yes        |   Yes      |     Yes       |    No + \n| TextureArray.Sample float   |     Yes      |   Yes        |   Yes      |     No        |    Yes\n| Separate Sampler            |     Yes      |   Yes        |   Yes      |     No        |    Yes\n| tex.Load                    |     Yes      |   Yes        |   Yes      |  Limited ^    |    Yes\n| Full bool                   |     Yes      |   Yes        |   Yes      |     No        |    Yes ^ \n| Mesh Shader                 |     No       |   No +       |   No +     |     No        |    No\n| `[unroll]`                  |     Yes      |   Yes        |   Yes ^    |     Yes       |    Limited + \n| Atomics                     |     Yes      |   Yes        |   Yes      |     Yes       |    No + \n| Atomics on RWBuffer         |     Yes      |   Yes        |   Yes      |     No        |    No + \n| Sampler Feedback            |     No       |   Yes        |   No +     |     No        |    Yes ^\n| RWByteAddressBuffer Atomic  |     No       |   Yes ^      |   Yes ^    |     Yes       |    No +\n\n## Half Type\n\nThere appears to be a problem writing to a StructuredBuffer containing half on D3D12. D3D12 also appears to have problems doing calculations with half.\n\nIn order for half to work in CUDA, NVRTC must be able to include `cuda_fp16.h` and related files. Please read the [CUDA target documentation](cuda-target.md) for more details. \n\n## u/int8_t Type\n\nNot currently supported in D3D11/D3D12 because not supported in HLSL/DXIL/DXBC. \n\nSupported in Vulkan via the extensions `GL_EXT_shader_explicit_arithmetic_types` and `GL_EXT_shader_8bit_storage`.\n\n## u/int16_t Type\n\nRequires SM6.2 which requires DXIL and therefore DXC and D3D12. For DXC this is discussed [here](https://github.com/Microsoft/DirectXShaderCompiler/wiki/16-Bit-Scalar-Types).\n\nSupported in Vulkan via the extensions `GL_EXT_shader_explicit_arithmetic_types` and `GL_EXT_shader_16bit_storage`.\n\n## u/int64_t Type\n\nRequires SM6.0 which requires DXIL for D3D12. Therefore not available with DXBC on D3D11 or D3D12.\n\n## int matrix\n\nMeans can use matrix types containing integer types. \n\n## tex.GetDimensions\n\ntex.GetDimensions is the GetDimensions method on 'texture' objects. This is not supported on CUDA as CUDA has no equivalent functionality to get these values. GetDimensions work on Buffer resource types on CUDA.\n\n## SM6.0 Wave Intrinsics\n\nCUDA has premliminary support for Wave Intrinsics, introduced in [PR #1352](https://github.com/shader-slang/slang/pull/1352). Slang synthesizes the 'WaveMask' based on program flow and the implied 'programmer view' of exectution. This support is built on top of WaveMask intrinsics with Wave Intrinsics being replaced with WaveMask Intrinsic calls with Slang generating the code to calculate the appropriate WaveMasks.\n\nPlease read [PR #1352](https://github.com/shader-slang/slang/pull/1352) for a better description of the status.\n\n## SM6.5 Wave Intrinsics\n\nSM6.5 Wave Intrinsics are supported, but requires a downstream DXC compiler that supports SM6.5. As it stands the DXC shipping with windows does not. \n\n## WaveMask Intrinsics\n\nIn order to map better to the CUDA sync/mask model Slang supports 'WaveMask' intrinsics. They operate in broadly the same way as the Wave intrinsics, but require the programmer to specify the lanes that are involved. To write code that uses wave intrinsics acrosss targets including CUDA, currently the WaveMask intrinsics must be used. For this to work, the masks passed to the WaveMask functions should exactly match the 'Active lanes' concept that HLSL uses, otherwise the result is undefined. \n\nThe WaveMask intrinsics are not part of HLSL and are only available on Slang.\n\n## WaveShuffle\n\n`WaveShuffle` and `WaveBroadcastLaneAt` are Slang specific intrinsic additions to expand the options available around `WaveReadLaneAt`. \n\nTo be clear this means they will not compile directly on 'standard' HLSL compilers such as `dxc`, but Slang HLSL *output* (which will not contain these intrinsics) can (and typically is) compiled via dxc.\n\nThe difference between them can be summarized as follows\n\n* WaveBroadcastLaneAt - laneId must be a compile time constant \n* WaveReadLaneAt - laneId can be dynamic but *MUST* be the same value across the Wave ie 'dynamically uniform' across the Wave\n* WaveShuffle - laneId can be truly dynamic (NOTE! That it is not strictly truly available currently on all targets, specifically HLSL)\n\nOther than the different restrictions on laneId they act identically to WaveReadLaneAt.\n\n`WaveBroadcastLaneAt` and `WaveReadLaneAt` will work on all targets that support wave intrinsics, with the only current restriction being that on GLSL targets, only scalars and vectors are supported.\n\n`WaveShuffle` will always work on CUDA/Vulkan. \n\nOn HLSL based targets currently `WaveShuffle` will be converted into `WaveReadLaneAt`. Strictly speaking this means it *requires* the `laneId` to be `dynamically uniform` across the Wave. In practice some hardware supports the loosened usage, and others does not. In the future this may be fixed in Slang and/or HLSL to work across all hardware. For now if you use `WaveShuffle` on HLSL based targets it will be necessary to confirm that `WaveReadLaneAt` has the loosened behavior for all the hardware intended. If target hardware does not support the loosened restrictions it's behavior is undefined. \n\n## Tesselation\n\nAlthough tesselation stages should work on D3D11 and D3D12 they are not tested within our test framework, and may have problems. \n\n## Native Bindless  \n\nBindless is possible on targets that support it - but is not the default behavior for those targets, and typically require significant effort in Slang code. \n\n'Native Bindless' targets use a form of 'bindless' for all targets. On CUDA this requires the target to use 'texture object' style binding and for the device to have 'compute capability 3.0' or higher.\n\n## Resource bounds \n\nFor CUDA this is optional as can be controlled via the SLANG_CUDA_BOUNDARY_MODE macro in the `slang-cuda-prelude.h`. By default it's behavior is `cudaBoundaryModeZero`.\n\n## Buffer Bounds\n\nThis is the feature when accessing outside of the bounds of a Buffer there is well defined behavior - on read returning all 0s, and on write, the write being ignored.\n\nOn CPU there is only bounds checking on debug compilation of C++ code. This will assert if the access is out of range.\n\nOn CUDA out of bounds accesses default to element 0 (!). The behavior can be controlled via the SLANG_CUDA_BOUND_CHECK macro in the `slang-cuda-prelude.h`. This behavior may seem a little strange - and it requires a buffer that has at least one member to not do something nasty. It is really a 'least worst' answer to a difficult problem and is better than out of range accesses or worse writes.\n\n## TextureArray.Sample float \n\nWhen using 'Sample' on a TextureArray, CUDA treats the array index parameter as an int, even though it is passed as a float.\n\n## Separate Sampler\n\nThis feature means that a multiple Samplers can be used with a Texture. In terms of the HLSL code this can be seen as the 'SamplerState' being a parameter passed to the 'Sample' method on a texture object. \n\nOn CUDA the SamplerState is ignored, because on this target a 'texture object' is the Texture and Sampler combination.\n\n## Graphics Pipeline\n\nCPU and CUDA only currently support compute shaders. \n\n## Ray Tracing DXR 1.0\n\nVulkan does not support a local root signature, but there is the concept of a 'shader record'. In Slang a single constant buffer can be marked as a shader record with the `[[vk::shader_record]]` attribute, for example:\n\n```\n[[vk::shader_record]]\ncbuffer ShaderRecord\n{\n\tuint shaderRecordID;\n} \n```\n\nIn practice to write shader code that works across D3D12 and VK you should have a single constant buffer marked as 'shader record' for VK and then on D3D that constant buffer should be bound in the local root signature on D3D. \n\n## tex.Load\n\ntex.Load is only supported on CUDA for Texture1D. Additionally CUDA only allows such access for linear memory, meaning the bound texture can also not have mip maps. Load *is* allowed on RWTexture types of other dimensions including 1D on CUDA.\n\n## Full bool\n\nMeans fully featured bool support. CUDA has issues around bool because there isn't a vector bool type built in. Currently bool aliases to an int vector type. \n\nOn CPU there are some issues in so far as bool's size is not well defined in size an alignment. Most C++ compilers now use a byte to represent a bool. In the past it has been backed by an int on some compilers. \n\n## `[unroll]`\n\nThe unroll attribute allows for unrolling `for` loops. At the moment the feature is dependent on downstream compiler support which is mixed. In the longer term the intention is for Slang to contain it's own loop unroller - and therefore not be dependent on the feature on downstream compilers. \n\nOn C++ this attribute becomes SLANG_UNROLL which is defined in the prelude. This can be predefined if there is a suitable mechanism, if there isn't a definition SLANG_UNROLL will be an empty definition. \n\nOn GLSL and VK targets loop unrolling uses the [GL_EXT_control_flow_attributes](https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_control_flow_attributes.txt) extension.\n\nSlang does have a cross target mechanism to [unroll loops](language-reference/06-statements.md), in the section `Compile-Time For Statement`.\n\n## Atomics on RWBuffer\n\nFor VK the GLSL output from Slang seems plausible, but VK binding fails in tests harness.\n\nOn CUDA RWBuffer becomes CUsurfObject, which is a 'texture' type and does not support atomics. \n\nOn the CPU atomics are not supported, but will be in the future.\n\n## Sampler Feedback\n\nThe HLSL [sampler feedback feature](https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html) is available for DirectX12. The features requires shader model 6.5 and therefore a version of [DXC](https://github.com/Microsoft/DirectXShaderCompiler) that supports that model or higher. The Shader Model 6.5 requirement also means only DXIL binary format is supported. \n\nThere doesn't not appear to be a similar feature available in Vulkan yet, but when it is available support should be addeed.\n\nFor CPU targets there is the IFeedbackTexture interface that requires an implemention for use. Slang does not currently include CPU implementations for texture types.  \n\n## RWByteAddressBuffer Atomic\n\nThe additional supported methods on RWByteAddressBuffer are...\n\n```\nvoid RWByteAddressBuffer::InterlockedAddF32(uint byteAddress, float valueToAdd, out float originalValue);\nvoid RWByteAddressBuffer::InterlockedAddF32(uint byteAddress, float valueToAdd);\n\nvoid RWByteAddressBuffer::InterlockedAddI64(uint byteAddress, int64_t valueToAdd, out int64_t originalValue);\nvoid RWByteAddressBuffer::InterlockedAddI64(uint byteAddress, int64_t valueToAdd);\n\nvoid RWByteAddressBuffer::InterlockedCompareExchangeU64(uint byteAddress, uint64_t compareValue, uint64_t value, out uint64_t outOriginalValue);\n\nuint64_t RWByteAddressBuffer::InterlockedExchangeU64(uint byteAddress, uint64_t value);\n\nuint64_t RWByteAddressBuffer::InterlockedMaxU64(uint byteAddress, uint64_t value);\nuint64_t RWByteAddressBuffer::InterlockedMinU64(uint byteAddress, uint64_t value);\n\nuint64_t RWByteAddressBuffer::InterlockedAndU64(uint byteAddress, uint64_t value);\nuint64_t RWByteAddressBuffer::InterlockedOrU64(uint byteAddress, uint64_t value);\nuint64_t RWByteAddressBuffer::InterlockedXorU64(uint byteAddress, uint64_t value);\n```\n\nOn HLSL based targets this functionality is achieved using [NVAPI](https://developer.nvidia.com/nvapi). Support for NVAPI is described\nin the separate [NVAPI Support](nvapi-support.md) document.  \n\nOn Vulkan, for float the [`GL_EXT_shader_atomic_float`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_EXT_shader_atomic_float.html) extension is required. For int64 the [`GL_EXT_shader_atomic_int64`](https://raw.githubusercontent.com/KhronosGroup/GLSL/master/extensions/ext/GL_EXT_shader_atomic_int64.txt) extension is required.\n\nCUDA requires SM6.0 or higher for int64 support. \n"
  },
  {
    "path": "Source/External/slang/docs/wave-intrinsics.md",
    "content": "Wave Intrinsics\n===============\n\nSlang has support for Wave intrinsics introduced to HLSL in [SM6.0](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12) and [SM6.5](https://github.com/microsoft/DirectX-Specs/blob/master/d3d/HLSL_ShaderModel6_5.md). All intrinsics are available on D3D12, and a subset on Vulkan. \n\nOn GLSL targets such as Vulkan wave intrinsics map to ['subgroup' extension] (https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_shader_subgroup.txt).  There is no subgroup support for Matrix types, and currently this means that Matrix is not a supported type for Wave intrinsics on Vulkan, but may be in the future.\n\nAlso introduced are some 'non standard' Wave intrinsics which are only available on Slang. All WaveMask intrinsics are non standard. Other non standard intrinsics expose more accurately different behaviours which are either not distinguished on HLSL, or perhaps currently unavailable. Two examples would be `WaveShuffle` and `WaveBroadcastLaneAt`. \n\nThere are three styles of wave intrinsics...\n\n## WaveActive\n\nThe majority of 'regular' HLSL Wave intrinsics which operate on implicit 'active' lanes. \n\nIn the [DXC Wiki](https://github.com/Microsoft/DirectXShaderCompiler/wiki/Wave-Intrinsics) active lanes are described as\n\n> These intrinsics are dependent on active lanes and therefore flow control. In the model of this document, implementations\n> must enforce that the number of active lanes exactly corresponds to the programmer’s view of flow control.\n \nIn practice this appears to imply that the programming model is that all lanes operate in 'lock step'. That the 'active lanes' are the lanes doing processing at a particular point in the control flow. On some hardware this may match how processing actually works. There is also a large amount of hardware in the field that doesn't follow this model, and allows lanes to diverge and not necessarily on flow control. On this style of hardware Active intrinsics may act to also converge lanes to give the appearance of 'in step' ness. \n \n## WaveMask\n\nThe WaveMask intrinsics take an explicit mask of lanes to operate on, in the same vein as CUDA. Requesting data from a from an inactive lane, can lead to undefined behavior, that includes locking up the shader. The WaveMask is an integer type that can hold the maximum amount of active lanes for this model - currently 32. In the future the WaveMask type may be made an opaque type, but can largely be operated on as if it is an integer.\n\nUsing WaveMask intrinsics is generally more verbose and prone to error than the 'Active' style, but it does have a few advantages\n\n* It works across all supported targets - including CUDA (currently WaveActive intrinics do not)\n* Gives more fine control\n* Might allow for higher performance (for example it gives more control of divergence)\n* Maps most closely to CUDA\n\nOn D3D12 and Vulkan the WaveMask instrinsics can be used, but the mask is effectively ignored. For this to work across targets including CUDA, the mask must be calculated such that it exactly matches that of HLSL defined 'active' lanes, else the behavior is undefined. \n\nThe WaveMask intrinsics are a non standard Slang feature, and may change in the future. \n\n```\nRWStructuredBuffer<int> outputBuffer;\n\n[numthreads(4, 1, 1)]\nvoid computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)\n{\n    // It is the programmers responsibility to determine the inital mask, and that is dependent on the launch\n    // It's common to launch such that all lanes are active - with CUDA this would mean 32 lanes. \n    // Here the launch only has 4 lanes active, and so the initial mask is 0xf.\n    const WaveMask mask0 = 0xf;\n    \n    int idx = int(dispatchThreadID.x);\n    \n    int value = 0;\n    \n    // When there is a conditional/flow control we typically need to work out a new mask.\n    // This can be achieved by calling WaveMaskBallot with the current mask, and the condition\n    // used in the flow control - here the subsequent 'if'.\n    const WaveMask mask1 = WaveMaskBallot(mask0, idx == 2);\n    \n    if (idx == 2)\n    {\n        // At this point the mask is `mask1`, although no WaveMask intrinsics are used along this path, \n        // so it's not used.\n    \n        // diverge\n        return;\n    }\n    \n    // If we get here, the active lanes must be the opposite of mask1 (because we took the other side of the condition), but cannot include\n    // any lanes which were not active before. We can calculate this as mask0 & ~mask1.\n    \n    const WaveMask mask2 = mask0 & ~mask1;\n    \n    // mask2 holds the correct active mask to use with WaveMaskMin\n    value = WaveMaskMin(mask2, idx + 1);\n    \n    // Write out the result\n    outputBuffer[idx] = value;\n}\n```\n\nMany of the nuances of writing code in this way are discussed in the [CUDA documentation](https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#warp-vote-functions).\n\nThe above example written via the regular intrinsics is significantly simpler, as we do not need to track 'active lanes' in the masks. \n\n```\nRWStructuredBuffer<int> outputBuffer;\n\n[numthreads(4, 1, 1)]\nvoid computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)\n{\n    int idx = int(dispatchThreadID.x);\n    \n    int value = 0;\n    \n    if (idx == 2)\n    {    \n        // diverge\n        return;\n    }\n    \n    value = WaveActiveMin(idx + 1);\n    \n    // Write out the result\n    outputBuffer[idx] = value;\n}\n```\n\n## WaveMulti\n\nThe standard 'Multi' intrinsics were added to HLSL is SM6.5, they can specify a mask of lanes via uint4. They introduce some intrinsics that work in a similar fashion to the `WaveMask` intrinsics. The available intrisnics is currently significantly restricted compared to WaveMask. \n\nStandard Wave intrinsics\n=========================\n\nThe Wave Intrinsics supported on Slang are listed below. Note that typically T generic types also include vector and matrix forms. \n\n```\n// Lane info\n\nuint WaveGetLaneCount();\n\nuint WaveGetLaneIndex();\n\nbool WaveIsFirstLane();\n\n// Ballot\n\nbool WaveActiveAllTrue(bool condition);\n\nbool WaveActiveAnyTrue(bool condition);\n\nuint4 WaveActiveBallot(bool condition);\n\nuint WaveActiveCountBits(bool value);\n\n// Across Lanes\n\nT WaveActiveBitAnd<T>(T expr);\n\nT WaveActiveBitOr<T>(T expr);\n\nT WaveActiveBitXor<T>(T expr);\n\nT WaveActiveMax<T>(T expr);\n\nT WaveActiveMin<T>(T expr);\n\nT WaveActiveProduct<T>(T expr);\n\nT WaveActiveSum<T>(T expr);\n\nbool WaveActiveAllEqual<T>(T value);\n\n// Prefix\n\nT WavePrefixProduct<T>(T expr);\n\nT WavePrefixSum<T>(T expr);\n\n// Communication\n\nT WaveReadLaneFirst<T>(T expr);\n\nT WaveReadLaneAt<T>(T value, int lane);\n\n// Prefix\n\nuint WavePrefixCountBits(bool value);\n\n// Shader model 6.5 stuff\n// https://github.com/microsoft/DirectX-Specs/blob/master/d3d/HLSL_ShaderModel6_5.md\n\nuint4 WaveMatch<T>(T value);\n\nuint WaveMultiPrefixCountBits(bool value, uint4 mask);\n\nT WaveMultiPrefixBitAnd<T>(T expr, uint4 mask);\n\nT WaveMultiPrefixBitOr<T>(T expr, uint4 mask);\n\nT WaveMultiPrefixBitXor<T>(T expr, uint4 mask);\n\nT WaveMultiPrefixProduct<T>(T value, uint4 mask);\n\nT WaveMultiPrefixSum<T>(T value, uint4 mask);\n```\n\nNon Standard Wave Intrinsics\n============================\n\nThe following intrinsics are not part of the HLSL Wave intrinsics standard, but were added to Slang for a variety of reasons. Within the following signatures T can be scalar, vector or matrix, except on Vulkan which doesn't (currently) support Matrix.\n\n```\nT WaveBroadcastLaneAt<T>(T value, constexpr int lane);\n\nT WaveShuffle<T>(T value, int lane);\n\nuint4 WaveGetActiveMulti();\n\nuint4 WaveGetConvergedMulti();\n\n// Barriers \n\nvoid AllMemoryBarrierWithWaveSync();\n\nvoid GroupMemoryBarrierWithWaveSync();\n```\n\n## Description\n\n```\nT WaveBroadcastLaneAt<T>(T value, constexpr int lane);\n```\n\nAll lanes receive the value specified in lane. Lane must be an active lane, otherwise the result is undefined. \nThis is a more restricive version of `WaveReadLaneAt` - which can take a non constexpr lane, *but* must be the same value for all lanes in the warp. Or 'dynamically uniform' as described in the HLSL documentation. \n\n```\nT WaveShuffle<T>(T value, int lane);\n```\n\nShuffle is a less restrictive version of `WaveReadLaneAt` in that it has no restriction on the lane value - it does *not* require the value to be same on all lanes. \n\nThere isn't explicit support for WaveShuffle in HLSL, and for now it will emit `WaveReadLaneAt`. As it turns out for a sizable set of hardware WaveReadLaneAt does work correctly when the lane is not 'dynamically uniform'. This is not necessarily the case for hardware general though, so if targetting HLSL it is important to make sure that this does work correctly on your target hardware.\n\nOur intention is that Slang will support the appropriate HLSL mechanism that makes this work on all hardware when it's available.  \n\n```\nvoid AllMemoryBarrierWithWaveSync();\n```\n\nSynchronizes all lanes to the same AllMemoryBarrierWithWaveSync in program flow. Orders all memory accesses such that accesses after the barrier can be seen by writes before.  \n\n```\nvoid GroupMemoryBarrierWithWaveSync();\n```\n\nSynchronizes all lanes to the same GroupMemoryBarrierWithWaveSync in program flow. Orders group shared memory accesses such that accesses after the barrier can be seen by writes before.  \n\nWave Mask Intrinsics\n====================\n\nCUDA has a different programming model for inter warp/wave communication based around masks of active lanes. This is because the CUDA programming model allows for divergence that is more granualar than just on program flow, and that there isn't implied reconvergence at the end of a conditional. \n\nIn the future Slang may have the capability to work out the masks required such that the regular HLSL Wave intrinsics work. As it stands there does not appear to be any way to implement the regular Wave intrinsics directly. To work around this problem we introduce 'WaveMask' intrinsics, which are essentially the same as the regular HLSL Wave intrinsics with the first parameter as the WaveMask which identifies the participating lanes. \n\nThe WaveMask intrinsics will work across targets, but *only* if on CUDA targets the mask captures exactly the same lanes as the 'Active' lanes concept in HLSL. If the masks deviate then the behavior is undefined. On non CUDA based targets currently the mask is ignored. This behavior may change on GLSL which has an extension to support a more CUDA like behavior.  \n\nMost of the `WaveMask` functions are identical to the regular Wave intrinsics, but they take a WaveMask as the first parameter, and the intrinsic name starts with `WaveMask`. \n\n```\nWaveMask WaveGetConvergedMask();\n```\n\nGets the mask of lanes which are converged within the Wave. Note that this is *not* the same as Active threads, and may be some subset of that. It is equivalent to the `__activemask()` in CUDA.\n\nOn non CUDA targets the the function will return all lanes as active - even though this is not the case. This is 'ok' in so far as on non CUDA targets the mask is ignored. It is *not* okay if the code uses the value other than as a superset of the 'really converged' lanes. For example testing the bit's and changing behavior would likely not work correctly on non CUDA targets. \n\n```\nvoid AllMemoryBarrierWithWaveMaskSync(WaveMask mask);\n```\n\nSame as AllMemoryBarrierWithWaveSync but takes a mask of active lanes to sync with. \n\n```\nvoid GroupMemoryBarrierWithWaveMaskSync(WaveMask mask);\n```\n\nSame as GroupMemoryBarrierWithWaveSync but takes a mask of active lanes to sync with. \n \nThe intrinsics that make up the Slang `WaveMask` extension. \n \n```\n// Lane info\n\nWaveMask WaveGetConvergedMask();\n\nWaveMask WaveGetActiveMask();\n\nbool WaveMaskIsFirstLane(WaveMask mask);\n\n// Ballot\n\nbool WaveMaskAllTrue(WaveMask mask, bool condition);\n\nbool WaveMaskAnyTrue(WaveMask mask, bool condition);\n\nWaveMask WaveMaskBallot(WaveMask mask, bool condition);\n\nWaveMask WaveMaskCountBits(WaveMask mask, bool value);\n\nWaveMask WaveMaskMatch<T>(WaveMask mask, T value);\n\n// Barriers\n\nvoid AllMemoryBarrierWithWaveMaskSync(WaveMask mask);\n\nvoid GroupMemoryBarrierWithWaveMaskSync(WaveMask mask);\n\n// Across lane ops\n\nT WaveMaskBitAnd<T>(WaveMask mask, T expr);\n\nT WaveMaskBitOr<T>(WaveMask mask, T expr);\n\nT WaveMaskBitXor<T>(WaveMask mask, T expr);\n\nT WaveMaskMax<T>(WaveMask mask, T expr);\n\nT WaveMaskMin<T>(WaveMask mask, T expr);\n\nT WaveMaskProduct<T>(WaveMask mask, T expr);\n\nT WaveMaskSum<T>(WaveMask mask, T expr);\n\nbool WaveMaskAllEqual<T>(WaveMask mask, T value);\n\n// Prefix\n\nT WaveMaskPrefixProduct<T>(WaveMask mask, T expr);\n\nT WaveMaskPrefixSum<T>(WaveMask mask, T expr);\n\nT WaveMaskPrefixBitAnd<T>(WaveMask mask, T expr);\n\nT WaveMaskPrefixBitOr<T>(WaveMask mask, T expr);\n\nT WaveMaskPrefixBitXor<T>(WaveMask mask, T expr);\n\nuint WaveMaskPrefixCountBits(WaveMask mask, bool value);\n\n// Communication\n\nT WaveMaskReadLaneFirst<T>(WaveMask mask, T expr);\n\nT WaveMaskBroadcastLaneAt<T>(WaveMask mask, T value, constexpr int lane);\n\nT WaveMaskReadLaneAt<T>(WaveMask mask, T value, int lane);\n\nT WaveMaskShuffle<T>(WaveMask mask, T value, int lane);\n```\n\n "
  },
  {
    "path": "Source/External/slang/prelude/slang-cpp-host-prelude.h",
    "content": "#ifndef SLANG_CPP_HOST_PRELUDE_H\n#define SLANG_CPP_HOST_PRELUDE_H\n\n#include <cstdio>\n#include <cmath>\n#include <cstring>\n\n#define SLANG_COM_PTR_ENABLE_REF_OPERATOR 1\n\n#include \"../source/slang-rt/slang-rt.h\"\n#include \"../slang-com-ptr.h\"\n#include \"slang-cpp-types.h\"\n\n#ifdef SLANG_LLVM\n#include \"slang-llvm.h\"\n#else // SLANG_LLVM\n#   if SLANG_GCC_FAMILY && __GNUC__ < 6\n#       include <cmath>\n#       define SLANG_PRELUDE_STD std::\n#   else\n#       include <math.h>\n#       define SLANG_PRELUDE_STD\n#   endif\n\n#   include <assert.h>\n#   include <stdlib.h>\n#   include <string.h>\n#   include <stdint.h>\n#endif // SLANG_LLVM\n\n\n#include \"slang-cpp-scalar-intrinsics.h\"\n\nusing namespace Slang;\n\ntemplate<typename TResult, typename... Args>\nusing Slang_FuncType = TResult(SLANG_MCALL *)(Args...);\n\n#endif\n"
  },
  {
    "path": "Source/External/slang/prelude/slang-cpp-prelude.h",
    "content": "#ifndef SLANG_CPP_PRELUDE_H\n#define SLANG_CPP_PRELUDE_H\n\n// Because the signiture of isnan, isfinite, and is isinf changed in C++, we use the macro\n// to use the version in the std namespace. \n// https://stackoverflow.com/questions/39130040/cmath-hides-isnan-in-math-h-in-c14-c11\n \n#ifdef SLANG_LLVM\n#include \"slang-llvm.h\"\n#else // SLANG_LLVM\n#   if SLANG_GCC_FAMILY && __GNUC__ < 6\n#       include <cmath>\n#       define SLANG_PRELUDE_STD std::\n#   else\n#       include <math.h>\n#       define SLANG_PRELUDE_STD\n#   endif\n\n#   include <assert.h>\n#   include <stdlib.h>\n#   include <string.h>\n#   include <stdint.h>\n#endif // SLANG_LLVM\n\n#if defined(_MSC_VER)\n#   define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport)\n#else\n#   define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__(\"default\")))\n//#   define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) __attribute__((__visibility__(\"default\")))\n#endif    \n\n#ifdef __cplusplus    \n#   define SLANG_PRELUDE_EXTERN_C extern \"C\"\n#   define SLANG_PRELUDE_EXTERN_C_START extern \"C\" {\n#   define SLANG_PRELUDE_EXTERN_C_END }\n#else\n#   define SLANG_PRELUDE_EXTERN_C \n#   define SLANG_PRELUDE_EXTERN_C_START\n#   define SLANG_PRELUDE_EXTERN_C_END \n#endif    \n\n#define SLANG_PRELUDE_EXPORT SLANG_PRELUDE_EXTERN_C SLANG_PRELUDE_SHARED_LIB_EXPORT\n#define SLANG_PRELUDE_EXPORT_START SLANG_PRELUDE_EXTERN_C_START SLANG_PRELUDE_SHARED_LIB_EXPORT\n#define SLANG_PRELUDE_EXPORT_END SLANG_PRELUDE_EXTERN_C_END\n\n#ifndef SLANG_INFINITY\n#   define SLANG_INFINITY   INFINITY\n#endif\n\n// Detect the compiler type\n\n#ifndef SLANG_COMPILER\n#    define SLANG_COMPILER\n\n/*\nCompiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/\nNOTE that SLANG_VC holds the compiler version - not just 1 or 0\n*/\n#    if defined(_MSC_VER)\n#        if _MSC_VER >= 1900\n#            define SLANG_VC 14\n#        elif _MSC_VER >= 1800\n#            define SLANG_VC 12\n#        elif _MSC_VER >= 1700\n#            define SLANG_VC 11\n#        elif _MSC_VER >= 1600\n#            define SLANG_VC 10\n#        elif _MSC_VER >= 1500\n#            define SLANG_VC 9\n#        else\n#            error \"unknown version of Visual C++ compiler\"\n#        endif\n#    elif defined(__clang__)\n#        define SLANG_CLANG 1\n#    elif defined(__SNC__)\n#        define SLANG_SNC 1\n#    elif defined(__ghs__)\n#        define SLANG_GHS 1\n#    elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */\n#        define SLANG_GCC 1\n#    else\n#        error \"unknown compiler\"\n#    endif\n/*\nAny compilers not detected by the above logic are now now explicitly zeroed out.\n*/\n#    ifndef SLANG_VC\n#        define SLANG_VC 0\n#    endif\n#    ifndef SLANG_CLANG\n#        define SLANG_CLANG 0\n#    endif\n#    ifndef SLANG_SNC\n#        define SLANG_SNC 0\n#    endif\n#    ifndef SLANG_GHS\n#        define SLANG_GHS 0\n#    endif\n#    ifndef SLANG_GCC\n#        define SLANG_GCC 0\n#    endif\n#endif /* SLANG_COMPILER */\n\n/*\nThe following section attempts to detect the target platform being compiled for.\n\nIf an application defines `SLANG_PLATFORM` before including this header,\nthey take responsibility for setting any compiler-dependent macros\nused later in the file.\n\nMost applications should not need to touch this section.\n*/\n#ifndef SLANG_PLATFORM\n#    define SLANG_PLATFORM\n/**\nOperating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/\n*/\n#    if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP\n#        define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */\n#    elif defined(XBOXONE)\n#        define SLANG_XBOXONE 1\n#    elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */\n#        define SLANG_WIN64 1\n#    elif defined(_M_PPC)\n#        define SLANG_X360 1\n#    elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */\n#        define SLANG_WIN32 1\n#    elif defined(__ANDROID__)\n#        define SLANG_ANDROID 1\n#    elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */\n#        define SLANG_LINUX 1\n#    elif defined(__APPLE__) && !defined(SLANG_LLVM)\n#        include \"TargetConditionals.h\"\n#        if TARGET_OS_MAC\n#            define SLANG_OSX 1\n#        else\n#            define SLANG_IOS 1\n#        endif\n#    elif defined(__APPLE__)\n// On `slang-llvm` we can't inclue \"TargetConditionals.h\" in general, so for now assume its OSX.\n#       define SLANG_OSX 1\n#    elif defined(__CELLOS_LV2__)\n#        define SLANG_PS3 1\n#    elif defined(__ORBIS__)\n#        define SLANG_PS4 1\n#    elif defined(__SNC__) && defined(__arm__)\n#        define SLANG_PSP2 1\n#    elif defined(__ghs__)\n#        define SLANG_WIIU 1\n#    else\n#        error \"unknown target platform\"\n#    endif\n\n\n/*\nAny platforms not detected by the above logic are now now explicitly zeroed out.\n*/\n#    ifndef SLANG_WINRT\n#        define SLANG_WINRT 0\n#    endif\n#    ifndef SLANG_XBOXONE\n#        define SLANG_XBOXONE 0\n#    endif\n#    ifndef SLANG_WIN64\n#        define SLANG_WIN64 0\n#    endif\n#    ifndef SLANG_X360\n#        define SLANG_X360 0\n#    endif\n#    ifndef SLANG_WIN32\n#        define SLANG_WIN32 0\n#    endif\n#    ifndef SLANG_ANDROID\n#        define SLANG_ANDROID 0\n#    endif\n#    ifndef SLANG_LINUX\n#        define SLANG_LINUX 0\n#    endif\n#    ifndef SLANG_IOS\n#        define SLANG_IOS 0\n#    endif\n#    ifndef SLANG_OSX\n#        define SLANG_OSX 0\n#    endif\n#    ifndef SLANG_PS3\n#        define SLANG_PS3 0\n#    endif\n#    ifndef SLANG_PS4\n#        define SLANG_PS4 0\n#    endif\n#    ifndef SLANG_PSP2\n#        define SLANG_PSP2 0\n#    endif\n#    ifndef SLANG_WIIU\n#        define SLANG_WIIU 0\n#    endif\n#endif /* SLANG_PLATFORM */\n\n/* Shorthands for \"families\" of compilers/platforms */\n#define SLANG_GCC_FAMILY (SLANG_CLANG || SLANG_SNC || SLANG_GHS || SLANG_GCC)\n#define SLANG_WINDOWS_FAMILY (SLANG_WINRT || SLANG_WIN32 || SLANG_WIN64)\n#define SLANG_MICROSOFT_FAMILY (SLANG_XBOXONE || SLANG_X360 || SLANG_WINDOWS_FAMILY)\n#define SLANG_LINUX_FAMILY (SLANG_LINUX || SLANG_ANDROID)\n#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX)                  /* equivalent to #if __APPLE__ */\n#define SLANG_UNIX_FAMILY (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */\n\n// GCC Specific\n#if SLANG_GCC_FAMILY\n#\tdefine SLANG_ALIGN_OF(T)\t__alignof__(T)\n// Use this macro instead of offsetof, because gcc produces warning if offsetof is used on a \n// non POD type, even though it produces the correct result\n#   define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1)\n#endif // SLANG_GCC_FAMILY\n\n// Microsoft VC specific\n#if SLANG_VC\n#   define SLANG_ALIGN_OF(T) __alignof(T)\n#endif // SLANG_VC\n\n// Default impls\n\n#ifndef SLANG_OFFSET_OF\n#   define SLANG_OFFSET_OF(X, Y) offsetof(X, Y)\n#endif\n\n// If slang.h has been included we don't need any of these definitions\n#ifndef SLANG_H\n\n/* Macro for declaring if a method is no throw. Should be set before the return parameter. */\n#ifndef SLANG_NO_THROW\n#   if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS)\n#       define SLANG_NO_THROW __declspec(nothrow)\n#   endif\n#endif\n#ifndef SLANG_NO_THROW\n#   define SLANG_NO_THROW\n#endif\n\n/* The `SLANG_STDCALL` and `SLANG_MCALL` defines are used to set the calling\nconvention for interface methods.\n*/\n#ifndef SLANG_STDCALL\n#   if SLANG_MICROSOFT_FAMILY\n#       define SLANG_STDCALL __stdcall\n#   else\n#       define SLANG_STDCALL\n#   endif\n#endif\n#ifndef SLANG_MCALL\n#   define SLANG_MCALL SLANG_STDCALL\n#endif\n\n#ifndef SLANG_FORCE_INLINE\n#    define SLANG_FORCE_INLINE inline\n#endif\n\n// TODO(JS): Should these be in slang-cpp-types.h? \n// They are more likely to clash with slang.h\n\nstruct SlangUUID\n{\n    uint32_t data1;\n    uint16_t data2;\n    uint16_t data3;\n    uint8_t  data4[8];\n};\n\ntypedef int32_t SlangResult;\n\nstruct ISlangUnknown\n{\n    virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) = 0;\n    virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0;\n    virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0;\n};\n\n#define SLANG_COM_INTERFACE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \\\n    public: \\\n    SLANG_FORCE_INLINE static const SlangUUID& getTypeGuid() \\\n    { \\\n        static const SlangUUID guid = { a, b, c, d0, d1, d2, d3, d4, d5, d6, d7 }; \\\n        return guid; \\\n    }\n#endif // SLANG_H\n\n// Includes\n\n#include \"slang-cpp-types.h\"\n#include \"slang-cpp-scalar-intrinsics.h\"\n\n// TODO(JS): Hack! Output C++ code from slang can copy uninitialized variables. \n#if defined(_MSC_VER)\n#   pragma warning(disable : 4700)\n#endif\n\n#ifndef SLANG_UNROLL\n#   define SLANG_UNROLL\n#endif\n\n#endif\n"
  },
  {
    "path": "Source/External/slang/prelude/slang-cpp-scalar-intrinsics.h",
    "content": "#ifndef SLANG_PRELUDE_SCALAR_INTRINSICS_H\n#define SLANG_PRELUDE_SCALAR_INTRINSICS_H\n\n#if !defined(SLANG_LLVM) && SLANG_PROCESSOR_X86_64 && SLANG_VC\n//  If we have visual studio and 64 bit processor, we can assume we have popcnt, and can include x86 intrinsics\n#   include <intrin.h>\n#endif\n\n#ifndef SLANG_FORCE_INLINE\n#    define SLANG_FORCE_INLINE inline\n#endif\n\n#ifdef SLANG_PRELUDE_NAMESPACE\nnamespace SLANG_PRELUDE_NAMESPACE {\n#endif\n\n#ifndef SLANG_PRELUDE_PI\n#   define SLANG_PRELUDE_PI           3.14159265358979323846\n#endif\n\n\nunion Union32 \n{\n    uint32_t u;\n    int32_t i;\n    float f;\n};\n\nunion Union64\n{\n    uint64_t u;\n    int64_t i;\n    double d;\n};\n\n// 32 bit cast conversions\nSLANG_FORCE_INLINE int32_t _bitCastFloatToInt(float f) { Union32 u; u.f = f; return u.i; }\nSLANG_FORCE_INLINE float _bitCastIntToFloat(int32_t i) { Union32 u; u.i = i; return u.f; }\nSLANG_FORCE_INLINE uint32_t _bitCastFloatToUInt(float f) { Union32 u; u.f = f; return u.u; }\nSLANG_FORCE_INLINE float _bitCastUIntToFloat(uint32_t ui) { Union32 u; u.u = ui; return u.f; }\n\n// ----------------------------- F16 -----------------------------------------\n\n\n// This impl is based on FloatToHalf that is in Slang codebase\nuint32_t f32tof16(const float value)\n{\n    const uint32_t inBits = _bitCastFloatToUInt(value);\n\n    // bits initially set to just the sign bit\n    uint32_t bits = (inBits >> 16) & 0x8000;\n    // Mantissa can't be used as is, as it holds last bit, for rounding.\n    uint32_t m = (inBits >> 12) & 0x07ff;\n    uint32_t e = (inBits >> 23) & 0xff;\n\n    if (e < 103)\n    {\n        // It's zero\n        return bits;\n    }\n    if (e == 0xff)\n    {\n        // Could be a NAN or INF. Is INF if *input* mantissa is 0.\n        \n        // Remove last bit for rounding to make output mantissa.\n        m >>= 1;\n       \n        // We *assume* float16/float32 signaling bit and remaining bits\n        // semantics are the same. (The signalling bit convention is target specific!).\n        // Non signal bit's usage within mantissa for a NAN are also target specific.\n      \n        // If the m is 0, it could be because the result is INF, but it could also be because all the \n        // bits that made NAN were dropped as we have less mantissa bits in f16. \n           \n        // To fix for this we make non zero if m is 0 and the input mantissa was not.\n        // This will (typically) produce a signalling NAN.\n        m += uint32_t(m == 0 && (inBits & 0x007fffffu));\n       \n        // Combine for output\n        return (bits | 0x7c00u | m);\n    }\n    if (e > 142)\n    {\n        // INF. \n        return bits | 0x7c00u;\n    }\n    if (e < 113)\n    {\n        m |= 0x0800u;\n        bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);\n        return bits;\n    }\n    bits |= ((e - 112) << 10) | (m >> 1);\n    bits += m & 1;\n    return bits;\n}\n\nstatic const float g_f16tof32Magic = _bitCastIntToFloat((127 + (127 - 15)) << 23);\n\nfloat f16tof32(const uint32_t value)\n{\n    const uint32_t sign = (value & 0x8000) << 16;\n    uint32_t exponent = (value & 0x7c00) >> 10;\n    uint32_t mantissa = (value & 0x03ff);\n\n    if (exponent == 0)\n    {\n        // If mantissa is 0 we are done, as output is 0. \n        // If it's not zero we must have a denormal.\n        if (mantissa)\n        {\n            // We have a denormal so use the magic to do exponent adjust\n            return _bitCastIntToFloat(sign | ((value & 0x7fff) << 13)) * g_f16tof32Magic;\n        }\n    }\n    else \n    {\n        // If the exponent is NAN or INF exponent is 0x1f on input. \n        // If that's the case, we just need to set the exponent to 0xff on output\n        // and the mantissa can just stay the same. If its 0 it's INF, else it is NAN and we just copy the bits\n        //\n        // Else we need to correct the exponent in the normalized case.\n        exponent = (exponent == 0x1F) ? 0xff : (exponent + (-15 + 127));\n    }\n    \n    return _bitCastUIntToFloat(sign | (exponent << 23) | (mantissa << 13));\n}\n\n// ----------------------------- F32 -----------------------------------------\n\n// Helpers\nSLANG_FORCE_INLINE float F32_calcSafeRadians(float radians);\n\n#ifdef SLANG_LLVM\n\nSLANG_PRELUDE_EXTERN_C_START\n\n// Unary \nfloat F32_ceil(float f);\nfloat F32_floor(float f);\nfloat F32_round(float f);\nfloat F32_sin(float f);\nfloat F32_cos(float f);\nfloat F32_tan(float f);\nfloat F32_asin(float f);\nfloat F32_acos(float f);\nfloat F32_atan(float f);\nfloat F32_sinh(float f);\nfloat F32_cosh(float f);\nfloat F32_tanh(float f);\nfloat F32_log2(float f);\nfloat F32_log(float f);\nfloat F32_log10(float f);\nfloat F32_exp2(float f);\nfloat F32_exp(float f);\nfloat F32_abs(float f);\nfloat F32_trunc(float f);\nfloat F32_sqrt(float f);\n\nbool F32_isnan(float f);\nbool F32_isfinite(float f); \nbool F32_isinf(float f);\n\n// Binary\nSLANG_FORCE_INLINE float F32_min(float a, float b) { return a < b ? a : b; }\nSLANG_FORCE_INLINE float F32_max(float a, float b) { return a > b ? a : b; }\nfloat F32_pow(float a, float b);\nfloat F32_fmod(float a, float b);\nfloat F32_remainder(float a, float b);\nfloat F32_atan2(float a, float b);\n\nfloat F32_frexp(float x, float* e);\nfloat F32_modf(float x, float* ip);\n\n// Ternary\nSLANG_FORCE_INLINE float F32_fma(float a, float b, float c) { return a * b + c; }\n\nSLANG_PRELUDE_EXTERN_C_END\n\n#else\n\n// Unary \nSLANG_FORCE_INLINE float F32_ceil(float f) { return ::ceilf(f); }\nSLANG_FORCE_INLINE float F32_floor(float f) { return ::floorf(f); }\nSLANG_FORCE_INLINE float F32_round(float f) { return ::roundf(f); }\nSLANG_FORCE_INLINE float F32_sin(float f) { return ::sinf(f); }\nSLANG_FORCE_INLINE float F32_cos(float f) { return ::cosf(f); }\nSLANG_FORCE_INLINE float F32_tan(float f) { return ::tanf(f); }\nSLANG_FORCE_INLINE float F32_asin(float f) { return ::asinf(f); }\nSLANG_FORCE_INLINE float F32_acos(float f) { return ::acosf(f); }\nSLANG_FORCE_INLINE float F32_atan(float f) { return ::atanf(f); }\nSLANG_FORCE_INLINE float F32_sinh(float f) { return ::sinhf(f); }\nSLANG_FORCE_INLINE float F32_cosh(float f) { return ::coshf(f); }\nSLANG_FORCE_INLINE float F32_tanh(float f) { return ::tanhf(f); }\nSLANG_FORCE_INLINE float F32_log2(float f) { return ::log2f(f); }\nSLANG_FORCE_INLINE float F32_log(float f) { return ::logf(f); }\nSLANG_FORCE_INLINE float F32_log10(float f) { return ::log10f(f); }\nSLANG_FORCE_INLINE float F32_exp2(float f) { return ::exp2f(f); }\nSLANG_FORCE_INLINE float F32_exp(float f) { return ::expf(f); }\nSLANG_FORCE_INLINE float F32_abs(float f) { return ::fabsf(f); }\nSLANG_FORCE_INLINE float F32_trunc(float f) { return ::truncf(f); }\nSLANG_FORCE_INLINE float F32_sqrt(float f) { return ::sqrtf(f); }\n\nSLANG_FORCE_INLINE bool F32_isnan(float f) { return SLANG_PRELUDE_STD isnan(f); }\nSLANG_FORCE_INLINE bool F32_isfinite(float f) { return SLANG_PRELUDE_STD isfinite(f); }\nSLANG_FORCE_INLINE bool F32_isinf(float f) { return SLANG_PRELUDE_STD isinf(f); }\n\n// Binary\nSLANG_FORCE_INLINE float F32_min(float a, float b) { return ::fminf(a, b); }\nSLANG_FORCE_INLINE float F32_max(float a, float b) { return ::fmaxf(a, b); }\nSLANG_FORCE_INLINE float F32_pow(float a, float b) { return ::powf(a, b); }\nSLANG_FORCE_INLINE float F32_fmod(float a, float b) { return ::fmodf(a, b); }\nSLANG_FORCE_INLINE float F32_remainder(float a, float b) { return ::remainderf(a, b); }\nSLANG_FORCE_INLINE float F32_atan2(float a, float b) { return float(::atan2(a, b)); }\n\nSLANG_FORCE_INLINE float F32_frexp(float x, float* e)\n{\n    int ei;\n    float m = ::frexpf(x, &ei);\n    *e = float(ei);\n    return m;\n}\nSLANG_FORCE_INLINE float F32_modf(float x, float* ip)\n{\n    return ::modff(x, ip);\n}\n\n// Ternary\nSLANG_FORCE_INLINE float F32_fma(float a, float b, float c) { return ::fmaf(a, b, c); }\n\n#endif\n\nSLANG_FORCE_INLINE float F32_calcSafeRadians(float radians)\n{\n    // Put 0 to 2pi cycles to cycle around 0 to 1 \n\tfloat a = radians * (1.0f /  float(SLANG_PRELUDE_PI * 2));\n    // Get truncated fraction, as value in  0 - 1 range\n    a = a - F32_floor(a);\n    // Convert back to 0 - 2pi range\n\treturn (a * float(SLANG_PRELUDE_PI * 2));\n}\n\nSLANG_FORCE_INLINE float F32_rsqrt(float f) { return 1.0f / F32_sqrt(f); }\nSLANG_FORCE_INLINE float F32_sign(float f) { return ( f == 0.0f) ? f : (( f < 0.0f) ? -1.0f : 1.0f); } \nSLANG_FORCE_INLINE float F32_frac(float f) { return f - F32_floor(f); }\n\nSLANG_FORCE_INLINE uint32_t F32_asuint(float f) { Union32 u; u.f = f; return u.u; }\nSLANG_FORCE_INLINE int32_t F32_asint(float f) { Union32 u; u.f = f; return u.i; }\n\n// ----------------------------- F64 -----------------------------------------\n\nSLANG_FORCE_INLINE double F64_calcSafeRadians(double radians);\n\n#ifdef SLANG_LLVM\n\nSLANG_PRELUDE_EXTERN_C_START\n\n// Unary \ndouble F64_ceil(double f);\ndouble F64_floor(double f);\ndouble F64_round(double f);\ndouble F64_sin(double f);\ndouble F64_cos(double f);\ndouble F64_tan(double f);\ndouble F64_asin(double f);\ndouble F64_acos(double f);\ndouble F64_atan(double f);\ndouble F64_sinh(double f);\ndouble F64_cosh(double f);\ndouble F64_tanh(double f);\ndouble F64_log2(double f);\ndouble F64_log(double f);\ndouble F64_log10(float f);\ndouble F64_exp2(double f);\ndouble F64_exp(double f);\ndouble F64_abs(double f);\ndouble F64_trunc(double f);\ndouble F64_sqrt(double f);\n\nbool F64_isnan(double f);\nbool F64_isfinite(double f);\nbool F64_isinf(double f);\n\n// Binary\nSLANG_FORCE_INLINE double F64_min(double a, double b) { return a < b ? a : b; }\nSLANG_FORCE_INLINE double F64_max(double a, double b) { return a > b ? a : b; }\ndouble F64_pow(double a, double b);\ndouble F64_fmod(double a, double b);\ndouble F64_remainder(double a, double b);\ndouble F64_atan2(double a, double b);\n\ndouble F64_frexp(double x, double* e);\n\ndouble F64_modf(double x, double* ip);\n\n// Ternary\nSLANG_FORCE_INLINE double F64_fma(double a, double b, double c) { return a * b + c; }\n\nSLANG_PRELUDE_EXTERN_C_END\n\n#else // SLANG_LLVM\n\n// Unary \nSLANG_FORCE_INLINE double F64_ceil(double f) { return ::ceil(f); }\nSLANG_FORCE_INLINE double F64_floor(double f) { return ::floor(f); }\nSLANG_FORCE_INLINE double F64_round(double f) { return ::round(f); }\nSLANG_FORCE_INLINE double F64_sin(double f) { return ::sin(f); }\nSLANG_FORCE_INLINE double F64_cos(double f) { return ::cos(f); }\nSLANG_FORCE_INLINE double F64_tan(double f) { return ::tan(f); }\nSLANG_FORCE_INLINE double F64_asin(double f) { return ::asin(f); }\nSLANG_FORCE_INLINE double F64_acos(double f) { return ::acos(f); }\nSLANG_FORCE_INLINE double F64_atan(double f) { return ::atan(f); }\nSLANG_FORCE_INLINE double F64_sinh(double f) { return ::sinh(f); }\nSLANG_FORCE_INLINE double F64_cosh(double f) { return ::cosh(f); }\nSLANG_FORCE_INLINE double F64_tanh(double f) { return ::tanh(f); }\nSLANG_FORCE_INLINE double F64_log2(double f) { return ::log2(f); }\nSLANG_FORCE_INLINE double F64_log(double f) { return ::log(f); }\nSLANG_FORCE_INLINE double F64_log10(float f) { return ::log10(f); }\nSLANG_FORCE_INLINE double F64_exp2(double f) { return ::exp2(f); }\nSLANG_FORCE_INLINE double F64_exp(double f) { return ::exp(f); }\nSLANG_FORCE_INLINE double F64_abs(double f) { return ::fabs(f); }\nSLANG_FORCE_INLINE double F64_trunc(double f) { return ::trunc(f); }\nSLANG_FORCE_INLINE double F64_sqrt(double f) { return ::sqrt(f); }\n\n\nSLANG_FORCE_INLINE bool F64_isnan(double f) { return SLANG_PRELUDE_STD isnan(f); }\nSLANG_FORCE_INLINE bool F64_isfinite(double f) { return SLANG_PRELUDE_STD isfinite(f); }\nSLANG_FORCE_INLINE bool F64_isinf(double f) { return SLANG_PRELUDE_STD isinf(f); }\n\n// Binary\nSLANG_FORCE_INLINE double F64_min(double a, double b) { return ::fmin(a, b); }\nSLANG_FORCE_INLINE double F64_max(double a, double b) { return ::fmax(a, b); }\nSLANG_FORCE_INLINE double F64_pow(double a, double b) { return ::pow(a, b); }\nSLANG_FORCE_INLINE double F64_fmod(double a, double b) { return ::fmod(a, b); }\nSLANG_FORCE_INLINE double F64_remainder(double a, double b) { return ::remainder(a, b); }\nSLANG_FORCE_INLINE double F64_atan2(double a, double b) { return ::atan2(a, b); }\n\nSLANG_FORCE_INLINE double F64_frexp(double x, double* e)\n{\n    int ei;\n    double m = ::frexp(x, &ei);\n    *e = float(ei);\n    return m;\n}\n\nSLANG_FORCE_INLINE double F64_modf(double x, double* ip)\n{\n    return ::modf(x, ip);\n}\n\n// Ternary\nSLANG_FORCE_INLINE double F64_fma(double a, double b, double c) { return ::fma(a, b, c); }\n\n#endif // SLANG_LLVM\n\nSLANG_FORCE_INLINE double F64_rsqrt(double f) { return 1.0 / F64_sqrt(f); }\nSLANG_FORCE_INLINE double F64_sign(double f) { return (f == 0.0) ? f : ((f < 0.0) ? -1.0 : 1.0); }\nSLANG_FORCE_INLINE double F64_frac(double f) { return f - F64_floor(f); }\n\nSLANG_FORCE_INLINE void F64_asuint(double d, uint32_t* low, uint32_t* hi)\n{\n    Union64 u;\n    u.d = d;\n    *low = uint32_t(u.u);\n    *hi = uint32_t(u.u >> 32);\n}\n\nSLANG_FORCE_INLINE void F64_asint(double d, int32_t* low, int32_t* hi)\n{\n    Union64 u;\n    u.d = d;\n    *low = int32_t(u.u);\n    *hi = int32_t(u.u >> 32);\n}\n\nSLANG_FORCE_INLINE double F64_calcSafeRadians(double radians)\n{\n    // Put 0 to 2pi cycles to cycle around 0 to 1 \n\tdouble a = radians * (1.0f /  (SLANG_PRELUDE_PI * 2));\n    // Get truncated fraction, as value in  0 - 1 range\n    a = a - F64_floor(a);\n    // Convert back to 0 - 2pi range\n\treturn (a * (SLANG_PRELUDE_PI * 2));\n}\n\n// ----------------------------- I32 -----------------------------------------\n\nSLANG_FORCE_INLINE int32_t I32_abs(int32_t f) { return (f < 0) ? -f : f; }\n\nSLANG_FORCE_INLINE int32_t I32_min(int32_t a, int32_t b) { return a < b ? a : b; }\nSLANG_FORCE_INLINE int32_t I32_max(int32_t a, int32_t b) { return a > b ? a : b; }\n\nSLANG_FORCE_INLINE float I32_asfloat(int32_t x) { Union32 u; u.i = x; return u.f; }\nSLANG_FORCE_INLINE uint32_t I32_asuint(int32_t x) { return uint32_t(x); }\nSLANG_FORCE_INLINE double I32_asdouble(int32_t low, int32_t hi )\n{\n    Union64 u;\n    u.u = (uint64_t(hi) << 32) | uint32_t(low);\n    return u.d;\n}\n\n// ----------------------------- U32 -----------------------------------------\n\nSLANG_FORCE_INLINE uint32_t U32_abs(uint32_t f) { return f; }\n\nSLANG_FORCE_INLINE uint32_t U32_min(uint32_t a, uint32_t b) { return a < b ? a : b; }\nSLANG_FORCE_INLINE uint32_t U32_max(uint32_t a, uint32_t b) { return a > b ? a : b; }\n\nSLANG_FORCE_INLINE float U32_asfloat(uint32_t x) { Union32 u; u.u = x; return u.f; }\nSLANG_FORCE_INLINE uint32_t U32_asint(int32_t x) { return uint32_t(x); } \n\nSLANG_FORCE_INLINE double U32_asdouble(uint32_t low, uint32_t hi)\n{\n    Union64 u;\n    u.u = (uint64_t(hi) << 32) | low;\n    return u.d;\n}\n\n\nSLANG_FORCE_INLINE uint32_t U32_countbits(uint32_t v)\n{\n#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM)\n    return __builtin_popcount(v);\n#elif SLANG_PROCESSOR_X86_64 && SLANG_VC\n    return __popcnt(v);\n#else     \n    uint32_t c = 0;\n    while (v)\n    {\n        c++;\n        v &= v - 1;\n    }\n    return c;\n#endif\n}\n\n// ----------------------------- U64 -----------------------------------------\n\nSLANG_FORCE_INLINE uint64_t U64_abs(uint64_t f) { return f; }\n\nSLANG_FORCE_INLINE uint64_t U64_min(uint64_t a, uint64_t b) { return a < b ? a : b; }\nSLANG_FORCE_INLINE uint64_t U64_max(uint64_t a, uint64_t b) { return a > b ? a : b; }\n\n// TODO(JS): We don't define countbits for 64bit in stdlib currently.\n// It's not clear from documentation if it should return 32 or 64 bits, if it exists. \n// 32 bits can always hold the result, and will be implicitly promoted. \nSLANG_FORCE_INLINE uint32_t U64_countbits(uint64_t v)\n{\n#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM)   \n    return uint32_t(__builtin_popcountl(v));\n#elif SLANG_PROCESSOR_X86_64 && SLANG_VC\n    return uint32_t(__popcnt64(v));\n#else     \n    uint32_t c = 0;\n    while (v)\n    {\n        c++;\n        v &= v - 1;\n    }\n    return c;\n#endif\n}\n\n// ----------------------------- I64 -----------------------------------------\n\nSLANG_FORCE_INLINE int64_t I64_abs(int64_t f) { return (f < 0) ? -f : f; }\n\nSLANG_FORCE_INLINE int64_t I64_min(int64_t a, int64_t b) { return a < b ? a : b; }\nSLANG_FORCE_INLINE int64_t I64_max(int64_t a, int64_t b) { return a > b ? a : b; }\n\n\n// ----------------------------- Interlocked ---------------------------------\n\n#if SLANG_LLVM\n\n#else // SLANG_LLVM\n\n#   ifdef _WIN32\n#       include <intrin.h>\n#   endif\n\nvoid InterlockedAdd(uint32_t* dest, uint32_t value, uint32_t* oldValue)\n{\n#   ifdef _WIN32\n    *oldValue = _InterlockedExchangeAdd((long*)dest, (long)value);\n#   else\n    *oldValue = __sync_fetch_and_add(dest, value);\n#   endif\n}\n\n#endif // SLANG_LLVM\n\n#ifdef SLANG_PRELUDE_NAMESPACE\n} \n#endif\n\n#endif\n"
  },
  {
    "path": "Source/External/slang/prelude/slang-cpp-types.h",
    "content": "#ifndef SLANG_PRELUDE_CPP_TYPES_H\n#define SLANG_PRELUDE_CPP_TYPES_H\n\n#ifndef SLANG_PRELUDE_ASSERT\n#   ifdef SLANG_PRELUDE_ENABLE_ASSERT\n#       define SLANG_PRELUDE_ASSERT(VALUE) assert(VALUE)\n#   else\n#       define SLANG_PRELUDE_ASSERT(VALUE) \n#   endif\n#endif\n\n// Since we are using unsigned arithmatic care is need in this comparison.\n// It is *assumed* that sizeInBytes >= elemSize. Which means (sizeInBytes >= elemSize) >= 0\n// Which means only a single test is needed\n\n// Asserts for bounds checking.\n// It is assumed index/count are unsigned types.\n#define SLANG_BOUND_ASSERT(index, count)  SLANG_PRELUDE_ASSERT(index < count); \n#define SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3) == 0);\n\n// Macros to zero index if an access is out of range\n#define SLANG_BOUND_ZERO_INDEX(index, count) index = (index < count) ? index : 0; \n#define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) index = (index <= (sizeInBytes - elemSize)) ? index : 0; \n\n// The 'FIX' macro define how the index is fixed. The default is to do nothing. If SLANG_ENABLE_BOUND_ZERO_INDEX\n// the fix macro will zero the index, if out of range\n#ifdef  SLANG_ENABLE_BOUND_ZERO_INDEX\n#   define SLANG_BOUND_FIX(index, count) SLANG_BOUND_ZERO_INDEX(index, count)\n#   define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes)\n#   define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) SLANG_BOUND_ZERO_INDEX(index, count)\n#else\n#   define SLANG_BOUND_FIX(index, count) \n#   define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) \n#   define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) \n#endif\n\n#ifndef SLANG_BOUND_CHECK\n#   define SLANG_BOUND_CHECK(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count)\n#endif\n\n#ifndef SLANG_BOUND_CHECK_BYTE_ADDRESS\n#   define SLANG_BOUND_CHECK_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes)\n#endif\n\n#ifndef SLANG_BOUND_CHECK_FIXED_ARRAY\n#   define SLANG_BOUND_CHECK_FIXED_ARRAY(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count)\n#endif\n\n#ifdef SLANG_PRELUDE_NAMESPACE\nnamespace SLANG_PRELUDE_NAMESPACE {\n#endif\n\nstruct TypeInfo\n{\n    size_t typeSize;\n};\n\ntemplate <typename T, size_t SIZE>\nstruct FixedArray\n{\n    const T& operator[](size_t index) const { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; }\n    T& operator[](size_t index) { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; }\n\n    T m_data[SIZE];\n};\n\n// An array that has no specified size, becomes a 'Array'. This stores the size so it can potentially \n// do bounds checking.  \ntemplate <typename T>\nstruct Array\n{\n    const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    T& operator[](size_t index) { SLANG_BOUND_CHECK(index, count); return data[index]; }\n\n    T* data;\n    size_t count;\n};\n\n#if 0\ntemplate<size_t N>\nstruct AnyValue\n{\n    uint8_t data[N];\n};\ntemplate<size_t N, typename T>\nAnyValue<N> packAnyValue(const T& val)\n{\n    AnyValue<N> result;\n    memcpy(&result, &val, sizeof(T));\n    return result;\n}\ntemplate<size_t N, typename T>\nT unpackAnyValue(const AnyValue<N>& val)\n{\n    T result;\n    memcpy(&result, &val, sizeof(T));\n    return result;\n}\n#endif\n\n/* Constant buffers become a pointer to the contained type, so ConstantBuffer<T> becomes T* in C++ code.\n*/\n\ntemplate <typename T, int COUNT>\nstruct Vector;\n\ntemplate <typename T>\nstruct Vector<T, 1>\n{\n    T x;\n};\n\ntemplate <typename T>\nstruct Vector<T, 2>\n{\n    T x, y;\n};\n\ntemplate <typename T>\nstruct Vector<T, 3>\n{\n    T x, y, z;\n};\n\ntemplate <typename T>\nstruct Vector<T, 4>\n{\n    T x, y, z, w;\n};\n\n\ntypedef Vector<float, 2> float2;\ntypedef Vector<float, 3> float3;\ntypedef Vector<float, 4> float4;\n\ntypedef Vector<int32_t, 2> int2;\ntypedef Vector<int32_t, 3> int3;\ntypedef Vector<int32_t, 4> int4;\n\ntypedef Vector<uint32_t, 2> uint2;\ntypedef Vector<uint32_t, 3> uint3;\ntypedef Vector<uint32_t, 4> uint4;\n\ntemplate <typename T, int ROWS, int COLS>\nstruct Matrix\n{\n    Vector<T, COLS> rows[ROWS];\n};\n\n// We can just map `NonUniformResourceIndex` type directly to the index type on CPU, as CPU does not require\n// any special handling around such accesses.\ntypedef size_t NonUniformResourceIndex;\n\n// ----------------------------- ResourceType -----------------------------------------\n\n// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions\n// Missing  Load(_In_  int  Location, _Out_ uint Status);\n\ntemplate <typename T>\nstruct RWStructuredBuffer\n{\n    SLANG_FORCE_INLINE T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }  \n    void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) { *outNumStructs = uint32_t(count); *outStride = uint32_t(sizeof(T)); }\n  \n    T* data;\n    size_t count;\n};\n\ntemplate <typename T>\nstruct StructuredBuffer\n{\n    SLANG_FORCE_INLINE const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) { *outNumStructs = uint32_t(count); *outStride = uint32_t(sizeof(T)); }\n    \n    T* data;\n    size_t count;\n};\n\n\ntemplate <typename T>\nstruct RWBuffer\n{\n    SLANG_FORCE_INLINE T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); }\n    \n    T* data;\n    size_t count;\n};\n\ntemplate <typename T>\nstruct Buffer\n{\n    SLANG_FORCE_INLINE const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); }\n    \n    T* data;\n    size_t count;\n};\n\n// Missing  Load(_In_  int  Location, _Out_ uint Status);\nstruct ByteAddressBuffer\n{\n    void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); }\n    uint32_t Load(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);\n        return data[index >> 2]; \n    }\n    uint2 Load2(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint2{data[dataIdx], data[dataIdx + 1]}; \n    }\n    uint3 Load3(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; \n    }\n    uint4 Load4(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; \n    }\n    template<typename T>\n    T Load(size_t index) const\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        return *(const T*)(((const char*)data) + index);\n    }\n    \n    const uint32_t* data;\n    size_t sizeInBytes;  //< Must be multiple of 4\n};\n\n// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer\n// Missing support for Atomic operations \n// Missing support for Load with status\nstruct RWByteAddressBuffer\n{\n    void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); }\n    \n    uint32_t Load(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);\n        return data[index >> 2]; \n    }\n    uint2 Load2(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint2{data[dataIdx], data[dataIdx + 1]}; \n    }\n    uint3 Load3(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; \n    }\n    uint4 Load4(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; \n    }\n    template<typename T>\n    T Load(size_t index) const\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        return *(const T*)(((const char*)data) + index);\n    }\n\n    void Store(size_t index, uint32_t v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);\n        data[index >> 2] = v; \n    }\n    void Store2(size_t index, uint2 v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        data[dataIdx + 0] = v.x;\n        data[dataIdx + 1] = v.y;\n    }\n    void Store3(size_t index, uint3 v) const \n    {  \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        data[dataIdx + 0] = v.x;\n        data[dataIdx + 1] = v.y;\n        data[dataIdx + 2] = v.z;\n    }\n    void Store4(size_t index, uint4 v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        data[dataIdx + 0] = v.x;\n        data[dataIdx + 1] = v.y;\n        data[dataIdx + 2] = v.z;\n        data[dataIdx + 3] = v.w;\n    }\n    template<typename T>\n    void Store(size_t index, T const& value) const\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        *(T*)(((char*)data) + index) = value;\n    }\n\n    uint32_t* data;\n    size_t sizeInBytes; //< Must be multiple of 4 \n};\n\nstruct ISamplerState;\nstruct ISamplerComparisonState;\n\nstruct SamplerState\n{\n    ISamplerState* state;\n};\n\nstruct SamplerComparisonState\n{\n    ISamplerComparisonState* state;\n};\n\n#ifndef SLANG_RESOURCE_SHAPE\n#    define SLANG_RESOURCE_SHAPE\ntypedef unsigned int SlangResourceShape;\nenum\n{\n    SLANG_RESOURCE_BASE_SHAPE_MASK = 0x0F,\n\n    SLANG_RESOURCE_NONE = 0x00,\n\n    SLANG_TEXTURE_1D = 0x01,\n    SLANG_TEXTURE_2D = 0x02,\n    SLANG_TEXTURE_3D = 0x03,\n    SLANG_TEXTURE_CUBE = 0x04,\n    SLANG_TEXTURE_BUFFER = 0x05,\n\n    SLANG_STRUCTURED_BUFFER = 0x06,\n    SLANG_BYTE_ADDRESS_BUFFER = 0x07,\n    SLANG_RESOURCE_UNKNOWN = 0x08,\n    SLANG_ACCELERATION_STRUCTURE = 0x09,\n\n    SLANG_RESOURCE_EXT_SHAPE_MASK = 0xF0,\n\n    SLANG_TEXTURE_FEEDBACK_FLAG = 0x10,\n    SLANG_TEXTURE_ARRAY_FLAG = 0x40,\n    SLANG_TEXTURE_MULTISAMPLE_FLAG = 0x80,\n\n    SLANG_TEXTURE_1D_ARRAY = SLANG_TEXTURE_1D | SLANG_TEXTURE_ARRAY_FLAG,\n    SLANG_TEXTURE_2D_ARRAY = SLANG_TEXTURE_2D | SLANG_TEXTURE_ARRAY_FLAG,\n    SLANG_TEXTURE_CUBE_ARRAY = SLANG_TEXTURE_CUBE | SLANG_TEXTURE_ARRAY_FLAG,\n\n    SLANG_TEXTURE_2D_MULTISAMPLE = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG,\n    SLANG_TEXTURE_2D_MULTISAMPLE_ARRAY =\n        SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG | SLANG_TEXTURE_ARRAY_FLAG,\n};\n#endif\n\n// \nstruct TextureDimensions\n{\n    void reset()\n    {\n        shape = 0;\n        width = height = depth = 0;\n        numberOfLevels = 0;\n        arrayElementCount = 0;\n    }\n    int getDimSizes(uint32_t outDims[4]) const\n    {\n        const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);\n        int count = 0;\n        switch (baseShape)\n        {\n            case SLANG_TEXTURE_1D:\n            {\n                outDims[count++] = width;\n                break;\n            }\n            case SLANG_TEXTURE_2D:\n            {\n                outDims[count++] = width;\n                outDims[count++] = height;\n                break;\n            }\n            case SLANG_TEXTURE_3D:\n            {\n                outDims[count++] = width;\n                outDims[count++] = height;\n                outDims[count++] = depth;\n                break;\n            }\n            case SLANG_TEXTURE_CUBE:\n            {\n                outDims[count++] = width;\n                outDims[count++] = height;\n                outDims[count++] = 6;\n                break;\n            }\n        }\n\n        if (shape & SLANG_TEXTURE_ARRAY_FLAG)\n        {\n            outDims[count++] = arrayElementCount;\n        }\n        return count;\n    }\n    int getMIPDims(int outDims[3]) const\n    {\n        const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);\n        int count = 0;\n        switch (baseShape)\n        {\n            case SLANG_TEXTURE_1D:\n            {\n                outDims[count++] = width;\n                break;\n            }\n            case SLANG_TEXTURE_CUBE:\n            case SLANG_TEXTURE_2D:\n            {\n                outDims[count++] = width;\n                outDims[count++] = height;\n                break;\n            }\n            case SLANG_TEXTURE_3D:\n            {\n                outDims[count++] = width;\n                outDims[count++] = height;\n                outDims[count++] = depth;\n                break;\n            }\n        }\n        return count;\n    }\n    int calcMaxMIPLevels() const\n    {\n        int dims[3];\n        const int dimCount = getMIPDims(dims);\n        for (int count = 1; true; count++)\n        {\n            bool allOne = true;\n            for (int i = 0; i < dimCount; ++i)\n            {\n                if (dims[i] > 1)\n                {\n                    allOne = false;\n                    dims[i] >>= 1;\n                }\n            }\n            if (allOne)\n            {\n                return count;\n            }\n        }\n    }\n\n    uint32_t shape;\n    uint32_t width, height, depth;\n    uint32_t numberOfLevels;\n    uint32_t arrayElementCount;                  ///< For array types, 0 otherwise\n};\n\n\n\n\n\n// Texture\n\nstruct ITexture\n{\n    virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;\n    virtual void Load(const int32_t* v, void* outData, size_t dataSize) = 0;\n    virtual void Sample(SamplerState samplerState, const float* loc, void* outData, size_t dataSize) = 0;\n    virtual void SampleLevel(SamplerState samplerState, const float* loc, float level, void* outData, size_t dataSize) = 0;\n};\n\ntemplate <typename T>\nstruct Texture1D\n{\n    void GetDimensions(uint32_t* outWidth) { *outWidth = texture->GetDimensions().width; }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels) \n    { \n        auto dims = texture->GetDimensions(mipLevel); \n        *outWidth = dims.width; \n        *outNumberOfLevels = dims.numberOfLevels; \n    }\n    \n    void GetDimensions(float* outWidth) { *outWidth = texture->GetDimensions().width; }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels) \n    { \n        auto dims = texture->GetDimensions(mipLevel); \n        *outWidth = dims.width; \n        *outNumberOfLevels = dims.numberOfLevels; \n    }\n    \n    T Load(const int2& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T Sample(SamplerState samplerState, float loc) const { T out; texture->Sample(samplerState, &loc, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, float loc, float level) { T out; texture->SampleLevel(samplerState, &loc, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\ntemplate <typename T>\nstruct Texture2D\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T Sample(SamplerState samplerState, const float2& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, const float2& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\ntemplate <typename T>\nstruct Texture3D\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth)\n    {\n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n        *outDepth = dims.depth;\n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outDepth = dims.depth;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight, float* outDepth)\n    {\n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n        *outDepth = dims.depth;\n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outDepth, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outDepth = dims.depth;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(const int4& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\ntemplate <typename T>\nstruct TextureCube\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\ntemplate <typename T>\nstruct Texture1DArray\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outElements) { auto dims = texture->GetDimensions(); *outWidth = dims.width; *outElements = dims.arrayElementCount; }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outElements, uint32_t* outNumberOfLevels) \n    {\n        auto dims = texture->GetDimensions(mipLevel); \n        *outWidth = dims.width; \n        *outNumberOfLevels = dims.numberOfLevels;\n        *outElements = dims.arrayElementCount; \n    }        \n    void GetDimensions(float* outWidth, float* outElements) { auto dims = texture->GetDimensions(); *outWidth = dims.width; *outElements = dims.arrayElementCount; }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outElements, float* outNumberOfLevels) \n    {\n        auto dims = texture->GetDimensions(mipLevel); \n        *outWidth = dims.width; \n        *outNumberOfLevels = dims.numberOfLevels;\n        *outElements = dims.arrayElementCount; \n    }\n    \n    T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T Sample(SamplerState samplerState, const float2& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, const float2& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\ntemplate <typename T>\nstruct Texture2DArray\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)\n    {\n        auto dims = texture->GetDimensions();\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels)\n    {\n        auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements)\n    {\n        auto dims = texture->GetDimensions();\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels)\n    {\n        auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(const int4& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\ntemplate <typename T>\nstruct TextureCubeArray\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)\n    {\n        auto dims = texture->GetDimensions();\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels)\n    {\n        auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements)\n    {\n        auto dims = texture->GetDimensions();\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels)\n    {\n        auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Sample(SamplerState samplerState, const float4& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; }\n    T SampleLevel(SamplerState samplerState, const float4& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; }\n    \n    ITexture* texture;              \n};\n\n/* !!!!!!!!!!!!!!!!!!!!!!!!!!! RWTexture !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */\n\nstruct IRWTexture : ITexture\n{\n        /// Get the reference to the element at loc. \n    virtual void* refAt(const uint32_t* loc) = 0;\n};\n\ntemplate <typename T>\nstruct RWTexture1D\n{\n    void GetDimensions(uint32_t* outWidth) { *outWidth = texture->GetDimensions().width; }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outNumberOfLevels = dims.numberOfLevels; }\n    \n    void GetDimensions(float* outWidth) { *outWidth = texture->GetDimensions().width; }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outNumberOfLevels = dims.numberOfLevels; }\n    \n    T Load(int32_t loc) const { T out; texture->Load(&loc, &out, sizeof(out)); return out; }\n    T& operator[](uint32_t loc) { return *(T*)texture->refAt(&loc); }\n    IRWTexture* texture;              \n};\n\ntemplate <typename T>\nstruct RWTexture2D\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(const int2& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T& operator[](const uint2& loc) { return *(T*)texture->refAt(&loc.x); }\n    IRWTexture* texture;\n};\n\ntemplate <typename T>\nstruct RWTexture3D\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth)\n    {\n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n        *outDepth = dims.depth;\n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outDepth = dims.depth;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight, float* outDepth)\n    {\n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n        *outDepth = dims.depth;\n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outDepth, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outDepth = dims.depth;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); }\n    IRWTexture* texture;\n};\n\n\ntemplate <typename T>\nstruct RWTexture1DArray\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outElements) \n    { \n        auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outElements = dims.arrayElementCount; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outElements, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outElements) \n    { \n        auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outElements = dims.arrayElementCount; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outElements, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(int2 loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T& operator[](uint2 loc) { return *(T*)texture->refAt(&loc.x); }\n\n    IRWTexture* texture;\n};\n\ntemplate <typename T>\nstruct RWTexture2DArray\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)\n    {\n        auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight, float* outElements)\n    {\n        auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; }\n    T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); }\n\n    IRWTexture* texture;\n};\n\n// FeedbackTexture\n\nstruct FeedbackType {};\nstruct SAMPLER_FEEDBACK_MIN_MIP : FeedbackType {};\nstruct SAMPLER_FEEDBACK_MIP_REGION_USED : FeedbackType {};\n\nstruct IFeedbackTexture\n{\n    virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;\n\n    // Note here we pass the optional clamp parameter as a pointer. Passing nullptr means no clamp. \n    // This was preferred over having two function definitions, and having to differentiate their names\n    virtual void WriteSamplerFeedback(ITexture* tex, SamplerState samp, const float* location, const float* clamp = nullptr) = 0;\n    virtual void WriteSamplerFeedbackBias(ITexture* tex, SamplerState samp, const float* location, float bias, const float* clamp = nullptr) = 0;\n    virtual void WriteSamplerFeedbackGrad(ITexture* tex, SamplerState samp, const float* location, const float* ddx, const float* ddy, const float* clamp = nullptr) = 0;\n    \n    virtual void WriteSamplerFeedbackLevel(ITexture* tex, SamplerState samp, const float* location, float lod) = 0;\n};\n\ntemplate <typename T>\nstruct FeedbackTexture2D\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight) \n    { \n        const auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    template <typename S>\n    void WriteSamplerFeedback(Texture2D<S> tex, SamplerState samp, float2 location, float clamp) { texture->WriteSamplerFeedback(tex.texture, samp, &location.x, &clamp); } \n\n    template <typename S>\n    void WriteSamplerFeedbackBias(Texture2D<S> tex, SamplerState samp, float2 location, float bias, float clamp) { texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias, &clamp); }\n\n    template <typename S>\n    void WriteSamplerFeedbackGrad(Texture2D<S> tex, SamplerState samp, float2 location, float2 ddx, float2 ddy, float clamp) { texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); }\n\n    // Level\n\n    template <typename S> \n    void WriteSamplerFeedbackLevel(Texture2D<S> tex, SamplerState samp, float2 location, float lod) { texture->WriteSamplerFeedbackLevel(tex.texture, samp, &location.x, lod); }\n    \n    // Without Clamp\n    template <typename S> \n    void WriteSamplerFeedback(Texture2D<S> tex, SamplerState samp, float2 location) { texture->WriteSamplerFeedback(tex.texture, samp, &location.x); }\n\n    template <typename S> \n    void WriteSamplerFeedbackBias(Texture2D<S> tex, SamplerState samp, float2 location, float bias) { texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias); }\n\n    template <typename S> \n    void WriteSamplerFeedbackGrad(Texture2D<S> tex, SamplerState samp, float2 location, float2 ddx, float2 ddy) { texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x); }\n    \n    IFeedbackTexture* texture;\n};\n\ntemplate <typename T>\nstruct FeedbackTexture2DArray\n{\n    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)\n    {\n        auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount; \n    }\n    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    void GetDimensions(float* outWidth, float* outHeight, float* outElements)\n    {\n        auto dims = texture->GetDimensions(); \n        *outWidth = dims.width; \n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount; \n    }\n    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels)\n    {\n        const auto dims = texture->GetDimensions(mipLevel);\n        *outWidth = dims.width;\n        *outHeight = dims.height;\n        *outElements = dims.arrayElementCount;\n        *outNumberOfLevels = dims.numberOfLevels;\n    }\n    \n    template <typename S>\n    void WriteSamplerFeedback(Texture2DArray<S> texArray, SamplerState samp, float3 location, float clamp) { texture->WriteSamplerFeedback(texArray.texture, samp, &location.x, &clamp); }\n\n    template <typename S>\n    void WriteSamplerFeedbackBias(Texture2DArray<S> texArray, SamplerState samp, float3 location, float bias, float clamp) { texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias, &clamp); }\n\n    template <typename S>\n    void WriteSamplerFeedbackGrad(Texture2DArray<S> texArray, SamplerState samp, float3 location, float3 ddx, float3 ddy, float clamp) { texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); }\n\n    // Level\n    template <typename S>\n    void WriteSamplerFeedbackLevel(Texture2DArray<S> texArray, SamplerState samp, float3 location, float lod) { texture->WriteSamplerFeedbackLevel(texArray.texture, samp, &location.x, lod); }\n\n    // Without Clamp\n\n    template <typename S>\n    void WriteSamplerFeedback(Texture2DArray<S> texArray, SamplerState samp, float3 location) { texture->WriteSamplerFeedback(texArray.texture, samp, &location.x); }\n\n    template <typename S>\n    void WriteSamplerFeedbackBias(Texture2DArray<S> texArray, SamplerState samp, float3 location, float bias) { texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias); }\n\n    template <typename S>\n    void WriteSamplerFeedbackGrad(Texture2DArray<S> texArray, SamplerState samp, float3 location, float3 ddx, float3 ddy) { texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x); }\n    \n    IFeedbackTexture* texture;\n};\n\n/* Varying input for Compute */\n\n/* Used when running a single thread */\nstruct ComputeThreadVaryingInput\n{\n    uint3 groupID;\n    uint3 groupThreadID;\n};\n\nstruct ComputeVaryingInput\n{\n    uint3 startGroupID;     ///< start groupID\n    uint3 endGroupID;       ///< Non inclusive end groupID\n};\n\n// The uniformEntryPointParams and uniformState must be set to structures that match layout that the kernel expects.\n// This can be determined via reflection for example.\n\ntypedef void(*ComputeThreadFunc)(ComputeThreadVaryingInput* varyingInput, void* uniformEntryPointParams, void* uniformState);\ntypedef void(*ComputeFunc)(ComputeVaryingInput* varyingInput, void* uniformEntryPointParams, void* uniformState);\n\ntemplate<typename TResult, typename TInput>\nTResult slang_bit_cast(TInput val)\n{\n    return *(TResult*)(&val);\n}\n\n#ifdef SLANG_PRELUDE_NAMESPACE\n}\n#endif\n\n#endif\n\n\n"
  },
  {
    "path": "Source/External/slang/prelude/slang-cuda-prelude.h",
    "content": "// Define SLANG_CUDA_ENABLE_HALF to use the cuda_fp16 include to add half support. \n// For this to work NVRTC needs to have the path to the CUDA SDK.\n//\n// As it stands the includes paths defined for Slang are passed down to NVRTC. Similarly defines defined for the Slang compile\n// are passed down. \n\n#ifdef SLANG_CUDA_ENABLE_HALF\n// We don't want half2 operators, because it will implement comparison operators that return a bool(!). We want to generate\n// those functions. Doing so means that we will have to define all the other half2 operators.\n#   define __CUDA_NO_HALF2_OPERATORS__\n#   include <cuda_fp16.h>\n#endif\n\n#ifdef SLANG_CUDA_ENABLE_OPTIX\n#include <optix.h>\n#endif\n\n// Define slang offsetof implementation \n#ifndef SLANG_OFFSET_OF\n#   define SLANG_OFFSET_OF(type, member) (size_t)((char*)&(((type *)0)->member) - (char*)0)\n#endif\n\n#ifndef SLANG_ALIGN_OF\n#   define SLANG_ALIGN_OF(type) __alignof__(type)\n#endif\n\n// Must be large enough to cause overflow and therefore infinity\n#ifndef SLANG_INFINITY\n#   define SLANG_INFINITY   ((float)(1e+300 * 1e+300))\n#endif\n\n// For now we'll disable any asserts in this prelude\n#define SLANG_PRELUDE_ASSERT(x) \n\n#ifndef SLANG_CUDA_WARP_SIZE \n#   define SLANG_CUDA_WARP_SIZE 32\n#endif\n\n#define SLANG_CUDA_WARP_MASK (SLANG_CUDA_WARP_SIZE - 1)\n\n//\n#define SLANG_FORCE_INLINE inline\n\n#define SLANG_CUDA_CALL __device__ \n\n#define SLANG_FORCE_INLINE inline\n#define SLANG_INLINE inline\n\n\n// Since we are using unsigned arithmatic care is need in this comparison.\n// It is *assumed* that sizeInBytes >= elemSize. Which means (sizeInBytes >= elemSize) >= 0\n// Which means only a single test is needed\n\n// Asserts for bounds checking.\n// It is assumed index/count are unsigned types.\n#define SLANG_BOUND_ASSERT(index, count)  SLANG_PRELUDE_ASSERT(index < count); \n#define SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3) == 0);\n\n// Macros to zero index if an access is out of range\n#define SLANG_BOUND_ZERO_INDEX(index, count) index = (index < count) ? index : 0; \n#define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) index = (index <= (sizeInBytes - elemSize)) ? index : 0; \n\n// The 'FIX' macro define how the index is fixed. The default is to do nothing. If SLANG_ENABLE_BOUND_ZERO_INDEX\n// the fix macro will zero the index, if out of range\n#ifdef  SLANG_ENABLE_BOUND_ZERO_INDEX\n#   define SLANG_BOUND_FIX(index, count) SLANG_BOUND_ZERO_INDEX(index, count)\n#   define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes)\n#   define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) SLANG_BOUND_ZERO_INDEX(index, count) SLANG_BOUND_ZERO_INDEX(index, count)\n#else\n#   define SLANG_BOUND_FIX(index, count) \n#   define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) \n#   define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) \n#endif\n\n#ifndef SLANG_BOUND_CHECK\n#   define SLANG_BOUND_CHECK(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count)\n#endif\n\n#ifndef SLANG_BOUND_CHECK_BYTE_ADDRESS\n#   define SLANG_BOUND_CHECK_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes)\n#endif\n\n#ifndef SLANG_BOUND_CHECK_FIXED_ARRAY\n#   define SLANG_BOUND_CHECK_FIXED_ARRAY(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count)\n#endif\n\n // This macro handles how out-of-range surface coordinates are handled; \n // I can equal\n // cudaBoundaryModeClamp, in which case out-of-range coordinates are clamped to the valid range\n // cudaBoundaryModeZero, in which case out-of-range reads return zero and out-of-range writes are ignored\n // cudaBoundaryModeTrap, in which case out-of-range accesses cause the kernel execution to fail. \n \n#ifndef SLANG_CUDA_BOUNDARY_MODE\n#   define SLANG_CUDA_BOUNDARY_MODE cudaBoundaryModeZero\n\n// Can be one of SLANG_CUDA_PTX_BOUNDARY_MODE. Only applies *PTX* emitted CUDA operations\n// which currently is just RWTextureRW format writes\n// \n// .trap         causes an execution trap on out-of-bounds addresses\n// .clamp        stores data at the nearest surface location (sized appropriately)\n// .zero         drops stores to out-of-bounds addresses \n\n#   define SLANG_PTX_BOUNDARY_MODE \"zero\"\n#endif\n\nstruct TypeInfo\n{\n    size_t typeSize;\n};\n\ntemplate <typename T, size_t SIZE>\nstruct FixedArray\n{\n    SLANG_CUDA_CALL const T& operator[](size_t index) const { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; }\n    SLANG_CUDA_CALL T& operator[](size_t index) { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; }\n    \n    T m_data[SIZE];\n};\n\n// An array that has no specified size, becomes a 'Array'. This stores the size so it can potentially \n// do bounds checking.  \ntemplate <typename T>\nstruct Array\n{\n    SLANG_CUDA_CALL const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    SLANG_CUDA_CALL T& operator[](size_t index) { SLANG_BOUND_CHECK(index, count); return data[index]; }\n    \n    T* data;\n    size_t count;\n};\n\n// Typically defined in cuda.h, but we can't ship/rely on that, so just define here\ntypedef unsigned long long CUtexObject;                   \ntypedef unsigned long long CUsurfObject;                  \n\n// On CUDA sampler state is actually bound up with the texture object. We have a SamplerState type, \n// backed as a pointer, to simplify code generation, with the downside that such a binding will take up \n// uniform space, even though it will have no effect. \n// TODO(JS): Consider ways to strip use of variables of this type so have no binding,\nstruct SamplerStateUnused;\ntypedef SamplerStateUnused* SamplerState;\n\n\n// TODO(JS): Not clear yet if this can be handled on CUDA, by just ignoring.\n// For now, just map to the index type. \ntypedef size_t NonUniformResourceIndex;\n\n// Code generator will generate the specific type\ntemplate <typename T, int ROWS, int COLS>\nstruct Matrix;\n\ntypedef bool bool1;\ntypedef int2 bool2;\ntypedef int3 bool3;\ntypedef int4 bool4; \n\n\ntypedef signed char int8_t;\ntypedef short int16_t;\ntypedef int int32_t;\ntypedef long long int64_t;\n\ntypedef unsigned char uint8_t;\ntypedef unsigned short uint16_t;\ntypedef unsigned int uint32_t;\ntypedef unsigned long long uint64_t;\n\ntypedef long long longlong;\ntypedef unsigned long long ulonglong;\n\ntypedef unsigned char uchar;\ntypedef unsigned short ushort;\ntypedef unsigned int uint;\n\nunion Union32 \n{\n    uint32_t u;\n    int32_t i;\n    float f;\n};\n\nunion Union64\n{\n    uint64_t u;\n    int64_t i;\n    double d;\n};\n\n//\n// Half support\n// \n\n#if SLANG_CUDA_ENABLE_HALF\n\n// Add the other vector half types\nstruct __half3 { __half2 xy; __half z; };\nstruct __half4 { __half2 xy; __half2 zw; };\n\n// *** convert ***\n\n// half -> other\n\n// float\nSLANG_FORCE_INLINE SLANG_CUDA_CALL float2 convert_float2(const __half2& v) { return __half22float2(v); } \nSLANG_FORCE_INLINE SLANG_CUDA_CALL float3 convert_float3(const __half3& v) { const float2 xy = __half22float2(v.xy); return float3{xy.x, xy.y, __half2float(v.z)}; } \nSLANG_FORCE_INLINE SLANG_CUDA_CALL float4 convert_float4(const __half4& v) { const float2 xy = __half22float2(v.xy); const float2 zw = __half22float2(v.zw); return float4{xy.x, xy.y, zw.x, zw.y}; }\n\n// double\nSLANG_FORCE_INLINE SLANG_CUDA_CALL double2 convert_double2(const __half2& v) { const float2 xy = __half22float2(v); return double2{ xy.x, xy.y }; } \nSLANG_FORCE_INLINE SLANG_CUDA_CALL double3 convert_double3(const __half3& v) { const float2 xy = __half22float2(v.xy); return double3{ xy.x, xy.y, __half2float(v.z)}; } \nSLANG_FORCE_INLINE SLANG_CUDA_CALL double4 convert_double4(const __half4& v) { const float2 xy = __half22float2(v.xy); const float2 zw = __half22float2(v.zw); return double4{xy.x, xy.y, zw.x, zw.y}; }\n\n// int\nSLANG_FORCE_INLINE SLANG_CUDA_CALL int2 convert_int2(const __half2& v) { return int2 { __half2int_rz(v.x), __half2int_rz(v.y) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL int3 convert_int3(const __half3& v) { return int3 { __half2int_rz(v.xy.x), __half2int_rz(v.xy.y), __half2int_rz(v.z) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL int4 convert_int4(const __half4& v) { return int4 { __half2int_rz(v.xy.x), __half2int_rz(v.xy.y), __half2int_rz(v.zw.x), __half2int_rz(v.zw.y)}; }\n\n// uint\nSLANG_FORCE_INLINE SLANG_CUDA_CALL uint2 convert_uint2(const __half2& v) { return uint2 { __half2uint_rz(v.x), __half2uint_rz(v.y) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL uint3 convert_uint3(const __half3& v) { return uint3 { __half2uint_rz(v.xy.x), __half2uint_rz(v.xy.y), __half2uint_rz(v.z) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL uint4 convert_uint4(const __half4& v) { return uint4 { __half2uint_rz(v.xy.x), __half2uint_rz(v.xy.y), __half2uint_rz(v.zw.x), __half2uint_rz(v.zw.y)}; }\n\n// other -> half\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 convert___half2(const float2& v) { return __float22half2_rn(v); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 convert___half3(const float3& v) { return __half3{ __float22half2_rn(float2{v.x, v.y}), __float2half_rn(v.z) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 convert___half4(const float4& v) { return __half4{ __float22half2_rn(float2{v.x, v.y}), __float22half2_rn(float2{v.z, v.w}) }; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 convert___half2(const int2& v) { return __half2{ __int2half_rz(v.x), __int2half_rz(v.y) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 convert___half3(const int3& v) { return __half3{ __half2{__int2half_rz(v.x), __int2half_rz(v.y)}, __int2half_rz(v.z) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 convert___half4(const int4& v) { return __half4{ __half2{__int2half_rz(v.x), __int2half_rz(v.y)}, __half2{__int2half_rz(v.z),  __int2half_rz(v.w)} }; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 convert___half2(const uint2& v) { return __half2{ __uint2half_rz(v.x), __uint2half_rz(v.y) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 convert___half3(const uint3& v) { return __half3{ __half2{__uint2half_rz(v.x), __uint2half_rz(v.y)}, __uint2half_rz(v.z) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 convert___half4(const uint4& v) { return __half4{ __half2{__uint2half_rz(v.x), __uint2half_rz(v.y)}, __half2{__uint2half_rz(v.z),  __uint2half_rz(v.w)} }; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 convert___half2(const double2& v) { return __float22half2_rn(float2{v.x, v.y}); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 convert___half3(const double3& v) { return __half3{ __float22half2_rn(float2{v.x, v.y}), __float2half_rn(v.z) }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 convert___half4(const double4& v) { return __half4{ __float22half2_rn(float2{v.x, v.y}), __float22half2_rn(float2{v.z, v.w}) }; }\n\n// *** make ***\n\n// Mechanism to make half vectors\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 make___half2(__half x, __half y) { return __halves2half2(x, y); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 make___half3(__half x, __half y, __half z) { return __half3{ __halves2half2(x, y), z }; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 make___half4(__half x, __half y, __half z, __half w) { return __half4{ __halves2half2(x, y), __halves2half2(z, w)}; }\n\n// *** constructFromScalar ***\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 constructFromScalar___half2(half x) { return __half2half2(x); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 constructFromScalar___half3(half x) { return __half3{__half2half2(x), x}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 constructFromScalar___half4(half x) { const __half2 v = __half2half2(x); return __half4{v, v}; }\n\n// *** half2 ***\n\n// half2 maths ops\n\n// NOTE! That by default these are in cuda_fp16.hpp, but we disable them, because we need to define the comparison operators\n// as we need versions that will return vector<bool>\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator+(const __half2& lh, const __half2& rh) { return __hadd2(lh, rh); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator-(const __half2& lh, const __half2& rh) { return __hsub2(lh, rh); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator*(const __half2& lh, const __half2& rh) { return __hmul2(lh, rh); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator/(const __half2& lh, const __half2& rh) { return __h2div(lh, rh); }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2& operator+=(__half2& lh, const __half2& rh) { lh = __hadd2(lh, rh); return lh; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2& operator-=(__half2& lh, const __half2& rh) { lh = __hsub2(lh, rh); return lh; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2& operator*=(__half2& lh, const __half2& rh) { lh = __hmul2(lh, rh); return lh; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2& operator/=(__half2& lh, const __half2& rh) { lh = __h2div(lh, rh); return lh; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 &operator++(__half2 &h)      { __half2_raw one; one.x = 0x3C00; one.y = 0x3C00; h = __hadd2(h, one); return h; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 &operator--(__half2 &h)      { __half2_raw one; one.x = 0x3C00; one.y = 0x3C00; h = __hsub2(h, one); return h; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2  operator++(__half2 &h, int) { __half2 ret = h; __half2_raw one; one.x = 0x3C00; one.y = 0x3C00; h = __hadd2(h, one); return ret; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2  operator--(__half2 &h, int) { __half2 ret = h; __half2_raw one; one.x = 0x3C00; one.y = 0x3C00; h = __hsub2(h, one); return ret; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator+(const __half2 &h) { return h; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator-(const __half2 &h) { return __hneg2(h); }\n\n// vec op scalar\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator+(const __half2& lh, __half rh) { return __hadd2(lh, __half2half2(rh)); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator-(const __half2& lh, __half rh) { return __hsub2(lh, __half2half2(rh)); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator*(const __half2& lh, __half rh) { return __hmul2(lh, __half2half2(rh)); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator/(const __half2& lh, __half rh) { return __h2div(lh, __half2half2(rh)); }\n\n// scalar op vec\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator+(__half lh, const __half2& rh) { return __hadd2(__half2half2(lh), rh); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator-(__half lh, const __half2& rh) { return __hsub2(__half2half2(lh), rh); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator*(__half lh, const __half2& rh) { return __hmul2(__half2half2(lh), rh); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 operator/(__half lh, const __half2& rh) { return __h2div(__half2half2(lh), rh); }\n\n// *** half3 ***\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator+(const __half3& lh, const __half3& rh) { return __half3{__hadd2(lh.xy, rh.xy), __hadd(lh.z, rh.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator-(const __half3& lh, const __half3& rh) { return __half3{__hsub2(lh.xy, rh.xy), __hsub(lh.z, rh.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator*(const __half3& lh, const __half3& rh) { return __half3{__hmul2(lh.xy, rh.xy), __hmul(lh.z, rh.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator/(const __half3& lh, const __half3& rh) { return __half3{__h2div(lh.xy, rh.xy), __hdiv(lh.z, rh.z)}; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator-(const __half3& h) { return __half3{__hneg2(h.xy), __hneg(h.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator+(const __half3& h) { return h; }\n\n// vec op scalar\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator+(const __half3& lh, __half rh) { return __half3{__hadd2(lh.xy, __half2half2(rh)), __hadd(lh.z, rh)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator-(const __half3& lh, __half rh) { return __half3{__hsub2(lh.xy, __half2half2(rh)), __hsub(lh.z, rh)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator*(const __half3& lh, __half rh) { return __half3{__hmul2(lh.xy, __half2half2(rh)), __hmul(lh.z, rh)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator/(const __half3& lh, __half rh) { return __half3{__h2div(lh.xy, __half2half2(rh)), __hdiv(lh.z, rh)}; }\n\n// scalar op vec\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator+(__half lh, const __half3& rh) { return __half3{__hadd2(__half2half2(lh), rh.xy), __hadd(lh, rh.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator-(__half lh, const __half3& rh) { return __half3{__hsub2(__half2half2(lh), rh.xy), __hsub(lh, rh.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator*(__half lh, const __half3& rh) { return __half3{__hmul2(__half2half2(lh), rh.xy), __hmul(lh, rh.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 operator/(__half lh, const __half3& rh) { return __half3{__h2div(__half2half2(lh), rh.xy), __hdiv(lh, rh.z)}; }\n\n// *** half4 ***\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator+(const __half4& lh, const __half4& rh) { return __half4{__hadd2(lh.xy, rh.xy), __hadd2(lh.zw, rh.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator-(const __half4& lh, const __half4& rh) { return __half4{__hsub2(lh.xy, rh.xy), __hsub2(lh.zw, rh.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator*(const __half4& lh, const __half4& rh) { return __half4{__hmul2(lh.xy, rh.xy), __hmul2(lh.zw, rh.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator/(const __half4& lh, const __half4& rh) { return __half4{__h2div(lh.xy, rh.xy), __h2div(lh.zw, rh.zw)}; }\n\n// vec op scalar\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator+(const __half4& lh, __half rh) { const __half2 rhv = __half2half2(rh); return __half4{__hadd2(lh.xy, rhv), __hadd2(lh.zw, rhv)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator-(const __half4& lh, __half rh) { const __half2 rhv = __half2half2(rh); return __half4{__hsub2(lh.xy, rhv), __hsub2(lh.zw, rhv)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator*(const __half4& lh, __half rh) { const __half2 rhv = __half2half2(rh); return __half4{__hmul2(lh.xy, rhv), __hmul2(lh.zw, rhv)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator/(const __half4& lh, __half rh) { const __half2 rhv = __half2half2(rh); return __half4{__h2div(lh.xy, rhv), __h2div(lh.zw, rhv)}; }\n\n// scalar op vec\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator+(__half lh, const __half4& rh) { const __half2 lhv = __half2half2(lh); return __half4{__hadd2(lhv, rh.xy), __hadd2(lhv, rh.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator-(__half lh, const __half4& rh) { const __half2 lhv = __half2half2(lh); return __half4{__hsub2(lhv, rh.xy), __hsub2(lhv, rh.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator*(__half lh, const __half4& rh) { const __half2 lhv = __half2half2(lh); return __half4{__hmul2(lhv, rh.xy), __hmul2(lhv, rh.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator/(__half lh, const __half4& rh) { const __half2 lhv = __half2half2(lh); return __half4{__h2div(lhv, rh.xy), __h2div(lhv, rh.zw)}; }\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator-(const __half4& h) { return __half4{__hneg2(h.xy), __hneg2(h.zw)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 operator+(const __half4& h) { return h; }\n\n// Convenience functions ushort -> half\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 __ushort_as_half(const ushort2& i) { return __halves2half2(__ushort_as_half(i.x), __ushort_as_half(i.y)); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 __ushort_as_half(const ushort3& i) { return __half3{__halves2half2(__ushort_as_half(i.x), __ushort_as_half(i.y)), __ushort_as_half(i.z)}; }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 __ushort_as_half(const ushort4& i) { return __half4{ __halves2half2(__ushort_as_half(i.x), __ushort_as_half(i.y)), __halves2half2(__ushort_as_half(i.z), __ushort_as_half(i.w)) }; }\n\n// Convenience functions half -> ushort\n\nSLANG_FORCE_INLINE SLANG_CUDA_CALL ushort2 __half_as_ushort(const __half2& i) { return make_ushort2(__half_as_ushort(i.x), __half_as_ushort(i.y)); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL ushort3 __half_as_ushort(const __half3& i) { return make_ushort3(__half_as_ushort(i.xy.x), __half_as_ushort(i.xy.y), __half_as_ushort(i.z)); }\nSLANG_FORCE_INLINE SLANG_CUDA_CALL ushort4 __half_as_ushort(const __half4& i) { return make_ushort4(__half_as_ushort(i.xy.x), __half_as_ushort(i.xy.y), __half_as_ushort(i.zw.x), __half_as_ushort(i.zw.y)); }\n\n// This is a little bit of a hack. Fortunately CUDA has the definitions of the templated types in \n// include/surface_indirect_functions.h\n// Here we find the template definition requires a specialization of __nv_isurf_trait to allow \n// a specialization of the surface write functions. \n// This *isn't* a problem on the read functions as they don't have a return type that uses this mechanism \n\ntemplate<> struct __nv_isurf_trait<__half> { typedef void type; };\ntemplate<> struct __nv_isurf_trait<__half2> { typedef void type; };\ntemplate<> struct __nv_isurf_trait<__half4> { typedef void type; };\n\n#define SLANG_DROP_PARENS(...) __VA_ARGS__\n\n#define SLANG_SURFACE_READ(FUNC_NAME, TYPE_ARGS, ARGS) \\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half FUNC_NAME<__half>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    return __ushort_as_half(FUNC_NAME<ushort>(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \\\n} \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 FUNC_NAME<__half2>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    return __ushort_as_half(FUNC_NAME<ushort2>(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \\\n} \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 FUNC_NAME<__half4>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    return __ushort_as_half(FUNC_NAME<ushort4>(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \\\n}\n\nSLANG_SURFACE_READ(surf1Dread, (int x), (x))\nSLANG_SURFACE_READ(surf2Dread, (int x, int y), (x, y))\nSLANG_SURFACE_READ(surf3Dread, (int x, int y, int z), (x, y, z))\nSLANG_SURFACE_READ(surf1DLayeredread, (int x, int layer), (x, layer))\nSLANG_SURFACE_READ(surf2DLayeredread, (int x, int y, int layer), (x, y, layer))\nSLANG_SURFACE_READ(surfCubemapread, (int x, int y, int face), (x, y, face))\nSLANG_SURFACE_READ(surfCubemapLayeredread, (int x, int y, int layerFace), (x, y, layerFace))\n\n#define SLANG_SURFACE_WRITE(FUNC_NAME, TYPE_ARGS, ARGS) \\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half>(__half data, cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    FUNC_NAME<ushort>(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode);  \\\n} \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half2>(__half2 data, cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    FUNC_NAME<ushort2>(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode);  \\\n} \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half4>(__half4 data, cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    FUNC_NAME<ushort4>(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \\\n}\n\nSLANG_SURFACE_WRITE(surf1Dwrite, (int x), (x))\nSLANG_SURFACE_WRITE(surf2Dwrite, (int x, int y), (x, y))\nSLANG_SURFACE_WRITE(surf3Dwrite, (int x, int y, int z), (x, y, z))\nSLANG_SURFACE_WRITE(surf1DLayeredwrite, (int x, int layer), (x, layer))\nSLANG_SURFACE_WRITE(surf2DLayeredwrite, (int x, int y, int layer), (x, y, layer))\nSLANG_SURFACE_WRITE(surfCubemapwrite, (int x, int y, int face), (x, y, face))\nSLANG_SURFACE_WRITE(surfCubemapLayeredwrite, (int x, int y, int layerFace), (x, y, layerFace))\n\n// ! Hack to test out reading !!!\n// Only works converting *from* half \n \n//template <typename T> \n//SLANG_FORCE_INLINE SLANG_CUDA_CALL T surf2Dread_convert(cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode);\n\n#define SLANG_SURFACE_READ_HALF_CONVERT(FUNC_NAME, TYPE_ARGS, ARGS) \\\n\\\ntemplate <typename T>  \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL T FUNC_NAME##_convert(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode); \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL float FUNC_NAME##_convert<float>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode)  \\\n{ \\\n    return __ushort_as_half(FUNC_NAME<uint16_t>(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \\\n} \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL float2 FUNC_NAME##_convert<float2>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    const __half2 v = __ushort_as_half(FUNC_NAME<ushort2>(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \\\n    return float2{v.x, v.y}; \\\n} \\\n\\\ntemplate <> \\\nSLANG_FORCE_INLINE SLANG_CUDA_CALL float4 FUNC_NAME##_convert<float4>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \\\n{ \\\n    const __half4 v = __ushort_as_half(FUNC_NAME<ushort4>(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \\\n    return float4{v.xy.x, v.xy.y, v.zw.x, v.zw.y}; \\\n}\n\nSLANG_SURFACE_READ_HALF_CONVERT(surf1Dread, (int x), (x)) \nSLANG_SURFACE_READ_HALF_CONVERT(surf2Dread, (int x, int y), (x, y)) \nSLANG_SURFACE_READ_HALF_CONVERT(surf3Dread, (int x, int y, int z), (x, y, z))\n\n#endif\n\n// Support for doing format conversion when writing to a surface/RWTexture\n\n// NOTE! For normal surface access x values are *byte* addressed.\n// For the _convert versions they are *not*. They don't need to be because sust.p does not require it.\n\ntemplate <typename T>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert(T, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode);\ntemplate <typename T>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert(T, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode);\ntemplate <typename T>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert(T, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode);\n\n// https://docs.nvidia.com/cuda/inline-ptx-assembly/index.html\n// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#surface-instructions-sust\n\n// Float\n\ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert<float>(float v, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode)\n{\n    asm volatile ( \"{sust.p.1d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1}], {%2};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"f\"(v));     \n}\n \ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert<float>(float v, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode)\n{\n    asm volatile ( \"{sust.p.2d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1,%2}], {%3};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"r\"(y),\"f\"(v));\n}\n\ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert<float>(float v, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode)\n{\n    asm volatile ( \"{sust.p.2d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1,%2,%3}], {%4};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"r\"(y),\"r\"(z),\"f\"(v));\n}\n\n// Float2\n\ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert<float2>(float2 v, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode)\n{\n    const float vx = v.x, vy = v.y;\n    asm volatile ( \"{sust.p.1d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1}], {%2,%3};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"f\"(vx),\"f\"(vy));     \n}\n \ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert<float2>(float2 v, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode)\n{\n    const float vx = v.x, vy = v.y;\n    asm volatile ( \"{sust.p.2d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1,%2}], {%3,%4};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"r\"(y),\"f\"(vx),\"f\"(vy));\n}\n\ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert<float2>(float2 v, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode)\n{\n    const float vx = v.x, vy = v.y;\n    asm volatile ( \"{sust.p.2d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1,%2,%3}], {%4,%5};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"r\"(y),\"r\"(z),\"f\"(vx),\"f\"(vy));\n}\n\n// Float4\ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert<float4>(float4 v, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode)\n{\n    const float vx = v.x, vy = v.y, vz = v.z, vw = v.w;\n    asm volatile ( \"{sust.p.1d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1}], {%2,%3,%4,%5};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"f\"(vx),\"f\"(vy),\"f\"(vz),\"f\"(vw));     \n}\n \ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert<float4>(float4 v, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode)\n{\n    const float vx = v.x, vy = v.y, vz = v.z, vw = v.w;\n    asm volatile ( \"{sust.p.2d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1,%2}], {%3,%4,%5,%6};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"r\"(y),\"f\"(vx),\"f\"(vy),\"f\"(vz),\"f\"(vw));\n}\n\ntemplate <>\nSLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert<float4>(float4 v, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode)\n{\n    const float vx = v.x, vy = v.y, vz = v.z, vw = v.w;\n    asm volatile ( \"{sust.p.2d.b32.\" SLANG_PTX_BOUNDARY_MODE \" [%0, {%1,%2,%3}], {%4,%5,%6,%7};}\\n\\t\" :: \"l\"(surfObj),\"r\"(x),\"r\"(y),\"r\"(z),\"f\"(vx),\"f\"(vy),\"f\"(vz),\"f\"(vw));\n}\n\n// ----------------------------- F32 -----------------------------------------\n\n// Unary \nSLANG_CUDA_CALL float F32_ceil(float f) { return ::ceilf(f); }\nSLANG_CUDA_CALL float F32_floor(float f) { return ::floorf(f); }\nSLANG_CUDA_CALL float F32_round(float f) { return ::roundf(f); }\nSLANG_CUDA_CALL float F32_sin(float f) { return ::sinf(f); }\nSLANG_CUDA_CALL float F32_cos(float f) { return ::cosf(f); }\nSLANG_CUDA_CALL void F32_sincos(float f, float* s, float* c) { ::sincosf(f, s, c); }\nSLANG_CUDA_CALL float F32_tan(float f) { return ::tanf(f); }\nSLANG_CUDA_CALL float F32_asin(float f) { return ::asinf(f); }\nSLANG_CUDA_CALL float F32_acos(float f) { return ::acosf(f); }\nSLANG_CUDA_CALL float F32_atan(float f) { return ::atanf(f); }\nSLANG_CUDA_CALL float F32_sinh(float f) { return ::sinhf(f); }\nSLANG_CUDA_CALL float F32_cosh(float f) { return ::coshf(f); }\nSLANG_CUDA_CALL float F32_tanh(float f) { return ::tanhf(f); }\nSLANG_CUDA_CALL float F32_log2(float f) { return ::log2f(f); }\nSLANG_CUDA_CALL float F32_log(float f) { return ::logf(f); }\nSLANG_CUDA_CALL float F32_log10(float f) { return ::log10f(f); }\nSLANG_CUDA_CALL float F32_exp2(float f) { return ::exp2f(f); }\nSLANG_CUDA_CALL float F32_exp(float f) { return ::expf(f); }\nSLANG_CUDA_CALL float F32_abs(float f) { return ::fabsf(f); }\nSLANG_CUDA_CALL float F32_trunc(float f) { return ::truncf(f); }\nSLANG_CUDA_CALL float F32_sqrt(float f) { return ::sqrtf(f); }\nSLANG_CUDA_CALL float F32_rsqrt(float f) { return ::rsqrtf(f); }\nSLANG_CUDA_CALL float F32_sign(float f) { return ( f == 0.0f) ? f : (( f < 0.0f) ? -1.0f : 1.0f); } \nSLANG_CUDA_CALL float F32_frac(float f) { return f - F32_floor(f); }\n\nSLANG_CUDA_CALL bool F32_isnan(float f) { return isnan(f); }\nSLANG_CUDA_CALL bool F32_isfinite(float f) { return isfinite(f); }\nSLANG_CUDA_CALL bool F32_isinf(float f) { return isinf(f); }\n\n// Binary\nSLANG_CUDA_CALL float F32_min(float a, float b) { return ::fminf(a, b); }\nSLANG_CUDA_CALL float F32_max(float a, float b) { return ::fmaxf(a, b); }\nSLANG_CUDA_CALL float F32_pow(float a, float b) { return ::powf(a, b); }\nSLANG_CUDA_CALL float F32_fmod(float a, float b) { return ::fmodf(a, b); }\nSLANG_CUDA_CALL float F32_remainder(float a, float b) { return ::remainderf(a, b); }\nSLANG_CUDA_CALL float F32_atan2(float a, float b) { return float(::atan2(a, b)); }\n\nSLANG_CUDA_CALL float F32_frexp(float x, float* e)\n{\n    int ei;\n    float m = ::frexpf(x, &ei);\n    *e = ei;\n    return m;\n}\nSLANG_CUDA_CALL float F32_modf(float x, float* ip)\n{\n    return ::modff(x, ip);\n}\n\nSLANG_CUDA_CALL uint32_t F32_asuint(float f) { Union32 u; u.f = f; return u.u; }\nSLANG_CUDA_CALL int32_t F32_asint(float f) { Union32 u; u.f = f; return u.i; }\n\n// Ternary\nSLANG_CUDA_CALL float F32_fma(float a, float b, float c) { return ::fmaf(a, b, c); }\n\n\n// ----------------------------- F64 -----------------------------------------\n\n// Unary \nSLANG_CUDA_CALL double F64_ceil(double f) { return ::ceil(f); }\nSLANG_CUDA_CALL double F64_floor(double f) { return ::floor(f); }\nSLANG_CUDA_CALL double F64_round(double f) { return ::round(f); }\nSLANG_CUDA_CALL double F64_sin(double f) { return ::sin(f); }\nSLANG_CUDA_CALL double F64_cos(double f) { return ::cos(f); }\nSLANG_CUDA_CALL void F64_sincos(double f, double* s, double* c) { ::sincos(f, s, c); }\nSLANG_CUDA_CALL double F64_tan(double f) { return ::tan(f); }\nSLANG_CUDA_CALL double F64_asin(double f) { return ::asin(f); }\nSLANG_CUDA_CALL double F64_acos(double f) { return ::acos(f); }\nSLANG_CUDA_CALL double F64_atan(double f) { return ::atan(f); }\nSLANG_CUDA_CALL double F64_sinh(double f) { return ::sinh(f); }\nSLANG_CUDA_CALL double F64_cosh(double f) { return ::cosh(f); }\nSLANG_CUDA_CALL double F64_tanh(double f) { return ::tanh(f); }\nSLANG_CUDA_CALL double F64_log2(double f) { return ::log2(f); }\nSLANG_CUDA_CALL double F64_log(double f) { return ::log(f); }\nSLANG_CUDA_CALL double F64_log10(float f) { return ::log10(f); }\nSLANG_CUDA_CALL double F64_exp2(double f) { return ::exp2(f); }\nSLANG_CUDA_CALL double F64_exp(double f) { return ::exp(f); }\nSLANG_CUDA_CALL double F64_abs(double f) { return ::fabs(f); }\nSLANG_CUDA_CALL double F64_trunc(double f) { return ::trunc(f); }\nSLANG_CUDA_CALL double F64_sqrt(double f) { return ::sqrt(f); }\nSLANG_CUDA_CALL double F64_rsqrt(double f) { return ::rsqrt(f); }\nSLANG_CUDA_CALL double F64_sign(double f) { return (f == 0.0) ? f : ((f < 0.0) ? -1.0 : 1.0); }\nSLANG_CUDA_CALL double F64_frac(double f) { return f - F64_floor(f); }\n\nSLANG_CUDA_CALL bool F64_isnan(double f) { return isnan(f); }\nSLANG_CUDA_CALL bool F64_isfinite(double f) { return isfinite(f); }\nSLANG_CUDA_CALL bool F64_isinf(double f) { return isinf(f); }\n\n// Binary\nSLANG_CUDA_CALL double F64_min(double a, double b) { return ::fmin(a, b); }\nSLANG_CUDA_CALL double F64_max(double a, double b) { return ::fmax(a, b); }\nSLANG_CUDA_CALL double F64_pow(double a, double b) { return ::pow(a, b); }\nSLANG_CUDA_CALL double F64_fmod(double a, double b) { return ::fmod(a, b); }\nSLANG_CUDA_CALL double F64_remainder(double a, double b) { return ::remainder(a, b); }\nSLANG_CUDA_CALL double F64_atan2(double a, double b) { return ::atan2(a, b); }\n\nSLANG_CUDA_CALL double F64_frexp(double x, double* e)\n{\n    int ei;\n    double m = ::frexp(x, &ei);\n    *e = ei;\n    return m;\n}\nSLANG_CUDA_CALL double F64_modf(double x, double* ip)\n{\n    return ::modf(x, ip);\n}\n\nSLANG_CUDA_CALL void F64_asuint(double d, uint32_t* low, uint32_t* hi)\n{\n    Union64 u;\n    u.d = d;\n    *low = uint32_t(u.u);\n    *hi = uint32_t(u.u >> 32);\n}\n\nSLANG_CUDA_CALL void F64_asint(double d, int32_t* low, int32_t* hi)\n{\n    Union64 u;\n    u.d = d;\n    *low = int32_t(u.u);\n    *hi = int32_t(u.u >> 32);\n}\n\n// Ternary\nSLANG_CUDA_CALL double F64_fma(double a, double b, double c) { return ::fma(a, b, c); }\n\n// ----------------------------- I32 -----------------------------------------\n\n// Unary\nSLANG_CUDA_CALL int32_t I32_abs(int32_t f) { return (f < 0) ? -f : f; }\n\n// Binary\nSLANG_CUDA_CALL int32_t I32_min(int32_t a, int32_t b) { return a < b ? a : b; }\nSLANG_CUDA_CALL int32_t I32_max(int32_t a, int32_t b) { return a > b ? a : b; }\n\nSLANG_CUDA_CALL float I32_asfloat(int32_t x) { Union32 u; u.i = x; return u.f; }\nSLANG_CUDA_CALL uint32_t I32_asuint(int32_t x) { return uint32_t(x); }\nSLANG_CUDA_CALL double I32_asdouble(int32_t low, int32_t hi )\n{\n    Union64 u;\n    u.u = (uint64_t(hi) << 32) | uint32_t(low);\n    return u.d;\n}\n\n// ----------------------------- U32 -----------------------------------------\n\n// Unary \nSLANG_CUDA_CALL uint32_t U32_abs(uint32_t f) { return f; }\n\n// Binary\nSLANG_CUDA_CALL uint32_t U32_min(uint32_t a, uint32_t b) { return a < b ? a : b; }\nSLANG_CUDA_CALL uint32_t U32_max(uint32_t a, uint32_t b) { return a > b ? a : b; }\n\nSLANG_CUDA_CALL float U32_asfloat(uint32_t x) { Union32 u; u.u = x; return u.f; }\nSLANG_CUDA_CALL uint32_t U32_asint(int32_t x) { return uint32_t(x); } \n\nSLANG_CUDA_CALL double U32_asdouble(uint32_t low, uint32_t hi)\n{\n    Union64 u;\n    u.u = (uint64_t(hi) << 32) | low;\n    return u.d;\n}\n\nSLANG_CUDA_CALL uint32_t U32_countbits(uint32_t v)\n{\n    // https://docs.nvidia.com/cuda/cuda-math-api/group__CUDA__MATH__INTRINSIC__INT.html#group__CUDA__MATH__INTRINSIC__INT_1g43c9c7d2b9ebf202ff1ef5769989be46\n    return __popc(v);\n}\n\n\n// ----------------------------- I64 -----------------------------------------\n\nSLANG_CUDA_CALL int64_t I64_abs(int64_t f) { return (f < 0) ? -f : f; }\n\nSLANG_CUDA_CALL int64_t I64_min(int64_t a, int64_t b) { return a < b ? a : b; }\nSLANG_CUDA_CALL int64_t I64_max(int64_t a, int64_t b) { return a > b ? a : b; }\n\n// ----------------------------- U64 -----------------------------------------\n\nSLANG_CUDA_CALL int64_t U64_abs(uint64_t f) { return f; }\n\nSLANG_CUDA_CALL int64_t U64_min(uint64_t a, uint64_t b) { return a < b ? a : b; }\nSLANG_CUDA_CALL int64_t U64_max(uint64_t a, uint64_t b) { return a > b ? a : b; }\n\nSLANG_CUDA_CALL uint32_t U64_countbits(uint64_t v)\n{\n    // https://docs.nvidia.com/cuda/cuda-math-api/group__CUDA__MATH__INTRINSIC__INT.html#group__CUDA__MATH__INTRINSIC__INT_1g43c9c7d2b9ebf202ff1ef5769989be46\n    return __popcll(v);\n}\n\n\n// ----------------------------- ResourceType -----------------------------------------\n\n\n// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions\n// Missing  Load(_In_  int  Location, _Out_ uint Status);\n\ntemplate <typename T>\nstruct StructuredBuffer\n{\n    SLANG_CUDA_CALL const T& operator[](size_t index) const\n    {\n#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT\n        SLANG_BOUND_CHECK(index, count);\n#endif\n        return data[index];\n    }\n\n    SLANG_CUDA_CALL const T& Load(size_t index) const\n    {\n#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT\n        SLANG_BOUND_CHECK(index, count);\n#endif\n        return data[index];\n    }\n\n#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT\n    SLANG_CUDA_CALL void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) { *outNumStructs = uint32_t(count); *outStride = uint32_t(sizeof(T)); }\n#endif\n\n    T* data;\n#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT\n    size_t count;\n#endif\n};\n\ntemplate <typename T>\nstruct RWStructuredBuffer : StructuredBuffer<T>\n{\n    SLANG_CUDA_CALL T& operator[](size_t index) const\n    {\n#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT\n        SLANG_BOUND_CHECK(index, this->count);\n#endif\n        return this->data[index];\n    }\n};\n\n// Missing  Load(_In_  int  Location, _Out_ uint Status);\nstruct ByteAddressBuffer\n{\n    SLANG_CUDA_CALL void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); }\n    SLANG_CUDA_CALL uint32_t Load(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);\n        return data[index >> 2]; \n    }\n    SLANG_CUDA_CALL uint2 Load2(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); \n        const size_t dataIdx = index >> 2; \n        return uint2{data[dataIdx], data[dataIdx + 1]}; \n    }\n    SLANG_CUDA_CALL uint3 Load3(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; \n    }\n    SLANG_CUDA_CALL uint4 Load4(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; \n    }\n    template<typename T>\n    SLANG_CUDA_CALL T Load(size_t index) const\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        return *(const T*)(((const char*)data) + index);\n    }\n    \n    const uint32_t* data;\n    size_t sizeInBytes;  //< Must be multiple of 4\n};\n\n// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer\n// Missing support for Atomic operations \n// Missing support for Load with status\nstruct RWByteAddressBuffer\n{\n    SLANG_CUDA_CALL void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); }\n    \n    SLANG_CUDA_CALL uint32_t Load(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);\n        return data[index >> 2]; \n    }\n    SLANG_CUDA_CALL uint2 Load2(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint2{data[dataIdx], data[dataIdx + 1]}; \n    }\n    SLANG_CUDA_CALL uint3 Load3(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; \n    }\n    SLANG_CUDA_CALL uint4 Load4(size_t index) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; \n    }\n    template<typename T>\n    SLANG_CUDA_CALL T Load(size_t index) const\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        return *(const T*)((const char*)data + index);\n    }\n    \n    SLANG_CUDA_CALL void Store(size_t index, uint32_t v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);\n        data[index >> 2] = v; \n    }\n    SLANG_CUDA_CALL void Store2(size_t index, uint2 v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        data[dataIdx + 0] = v.x;\n        data[dataIdx + 1] = v.y;\n    }\n    SLANG_CUDA_CALL void Store3(size_t index, uint3 v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        data[dataIdx + 0] = v.x;\n        data[dataIdx + 1] = v.y;\n        data[dataIdx + 2] = v.z;\n    }\n    SLANG_CUDA_CALL void Store4(size_t index, uint4 v) const \n    { \n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);\n        const size_t dataIdx = index >> 2; \n        data[dataIdx + 0] = v.x;\n        data[dataIdx + 1] = v.y;\n        data[dataIdx + 2] = v.z;\n        data[dataIdx + 3] = v.w;\n    }\n    template<typename T>\n    SLANG_CUDA_CALL void Store(size_t index, T const& value) const\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        *(T*)(((char*)data) + index) = value;\n    }\n    \n        /// Can be used in stdlib to gain access\n    template <typename T>\n    SLANG_CUDA_CALL T* _getPtrAt(size_t index)\n    {\n        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);\n        return (T*)(((char*)data) + index);\n    }\n    \n    uint32_t* data;\n    size_t sizeInBytes; //< Must be multiple of 4 \n};\n\n\n// ---------------------- Wave --------------------------------------\n\n// TODO(JS): It appears that cuda does not have a simple way to get a lane index. \n// \n// Another approach could be... \n// laneId = ((threadIdx.z * blockDim.y + threadIdx.y) * blockDim.x + threadIdx.x) & SLANG_CUDA_WARP_MASK\n// If that is really true another way to do this, would be for code generator to add this function \n// with the [numthreads] baked in. \n// \n// For now I'll just assume you have a launch that makes the following correct if the kernel uses WaveGetLaneIndex()\n#ifndef SLANG_USE_ASM_LANE_ID\n __forceinline__ __device__ uint32_t _getLaneId()\n{\n    // If the launch is (or I guess some multiple of the warp size) \n    // we try this mechanism, which is apparently faster. \n    return threadIdx.x & SLANG_CUDA_WARP_MASK;\n}\n#else\n__forceinline__ __device__ uint32_t _getLaneId()\n{\n    // https://stackoverflow.com/questions/44337309/whats-the-most-efficient-way-to-calculate-the-warp-id-lane-id-in-a-1-d-grid#\n    // This mechanism is not the fastest way to do it, and that is why the other mechanism \n    // is the default. But the other mechanism relies on a launch that makes the assumption \n    // true.\n    unsigned ret; \n    asm volatile (\"mov.u32 %0, %laneid;\" : \"=r\"(ret));\n    return ret;\n}\n#endif\n\ntypedef int WarpMask;\n\n// It appears that the __activemask() cannot always be used because \n// threads need to be converged. \n// \n// For CUDA the article claims mask has to be used carefully\n// https://devblogs.nvidia.com/using-cuda-warp-level-primitives/\n// With the Warp intrinsics there is no mask, and it's just the 'active lanes'. \n// __activemask() though does not require there is convergence, so that doesn't work.\n// \n// '__ballot_sync' produces a convergance. \n// \n// From the CUDA docs:\n// ```For __all_sync, __any_sync, and __ballot_sync, a mask must be passed that specifies the threads \n// participating in the call. A bit, representing the thread's lane ID, must be set for each participating thread \n// to ensure they are properly converged before the intrinsic is executed by the hardware. All active threads named \n// in mask must execute the same intrinsic with the same mask, or the result is undefined.```\n//\n// Currently there isn't a mechanism to correctly get the mask without it being passed through.\n// Doing so will most likely require some changes to slang code generation to track masks, for now then we use\n// _getActiveMask. \n\n// Return mask of all the lanes less than the current lane\n__forceinline__ __device__ WarpMask _getLaneLtMask()\n{\n    return (int(1) << _getLaneId()) - 1;\n}    \n\n// TODO(JS): \n// THIS IS NOT CORRECT! That determining the appropriate active mask requires appropriate\n// mask tracking.\n__forceinline__ __device__ WarpMask _getActiveMask()\n{\n    return __ballot_sync(__activemask(), true);\n}\n\n// Return a mask suitable for the 'MultiPrefix' style functions\n__forceinline__ __device__ WarpMask _getMultiPrefixMask(int mask)\n{\n    return mask;\n}\n\n// Note! Note will return true if mask is 0, but thats okay, because there must be one\n// lane active to execute anything\n__inline__ __device__ bool _waveIsSingleLane(WarpMask mask)\n{\n    return (mask & (mask - 1)) == 0;\n}\n\n// Returns the power of 2 size of run of set bits. Returns 0 if not a suitable run.\n__inline__ __device__ int _waveCalcPow2Offset(WarpMask mask)\n{\n    // This should be the most common case, so fast path it\n    if (mask == SLANG_CUDA_WARP_MASK)\n    {\n        return SLANG_CUDA_WARP_SIZE;\n    }\n    // Is it a contiguous run of bits?\n    if ((mask & (mask + 1)) == 0)\n    {\n        // const int offsetSize = __ffs(mask + 1) - 1;\n        const int offset = 32 - __clz(mask);\n        // Is it a power of 2 size\n        if ((offset & (offset - 1)) == 0)\n        {\n            return offset;\n        }\n    }\n    return 0;\n}\n\n__inline__ __device__ bool _waveIsFirstLane()\n{\n    const WarpMask mask = __activemask();\n    // We special case bit 0, as that most warps are expected to be fully active. \n    \n    // mask & -mask, isolates the lowest set bit.\n    //return (mask & 1 ) || ((mask & -mask) == (1 << _getLaneId()));\n    \n    // This mechanism is most similar to what was in an nVidia post, so assume it is prefered. \n    return (mask & 1 ) || ((__ffs(mask) - 1) == _getLaneId());\n}\n\ntemplate <typename T>\nstruct WaveOpOr\n{\n    __inline__ __device__ static T getInitial(T a) { return 0; }\n    __inline__ __device__ static T doOp(T a, T b) { return a | b; }\n};\n\ntemplate <typename T>\nstruct WaveOpAnd\n{\n    __inline__ __device__ static T getInitial(T a) { return ~T(0); }\n    __inline__ __device__ static T doOp(T a, T b) { return a & b; }\n};\n\ntemplate <typename T>\nstruct WaveOpXor\n{\n    __inline__ __device__ static T getInitial(T a) { return 0; }\n    __inline__ __device__ static T doOp(T a, T b) { return a ^ b; }\n    __inline__ __device__ static T doInverse(T a, T b) { return a ^ b; }\n};\n\ntemplate <typename T>\nstruct WaveOpAdd\n{\n    __inline__ __device__ static T getInitial(T a) { return 0; }\n    __inline__ __device__ static T doOp(T a, T b) { return a + b; }\n    __inline__ __device__ static T doInverse(T a, T b) { return a - b; }\n};\n\ntemplate <typename T>\nstruct WaveOpMul\n{\n    __inline__ __device__ static T getInitial(T a) { return T(1); }\n    __inline__ __device__ static T doOp(T a, T b) { return a * b; }\n    // Using this inverse for int is probably undesirable - because in general it requires T to have more precision\n    // There is also a performance aspect to it, where divides are generally significantly slower\n    __inline__ __device__ static T doInverse(T a, T b) { return a / b; }\n};\n\ntemplate <typename T>\nstruct WaveOpMax\n{\n    __inline__ __device__ static T getInitial(T a) { return a; }\n    __inline__ __device__ static T doOp(T a, T b) { return a > b ? a : b; }\n};\n\ntemplate <typename T>\nstruct WaveOpMin\n{\n    __inline__  __device__ static T getInitial(T a) { return a; }\n    __inline__ __device__ static T doOp(T a, T b) { return a < b ? a : b; }\n};\n\ntemplate <typename T>\nstruct ElementTypeTrait;\n\n// Scalar\ntemplate <> struct ElementTypeTrait<int> { typedef int Type; };\ntemplate <> struct ElementTypeTrait<uint> { typedef uint Type; };\ntemplate <> struct ElementTypeTrait<float> { typedef float Type; };\ntemplate <> struct ElementTypeTrait<double> { typedef double Type; };\ntemplate <> struct ElementTypeTrait<uint64_t> { typedef uint64_t Type; };\ntemplate <> struct ElementTypeTrait<int64_t> { typedef int64_t Type; };\n\n// Vector\ntemplate <> struct ElementTypeTrait<int1> { typedef int Type; };\ntemplate <> struct ElementTypeTrait<int2> { typedef int Type; };\ntemplate <> struct ElementTypeTrait<int3> { typedef int Type; };\ntemplate <> struct ElementTypeTrait<int4> { typedef int Type; };\n\ntemplate <> struct ElementTypeTrait<uint1> { typedef uint Type; };\ntemplate <> struct ElementTypeTrait<uint2> { typedef uint Type; };\ntemplate <> struct ElementTypeTrait<uint3> { typedef uint Type; };\ntemplate <> struct ElementTypeTrait<uint4> { typedef uint Type; };\n\ntemplate <> struct ElementTypeTrait<float1> { typedef float Type; };\ntemplate <> struct ElementTypeTrait<float2> { typedef float Type; };\ntemplate <> struct ElementTypeTrait<float3> { typedef float Type; };\ntemplate <> struct ElementTypeTrait<float4> { typedef float Type; };\n\ntemplate <> struct ElementTypeTrait<double1> { typedef double Type; };\ntemplate <> struct ElementTypeTrait<double2> { typedef double Type; };\ntemplate <> struct ElementTypeTrait<double3> { typedef double Type; };\ntemplate <> struct ElementTypeTrait<double4> { typedef double Type; };\n\n// Matrix\ntemplate <typename T, int ROWS, int COLS> \nstruct ElementTypeTrait<Matrix<T, ROWS, COLS> >  \n{ \n    typedef T Type; \n};\n\n// Scalar \ntemplate <typename INTF, typename T>\n__device__ T _waveReduceScalar(WarpMask mask, T val)\n{\n    const int offsetSize = _waveCalcPow2Offset(mask);\n    if (offsetSize > 0)\n    {\n        // Fast path O(log2(activeLanes)) \n        for (int offset = offsetSize >> 1; offset > 0; offset >>= 1)\n        {\n            val = INTF::doOp(val, __shfl_xor_sync(mask, val, offset));\n        }\n    }\n    else if (!_waveIsSingleLane(mask))\n    {\n        T result = INTF::getInitial(val);\n        int remaining = mask;\n        while (remaining)\n        {\n            const int laneBit = remaining & -remaining;\n            // Get the sourceLane \n            const int srcLane = __ffs(laneBit) - 1;\n            // Broadcast (can also broadcast to self) \n            result = INTF::doOp(result, __shfl_sync(mask, val, srcLane));\n            remaining &= ~laneBit;\n        }\n        return result;\n    }\n    return val;\n}\n\n\n// Multiple values\ntemplate <typename INTF, typename T, size_t COUNT>\n__device__ void _waveReduceMultiple(WarpMask mask, T* val)\n{\n    const int offsetSize = _waveCalcPow2Offset(mask);\n    if (offsetSize > 0)\n    {\n        // Fast path O(log2(activeLanes)) \n        for (int offset = offsetSize >> 1; offset > 0; offset >>= 1)\n        {\n            for (size_t i = 0; i < COUNT; ++i)\n            {\n                val[i] = INTF::doOp(val[i], __shfl_xor_sync(mask, val[i], offset));\n            }\n        }\n    }\n    else if (!_waveIsSingleLane(mask))\n    {\n        // Copy the original\n        T originalVal[COUNT];\n        for (size_t i = 0; i < COUNT; ++i)\n        {\n            const T v = val[i];\n            originalVal[i] = v;\n            val[i] = INTF::getInitial(v);\n        }\n        \n        int remaining = mask;\n        while (remaining)\n        {\n            const int laneBit = remaining & -remaining;\n            // Get the sourceLane \n            const int srcLane = __ffs(laneBit) - 1;\n            // Broadcast (can also broadcast to self) \n            for (size_t i = 0; i < COUNT; ++i)\n            {\n                val[i] = INTF::doOp(val[i], __shfl_sync(mask, originalVal[i], srcLane));\n            }\n            remaining &= ~laneBit;\n        }\n    }\n}\n\ntemplate <typename INTF, typename T>\n__device__ void _waveReduceMultiple(WarpMask mask, T* val)\n{\n    typedef typename ElementTypeTrait<T>::Type ElemType;    \n    _waveReduceMultiple<INTF, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)val);\n}\n\ntemplate <typename T>\n__inline__ __device__  T _waveOr(WarpMask mask, T val) { return _waveReduceScalar<WaveOpOr<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _waveAnd(WarpMask mask, T val) { return _waveReduceScalar<WaveOpAnd<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _waveXor(WarpMask mask, T val) { return _waveReduceScalar<WaveOpXor<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _waveProduct(WarpMask mask, T val) { return _waveReduceScalar<WaveOpMul<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _waveSum(WarpMask mask, T val) { return _waveReduceScalar<WaveOpAdd<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _waveMin(WarpMask mask, T val) { return _waveReduceScalar<WaveOpMin<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _waveMax(WarpMask mask, T val) { return _waveReduceScalar<WaveOpMax<T>, T>(mask, val); }\n\n\n// Multiple\n\ntemplate <typename T>\n__inline__ __device__  T _waveOrMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpOr<ElemType> >(mask, &val); return val; }\n\ntemplate <typename T>\n__inline__ __device__  T _waveAndMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpAnd<ElemType> >(mask, &val); return val; }\n\ntemplate <typename T>\n__inline__ __device__  T _waveXorMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpXor<ElemType> >(mask, &val); return val; }\n\ntemplate <typename T>\n__inline__ __device__  T _waveProductMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpMul<ElemType> >(mask, &val); return val; }\n\ntemplate <typename T>\n__inline__ __device__  T _waveSumMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpAdd<ElemType> >(mask, &val); return val; }\n\ntemplate <typename T>\n__inline__ __device__  T _waveMinMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpMin<ElemType> >(mask, &val); return val; }\n\ntemplate <typename T>\n__inline__ __device__  T _waveMaxMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait<T>::Type ElemType; _waveReduceMultiple<WaveOpMax<ElemType> >(mask, &val); return val; }\n\n\ntemplate <typename T>\n__inline__ __device__ bool _waveAllEqual(WarpMask mask, T val) \n{\n    int pred;\n    __match_all_sync(mask, val, &pred);\n    return pred != 0;\n}\n\ntemplate <typename T>\n__inline__ __device__ bool _waveAllEqualMultiple(WarpMask mask, T inVal) \n{\n    typedef typename ElementTypeTrait<T>::Type ElemType;\n    const size_t count = sizeof(T) / sizeof(ElemType);\n    int pred;\n    const ElemType* src = (const ElemType*)&inVal;\n    for (size_t i = 0; i < count; ++i)\n    {\n        __match_all_sync(mask, src[i], &pred);\n        if (pred == 0)\n        {\n            return false;\n        }\n    }\n    return true;\n}\n\ntemplate <typename T>\n__inline__ __device__ T _waveReadFirst(WarpMask mask, T val) \n{\n    const int lowestLaneId = __ffs(mask) - 1;\n    return __shfl_sync(mask, val, lowestLaneId);   \n}\n\ntemplate <typename T>\n__inline__ __device__ T _waveReadFirstMultiple(WarpMask mask, T inVal) \n{\n    typedef typename ElementTypeTrait<T>::Type ElemType;\n    const size_t count = sizeof(T) / sizeof(ElemType);\n    T outVal;\n    const ElemType* src = (const ElemType*)&inVal;\n    ElemType* dst = (ElemType*)&outVal;\n    const int lowestLaneId = __ffs(mask) - 1;\n    for (size_t i = 0; i < count; ++i)\n    {\n        dst[i] = __shfl_sync(mask, src[i], lowestLaneId);   \n    }\n    return outVal;\n}\n\ntemplate <typename T>\n__inline__ __device__ T _waveShuffleMultiple(WarpMask mask, T inVal, int lane)\n{\n    typedef typename ElementTypeTrait<T>::Type ElemType;\n    const size_t count = sizeof(T) / sizeof(ElemType);\n    T outVal;\n    const ElemType* src = (const ElemType*)&inVal;\n    ElemType* dst = (ElemType*)&outVal;\n    for (size_t i = 0; i < count; ++i)\n    {\n        dst[i] = __shfl_sync(mask, src[i], lane);   \n    }\n    return outVal;\n}\n\n// Scalar \n\n// Invertable means that when we get to the end of the reduce, we can remove val (to make exclusive), using \n// the inverse of the op.\ntemplate <typename INTF, typename T>\n__device__ T _wavePrefixInvertableScalar(WarpMask mask, T val)\n{\n    const int offsetSize = _waveCalcPow2Offset(mask);\n    \n    const int laneId = _getLaneId();\n    T result;\n    if (offsetSize > 0)\n    {    \n        // Sum is calculated inclusive of this lanes value\n        result = val;\n        for (int i = 1; i < offsetSize; i += i) \n        {\n            const T readVal = __shfl_up_sync(mask, result, i, offsetSize);\n            if (laneId >= i)\n            {\n                result = INTF::doOp(result, readVal);\n            }\n        }\n        // Remove val from the result, by applyin inverse\n        result = INTF::doInverse(result, val);\n    }\n    else \n    {\n        result = INTF::getInitial(val);\n        if (!_waveIsSingleLane(mask))\n        {\n            int remaining = mask;\n            while (remaining)\n            {\n                const int laneBit = remaining & -remaining;\n                // Get the sourceLane \n                const int srcLane = __ffs(laneBit) - 1;\n                // Broadcast (can also broadcast to self) \n                const T readValue = __shfl_sync(mask, val, srcLane);\n                // Only accumulate if srcLane is less than this lane\n                if (srcLane < laneId)\n                {\n                    result = INTF::doOp(result, readValue);\n                }\n                remaining &= ~laneBit;\n            }\n        }   \n    }\n    return result;\n}\n \n\n// This implementation separately tracks the value to be propogated, and the value\n// that is the final result \ntemplate <typename INTF, typename T>\n__device__ T _wavePrefixScalar(WarpMask mask, T val)\n{\n    const int offsetSize = _waveCalcPow2Offset(mask);\n    \n    const int laneId = _getLaneId();\n    T result = INTF::getInitial(val);           \n    if (offsetSize > 0)\n    {    \n        // For transmitted value we will do it inclusively with this lanes value\n        // For the result we do not include the lanes value. This means an extra multiply for each iteration\n        // but means we don't need to have a divide at the end and also removes overflow issues in that scenario.\n        for (int i = 1; i < offsetSize; i += i) \n        {\n            const T readVal = __shfl_up_sync(mask, val, i, offsetSize);\n            if (laneId >= i)\n            {\n                result = INTF::doOp(result, readVal);\n                val = INTF::doOp(val, readVal);\n            }\n        }\n    }\n    else \n    {\n        if (!_waveIsSingleLane(mask))\n        {\n            int remaining = mask;\n            while (remaining)\n            {\n                const int laneBit = remaining & -remaining;\n                // Get the sourceLane \n                const int srcLane = __ffs(laneBit) - 1;\n                // Broadcast (can also broadcast to self) \n                const T readValue = __shfl_sync(mask, val, srcLane);\n                // Only accumulate if srcLane is less than this lane\n                if (srcLane < laneId)\n                {\n                    result = INTF::doOp(result, readValue);\n                }\n                remaining &= ~laneBit;\n            }\n        }\n    }\n    return result;\n}\n\n\ntemplate <typename INTF, typename T, size_t COUNT>\n__device__ T _waveOpCopy(T* dst, const T* src)\n{\n    for (size_t j = 0; j < COUNT; ++j)\n    {\n        dst[j] = src[j];\n    }\n}    \n\n\ntemplate <typename INTF, typename T, size_t COUNT>\n__device__ T _waveOpDoInverse(T* inOut, const T* val)\n{\n    for (size_t j = 0; j < COUNT; ++j)\n    {\n        inOut[j] = INTF::doInverse(inOut[j], val[j]);\n    }\n}    \n\ntemplate <typename INTF, typename T, size_t COUNT>\n__device__ T _waveOpSetInitial(T* out, const T* val)\n{\n    for (size_t j = 0; j < COUNT; ++j)\n    {\n        out[j] = INTF::getInitial(val[j]);\n    }\n} \n\ntemplate <typename INTF, typename T, size_t COUNT>\n__device__ T _wavePrefixInvertableMultiple(WarpMask mask, T* val)\n{\n    const int offsetSize = _waveCalcPow2Offset(mask);\n    \n    const int laneId = _getLaneId();\n    T originalVal[COUNT];\n    _waveOpCopy<INTF, T, COUNT>(originalVal, val);\n    \n    if (offsetSize > 0)\n    {    \n        // Sum is calculated inclusive of this lanes value\n        for (int i = 1; i < offsetSize; i += i) \n        {\n            // TODO(JS): Note that here I don't split the laneId outside so it's only tested once.\n            // This may be better but it would also mean that there would be shfl between lanes \n            // that are on different (albeit identical) instructions. So this seems more likely to \n            // work as expected with everything in lock step.\n            for (size_t j = 0; j < COUNT; ++j)\n            {\n                const T readVal = __shfl_up_sync(mask, val[j], i, offsetSize);\n                if (laneId >= i)\n                {\n                    val[j] = INTF::doOp(val[j], readVal);\n                }\n            }\n        }\n        // Remove originalVal from the result, by applyin inverse\n        _waveOpDoInverse<INTF, T, COUNT>(val, originalVal);\n    }\n    else \n    {\n        _waveOpSetInitial<INTF, T, COUNT>(val, val);\n        if (!_waveIsSingleLane(mask))\n        {\n            int remaining = mask;\n            while (remaining)\n            {\n                const int laneBit = remaining & -remaining;\n                // Get the sourceLane \n                const int srcLane = __ffs(laneBit) - 1;\n                \n                for (size_t j = 0; j < COUNT; ++j)\n                {\n                    // Broadcast (can also broadcast to self) \n                    const T readValue = __shfl_sync(mask, originalVal[j], srcLane);\n                    // Only accumulate if srcLane is less than this lane\n                    if (srcLane < laneId)\n                    {\n                        val[j] = INTF::doOp(val[j], readValue);\n                    }\n                    remaining &= ~laneBit;\n                }\n            }\n        }   \n    }\n}\n \ntemplate <typename INTF, typename T, size_t COUNT>\n__device__ T _wavePrefixMultiple(WarpMask mask, T* val)\n{\n    const int offsetSize = _waveCalcPow2Offset(mask);\n    \n    const int laneId = _getLaneId();\n    \n    T work[COUNT];\n    _waveOpCopy<INTF, T, COUNT>(work, val);\n    _waveOpSetInitial<INTF, T, COUNT>(val, val);\n    \n    if (offsetSize > 0)\n    {    \n        // For transmitted value we will do it inclusively with this lanes value\n        // For the result we do not include the lanes value. This means an extra op for each iteration\n        // but means we don't need to have a divide at the end and also removes overflow issues in that scenario.\n        for (int i = 1; i < offsetSize; i += i) \n        {\n            for (size_t j = 0; j < COUNT; ++j)\n            {\n                const T readVal = __shfl_up_sync(mask, work[j], i, offsetSize);\n                if (laneId >= i)\n                {\n                    work[j] = INTF::doOp(work[j], readVal);\n                    val[j] = INTF::doOp(val[j], readVal);     \n                }\n            }\n        }\n    }\n    else \n    {\n        if (!_waveIsSingleLane(mask))\n        {\n            int remaining = mask;\n            while (remaining)\n            {\n                const int laneBit = remaining & -remaining;\n                // Get the sourceLane \n                const int srcLane = __ffs(laneBit) - 1;\n                \n                for (size_t j = 0; j < COUNT; ++j)\n                {\n                    // Broadcast (can also broadcast to self) \n                    const T readValue = __shfl_sync(mask, work[j], srcLane);\n                    // Only accumulate if srcLane is less than this lane\n                    if (srcLane < laneId)\n                    {\n                        val[j] = INTF::doOp(val[j], readValue);\n                    }\n                }\n                remaining &= ~laneBit;\n            }\n        }\n    }\n}\n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixProduct(WarpMask mask, T val) { return _wavePrefixScalar<WaveOpMul<T>, T>(mask, val); }\n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixSum(WarpMask mask, T val) { return _wavePrefixInvertableScalar<WaveOpAdd<T>, T>(mask, val); }    \n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixXor(WarpMask mask, T val) { return _wavePrefixInvertableScalar<WaveOpXor<T>, T>(mask, val); }    \n    \ntemplate <typename T>\n__inline__ __device__ T _wavePrefixOr(WarpMask mask, T val) { return _wavePrefixScalar<WaveOpOr<T>, T>(mask, val); }      \n    \ntemplate <typename T>\n__inline__ __device__ T _wavePrefixAnd(WarpMask mask, T val) { return _wavePrefixScalar<WaveOpAnd<T>, T>(mask, val); }      \n    \n    \ntemplate <typename T>\n__inline__ __device__ T _wavePrefixProductMultiple(WarpMask mask, T val)  \n{ \n    typedef typename ElementTypeTrait<T>::Type ElemType;    \n    _wavePrefixInvertableMultiple<WaveOpMul<ElemType>, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val);    \n    return val;\n}\n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixSumMultiple(WarpMask mask, T val) \n{ \n    typedef typename ElementTypeTrait<T>::Type ElemType;    \n    _wavePrefixInvertableMultiple<WaveOpAdd<ElemType>, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val);    \n    return val;\n}\n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixXorMultiple(WarpMask mask, T val)  \n{ \n    typedef typename ElementTypeTrait<T>::Type ElemType;    \n    _wavePrefixInvertableMultiple<WaveOpXor<ElemType>, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val);    \n    return val;\n}\n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixOrMultiple(WarpMask mask, T val) \n{ \n    typedef typename ElementTypeTrait<T>::Type ElemType;    \n    _wavePrefixMultiple<WaveOpOr<ElemType>, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val);    \n    return val;\n}\n\ntemplate <typename T>\n__inline__ __device__ T _wavePrefixAndMultiple(WarpMask mask, T val)  \n{ \n    typedef typename ElementTypeTrait<T>::Type ElemType;    \n    _wavePrefixMultiple<WaveOpAnd<ElemType>, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val);    \n    return val;\n}\n\ntemplate <typename T>\n__inline__ __device__ uint4 _waveMatchScalar(WarpMask mask, T val) \n{\n    int pred;\n    return make_uint4(__match_all_sync(mask, val, &pred), 0, 0, 0);\n}\n\ntemplate <typename T>\n__inline__ __device__ uint4 _waveMatchMultiple(WarpMask mask, const T& inVal) \n{\n    typedef typename ElementTypeTrait<T>::Type ElemType;\n    const size_t count = sizeof(T) / sizeof(ElemType);\n    int pred;\n    const ElemType* src = (const ElemType*)&inVal;\n    uint matchBits = 0xffffffff;\n    for (size_t i = 0; i < count && matchBits; ++i)\n    {\n        matchBits = matchBits & __match_all_sync(mask, src[i], &pred);\n    }\n    return make_uint4(matchBits, 0, 0, 0);\n}\n\n__device__ uint getAt(dim3 a,  int b)\n{\n    SLANG_PRELUDE_ASSERT(b >= 0 && b < 3);\n    return (&a.x)[b];\n}\n__device__ uint3 operator*(uint3 a, dim3 b)\n{\n    uint3 r;\n    r.x = a.x * b.x;\n    r.y = a.y * b.y;\n    r.z = a.z * b.z;\n    return r;\n}\n\ntemplate<typename TResult, typename TInput>\n__inline__ __device__ TResult slang_bit_cast(TInput val)\n{\n    return *(TResult*)(&val);\n}\n\n/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */\n\n\n/* Type that defines the uniform entry point params. The actual content of this type is dependent on the entry point parameters, and can be\nfound via reflection or defined such that it matches the shader appropriately.\n*/\nstruct UniformEntryPointParams;\nstruct UniformState;\n\n// ---------------------- OptiX Ray Payload --------------------------------------\n#ifdef SLANG_CUDA_ENABLE_OPTIX\nstruct RayDesc\n{\n    float3 Origin;\n    float  TMin;\n    float3 Direction;\n    float  TMax;\n};\n\nstatic __forceinline__ __device__\nvoid *unpackOptiXRayPayloadPointer(uint32_t i0, uint32_t i1)\n{\n    const uint64_t uptr = static_cast<uint64_t>(i0) << 32 | i1;\n    void*           ptr = reinterpret_cast<void*>(uptr);\n    return ptr;\n}\n\nstatic __forceinline__ __device__\nvoid  packOptiXRayPayloadPointer(void* ptr, uint32_t& i0, uint32_t& i1)\n{\n    const uint64_t uptr = reinterpret_cast<uint64_t>(ptr);\n    i0 = uptr >> 32;\n    i1 = uptr & 0x00000000ffffffff;\n}\n\nstatic __forceinline__ __device__ void *getOptiXRayPayloadPtr()\n{\n    const uint32_t u0 = optixGetPayload_0();\n    const uint32_t u1 = optixGetPayload_1();\n    return unpackOptiXRayPayloadPointer(u0, u1);\n}\n\ntemplate<typename T>\n__forceinline__ __device__ void *traceOptiXRay(\n    OptixTraversableHandle AccelerationStructure,\n    uint32_t RayFlags,\n    uint32_t InstanceInclusionMask,\n    uint32_t RayContributionToHitGroupIndex,\n    uint32_t MultiplierForGeometryContributionToHitGroupIndex,\n    uint32_t MissShaderIndex,\n    RayDesc Ray,\n    T *Payload\n) {\n    uint32_t r0, r1;\n    packOptiXRayPayloadPointer((void*)Payload, r0, r1);\n    optixTrace(\n        AccelerationStructure,\n        Ray.Origin,\n        Ray.Direction,\n        Ray.TMin,\n        Ray.TMax,\n        0.f, /* Time for motion blur, currently unsupported in slang */\n        InstanceInclusionMask,\n        RayFlags,\n        RayContributionToHitGroupIndex,\n        MultiplierForGeometryContributionToHitGroupIndex,\n        MissShaderIndex,\n        r0, r1\n    );\n}\n#endif\n"
  },
  {
    "path": "Source/External/slang/prelude/slang-hlsl-prelude.h",
    "content": "#ifdef SLANG_HLSL_ENABLE_NVAPI\n#include \"nvHLSLExtns.h\"\n#endif\n#pragma warning(disable: 3557)\n"
  },
  {
    "path": "Source/External/slang/prelude/slang-llvm.h",
    "content": "#ifndef SLANG_LLVM_H\n#define SLANG_LLVM_H\n\n// TODO(JS): \n// Disable exception declspecs, as not supported on LLVM without some extra options.\n// We could enable with `-fms-extensions`\n#define SLANG_DISABLE_EXCEPTIONS 1\n\n#ifndef SLANG_PRELUDE_ASSERT\n#   ifdef SLANG_PRELUDE_ENABLE_ASSERT\nextern \"C\" void assertFailure(const char* msg);\n#       define SLANG_PRELUDE_EXPECT(VALUE, MSG) if(VALUE) {} else assertFailure(\"assertion failed: '\" MSG \"'\")\n#       define SLANG_PRELUDE_ASSERT(VALUE) SLANG_PRELUDE_EXPECT(VALUE, #VALUE)\n#   else // SLANG_PRELUDE_ENABLE_ASSERT\n#       define SLANG_PRELUDE_EXPECT(VALUE, MSG)\n#       define SLANG_PRELUDE_ASSERT(x) \n#   endif // SLANG_PRELUDE_ENABLE_ASSERT\n#endif\n\n/*\nTaken from stddef.h \n*/\n\ntypedef __PTRDIFF_TYPE__ ptrdiff_t;\ntypedef __SIZE_TYPE__ size_t;\ntypedef __SIZE_TYPE__ rsize_t;\n\n//typedef __WCHAR_TYPE__ wchar_t;\n\n#if defined(__need_NULL)\n#undef NULL\n#ifdef __cplusplus\n#  if !defined(__MINGW32__) && !defined(_MSC_VER)\n#    define NULL __null\n#  else\n#    define NULL 0\n#  endif\n#else\n#  define NULL ((void*)0)\n#endif\n#ifdef __cplusplus\n#if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED)\nnamespace std { typedef decltype(nullptr) nullptr_t; }\nusing ::std::nullptr_t;\n#endif\n#endif\n#undef __need_NULL\n#endif /* defined(__need_NULL) */\n\n\n/*\nThe following are taken verbatim from stdint.h from Clang in LLVM. Only 8/16/32/64 types are needed. \n*/\n\n// LLVM/Clang types such that we can use LLVM/Clang without headers for C++ output from Slang\n\n#ifdef __INT64_TYPE__\n# ifndef __int8_t_defined /* glibc sys/types.h also defines int64_t*/\ntypedef __INT64_TYPE__ int64_t;\n# endif /* __int8_t_defined */\ntypedef __UINT64_TYPE__ uint64_t;\n# define __int_least64_t int64_t\n# define __uint_least64_t uint64_t\n#endif /* __INT64_TYPE__ */\n\n#ifdef __int_least64_t\ntypedef __int_least64_t int_least64_t;\ntypedef __uint_least64_t uint_least64_t;\ntypedef __int_least64_t int_fast64_t;\ntypedef __uint_least64_t uint_fast64_t;\n#endif /* __int_least64_t */\n\n#ifdef __INT32_TYPE__\n\n# ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/\ntypedef __INT32_TYPE__ int32_t;\n# endif /* __int8_t_defined */\n\n# ifndef __uint32_t_defined  /* more glibc compatibility */\n# define __uint32_t_defined\ntypedef __UINT32_TYPE__ uint32_t;\n# endif /* __uint32_t_defined */\n\n# define __int_least32_t int32_t\n# define __uint_least32_t uint32_t\n#endif /* __INT32_TYPE__ */\n\n#ifdef __int_least32_t\ntypedef __int_least32_t int_least32_t;\ntypedef __uint_least32_t uint_least32_t;\ntypedef __int_least32_t int_fast32_t;\ntypedef __uint_least32_t uint_fast32_t;\n#endif /* __int_least32_t */\n\n#ifdef __INT16_TYPE__\n#ifndef __int8_t_defined /* glibc sys/types.h also defines int16_t*/\ntypedef __INT16_TYPE__ int16_t;\n#endif /* __int8_t_defined */\ntypedef __UINT16_TYPE__ uint16_t;\n# define __int_least16_t int16_t\n# define __uint_least16_t uint16_t\n#endif /* __INT16_TYPE__ */\n\n#ifdef __int_least16_t\ntypedef __int_least16_t int_least16_t;\ntypedef __uint_least16_t uint_least16_t;\ntypedef __int_least16_t int_fast16_t;\ntypedef __uint_least16_t uint_fast16_t;\n#endif /* __int_least16_t */\n\n#ifdef __INT8_TYPE__\n#ifndef __int8_t_defined  /* glibc sys/types.h also defines int8_t*/\ntypedef __INT8_TYPE__ int8_t;\n#endif /* __int8_t_defined */\ntypedef __UINT8_TYPE__ uint8_t;\n# define __int_least8_t int8_t\n# define __uint_least8_t uint8_t\n#endif /* __INT8_TYPE__ */\n\n#ifdef __int_least8_t\ntypedef __int_least8_t int_least8_t;\ntypedef __uint_least8_t uint_least8_t;\ntypedef __int_least8_t int_fast8_t;\ntypedef __uint_least8_t uint_fast8_t;\n#endif /* __int_least8_t */\n\n/* prevent glibc sys/types.h from defining conflicting types */\n#ifndef __int8_t_defined\n# define __int8_t_defined\n#endif /* __int8_t_defined */\n\n/* C99 7.18.1.4 Integer types capable of holding object pointers.\n */\n#define __stdint_join3(a,b,c) a ## b ## c\n\n#ifndef _INTPTR_T\n#ifndef __intptr_t_defined\ntypedef __INTPTR_TYPE__ intptr_t;\n#define __intptr_t_defined\n#define _INTPTR_T\n#endif\n#endif\n\n#ifndef _UINTPTR_T\ntypedef __UINTPTR_TYPE__ uintptr_t;\n#define _UINTPTR_T\n#endif\n\n/* C99 7.18.1.5 Greatest-width integer types.\n */\ntypedef __INTMAX_TYPE__  intmax_t;\ntypedef __UINTMAX_TYPE__ uintmax_t;\n\n/* C99 7.18.4 Macros for minimum-width integer constants.\n *\n * The standard requires that integer constant macros be defined for all the\n * minimum-width types defined above. As 8-, 16-, 32-, and 64-bit minimum-width\n * types are required, the corresponding integer constant macros are defined\n * here. This implementation also defines minimum-width types for every other\n * integer width that the target implements, so corresponding macros are\n * defined below, too.\n *\n * These macros are defined using the same successive-shrinking approach as\n * the type definitions above. It is likewise important that macros are defined\n * in order of decending width.\n *\n * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the\n * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).\n */\n\n#define __int_c_join(a, b) a ## b\n#define __int_c(v, suffix) __int_c_join(v, suffix)\n#define __uint_c(v, suffix) __int_c_join(v##U, suffix)\n\n#ifdef __INT64_TYPE__\n# ifdef __INT64_C_SUFFIX__\n#  define __int64_c_suffix __INT64_C_SUFFIX__\n# else\n#  undef __int64_c_suffix\n# endif /* __INT64_C_SUFFIX__ */\n#endif /* __INT64_TYPE__ */\n\n#ifdef __int_least64_t\n# ifdef __int64_c_suffix\n#  define INT64_C(v) __int_c(v, __int64_c_suffix)\n#  define UINT64_C(v) __uint_c(v, __int64_c_suffix)\n# else\n#  define INT64_C(v) v\n#  define UINT64_C(v) v ## U\n# endif /* __int64_c_suffix */\n#endif /* __int_least64_t */\n\n\n#ifdef __INT32_TYPE__\n# ifdef __INT32_C_SUFFIX__\n#  define __int32_c_suffix __INT32_C_SUFFIX__\n#else\n#  undef __int32_c_suffix\n# endif /* __INT32_C_SUFFIX__ */\n#endif /* __INT32_TYPE__ */\n\n#ifdef __int_least32_t\n# ifdef __int32_c_suffix\n#  define INT32_C(v) __int_c(v, __int32_c_suffix)\n#  define UINT32_C(v) __uint_c(v, __int32_c_suffix)\n# else\n#  define INT32_C(v) v\n#  define UINT32_C(v) v ## U\n# endif /* __int32_c_suffix */\n#endif /* __int_least32_t */\n\n#ifdef __INT16_TYPE__\n# ifdef __INT16_C_SUFFIX__\n#  define __int16_c_suffix __INT16_C_SUFFIX__\n#else\n#  undef __int16_c_suffix\n# endif /* __INT16_C_SUFFIX__ */\n#endif /* __INT16_TYPE__ */\n\n#ifdef __int_least16_t\n# ifdef __int16_c_suffix\n#  define INT16_C(v) __int_c(v, __int16_c_suffix)\n#  define UINT16_C(v) __uint_c(v, __int16_c_suffix)\n# else\n#  define INT16_C(v) v\n#  define UINT16_C(v) v ## U\n# endif /* __int16_c_suffix */\n#endif /* __int_least16_t */\n\n\n#ifdef __INT8_TYPE__\n# ifdef __INT8_C_SUFFIX__\n#  define __int8_c_suffix __INT8_C_SUFFIX__\n#else\n#  undef  __int8_c_suffix\n# endif /* __INT8_C_SUFFIX__ */\n#endif /* __INT8_TYPE__ */\n\n#ifdef __int_least8_t\n# ifdef __int8_c_suffix\n#  define INT8_C(v) __int_c(v, __int8_c_suffix)\n#  define UINT8_C(v) __uint_c(v, __int8_c_suffix)\n# else\n#  define INT8_C(v) v\n#  define UINT8_C(v) v ## U\n# endif /* __int8_c_suffix */\n#endif /* __int_least8_t */\n\n/* C99 7.18.2.1 Limits of exact-width integer types.\n * C99 7.18.2.2 Limits of minimum-width integer types.\n * C99 7.18.2.3 Limits of fastest minimum-width integer types.\n *\n * The presence of limit macros are completely optional in C99.  This\n * implementation defines limits for all of the types (exact- and\n * minimum-width) that it defines above, using the limits of the minimum-width\n * type for any types that do not have exact-width representations.\n *\n * As in the type definitions, this section takes an approach of\n * successive-shrinking to determine which limits to use for the standard (8,\n * 16, 32, 64) bit widths when they don't have exact representations. It is\n * therefore important that the definitions be kept in order of decending\n * widths.\n *\n * Note that C++ should not check __STDC_LIMIT_MACROS here, contrary to the\n * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).\n */\n\n#ifdef __INT64_TYPE__\n# define INT64_MAX           INT64_C( 9223372036854775807)\n# define INT64_MIN         (-INT64_C( 9223372036854775807)-1)\n# define UINT64_MAX         UINT64_C(18446744073709551615)\n# define __INT_LEAST64_MIN   INT64_MIN\n# define __INT_LEAST64_MAX   INT64_MAX\n# define __UINT_LEAST64_MAX UINT64_MAX\n#endif /* __INT64_TYPE__ */\n\n#ifdef __INT_LEAST64_MIN\n# define INT_LEAST64_MIN   __INT_LEAST64_MIN\n# define INT_LEAST64_MAX   __INT_LEAST64_MAX\n# define UINT_LEAST64_MAX __UINT_LEAST64_MAX\n# define INT_FAST64_MIN    __INT_LEAST64_MIN\n# define INT_FAST64_MAX    __INT_LEAST64_MAX\n# define UINT_FAST64_MAX  __UINT_LEAST64_MAX\n#endif /* __INT_LEAST64_MIN */\n\n#ifdef __INT32_TYPE__\n# define INT32_MAX           INT32_C(2147483647)\n# define INT32_MIN         (-INT32_C(2147483647)-1)\n# define UINT32_MAX         UINT32_C(4294967295)\n# define __INT_LEAST32_MIN   INT32_MIN\n# define __INT_LEAST32_MAX   INT32_MAX\n# define __UINT_LEAST32_MAX UINT32_MAX\n#endif /* __INT32_TYPE__ */\n\n#ifdef __INT_LEAST32_MIN\n# define INT_LEAST32_MIN   __INT_LEAST32_MIN\n# define INT_LEAST32_MAX   __INT_LEAST32_MAX\n# define UINT_LEAST32_MAX __UINT_LEAST32_MAX\n# define INT_FAST32_MIN    __INT_LEAST32_MIN\n# define INT_FAST32_MAX    __INT_LEAST32_MAX\n# define UINT_FAST32_MAX  __UINT_LEAST32_MAX\n#endif /* __INT_LEAST32_MIN */\n\n#ifdef __INT16_TYPE__\n#define INT16_MAX            INT16_C(32767)\n#define INT16_MIN          (-INT16_C(32767)-1)\n#define UINT16_MAX          UINT16_C(65535)\n# define __INT_LEAST16_MIN   INT16_MIN\n# define __INT_LEAST16_MAX   INT16_MAX\n# define __UINT_LEAST16_MAX UINT16_MAX\n#endif /* __INT16_TYPE__ */\n\n#ifdef __INT_LEAST16_MIN\n# define INT_LEAST16_MIN   __INT_LEAST16_MIN\n# define INT_LEAST16_MAX   __INT_LEAST16_MAX\n# define UINT_LEAST16_MAX __UINT_LEAST16_MAX\n# define INT_FAST16_MIN    __INT_LEAST16_MIN\n# define INT_FAST16_MAX    __INT_LEAST16_MAX\n# define UINT_FAST16_MAX  __UINT_LEAST16_MAX\n#endif /* __INT_LEAST16_MIN */\n\n\n#ifdef __INT8_TYPE__\n# define INT8_MAX            INT8_C(127)\n# define INT8_MIN          (-INT8_C(127)-1)\n# define UINT8_MAX          UINT8_C(255)\n# define __INT_LEAST8_MIN    INT8_MIN\n# define __INT_LEAST8_MAX    INT8_MAX\n# define __UINT_LEAST8_MAX  UINT8_MAX\n#endif /* __INT8_TYPE__ */\n\n#ifdef __INT_LEAST8_MIN\n# define INT_LEAST8_MIN   __INT_LEAST8_MIN\n# define INT_LEAST8_MAX   __INT_LEAST8_MAX\n# define UINT_LEAST8_MAX __UINT_LEAST8_MAX\n# define INT_FAST8_MIN    __INT_LEAST8_MIN\n# define INT_FAST8_MAX    __INT_LEAST8_MAX\n# define UINT_FAST8_MAX  __UINT_LEAST8_MAX\n#endif /* __INT_LEAST8_MIN */\n\n/* Some utility macros */\n#define  __INTN_MIN(n)  __stdint_join3( INT, n, _MIN)\n#define  __INTN_MAX(n)  __stdint_join3( INT, n, _MAX)\n#define __UINTN_MAX(n)  __stdint_join3(UINT, n, _MAX)\n#define  __INTN_C(n, v) __stdint_join3( INT, n, _C(v))\n#define __UINTN_C(n, v) __stdint_join3(UINT, n, _C(v))\n\n/* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */\n/* C99 7.18.3 Limits of other integer types. */\n\n#define  INTPTR_MIN  (-__INTPTR_MAX__-1)\n#define  INTPTR_MAX    __INTPTR_MAX__\n#define UINTPTR_MAX   __UINTPTR_MAX__\n#define PTRDIFF_MIN (-__PTRDIFF_MAX__-1)\n#define PTRDIFF_MAX   __PTRDIFF_MAX__\n#define    SIZE_MAX      __SIZE_MAX__\n\n/* ISO9899:2011 7.20 (C11 Annex K): Define RSIZE_MAX if __STDC_WANT_LIB_EXT1__\n * is enabled. */\n#if defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1\n#define   RSIZE_MAX            (SIZE_MAX >> 1)\n#endif\n\n/* C99 7.18.2.5 Limits of greatest-width integer types. */\n#define  INTMAX_MIN (-__INTMAX_MAX__-1)\n#define  INTMAX_MAX   __INTMAX_MAX__\n#define UINTMAX_MAX  __UINTMAX_MAX__\n\n/* C99 7.18.3 Limits of other integer types. */\n#define SIG_ATOMIC_MIN __INTN_MIN(__SIG_ATOMIC_WIDTH__)\n#define SIG_ATOMIC_MAX __INTN_MAX(__SIG_ATOMIC_WIDTH__)\n#ifdef __WINT_UNSIGNED__\n# define WINT_MIN       __UINTN_C(__WINT_WIDTH__, 0)\n# define WINT_MAX       __UINTN_MAX(__WINT_WIDTH__)\n#else\n# define WINT_MIN       __INTN_MIN(__WINT_WIDTH__)\n# define WINT_MAX       __INTN_MAX(__WINT_WIDTH__)\n#endif\n\n#ifndef WCHAR_MAX\n# define WCHAR_MAX __WCHAR_MAX__\n#endif\n#ifndef WCHAR_MIN\n# if __WCHAR_MAX__ == __INTN_MAX(__WCHAR_WIDTH__)\n#  define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__)\n# else\n#  define WCHAR_MIN __UINTN_C(__WCHAR_WIDTH__, 0)\n# endif\n#endif\n\n/* 7.18.4.2 Macros for greatest-width integer constants. */\n#define  INTMAX_C(v) __int_c(v,  __INTMAX_C_SUFFIX__)\n#define UINTMAX_C(v) __int_c(v, __UINTMAX_C_SUFFIX__)\n\n\n#endif // SLANG_LLVM_H\n\n\n"
  },
  {
    "path": "Source/External/slang/slang-com-helper.h",
    "content": "#ifndef SLANG_COM_HELPER_H\n#define SLANG_COM_HELPER_H\n\n/** \\file slang-com-helper.h\n*/\n\n#include \"slang.h\"\n#include <atomic>\n\n/* !!!!!!!!!!!!!!!!!!!!! Macros to help checking SlangResult !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n/*! Set SLANG_HANDLE_RESULT_FAIL(x) to code to be executed whenever an error occurs, and is detected by one of the macros */\n#ifndef SLANG_HANDLE_RESULT_FAIL\n#\tdefine SLANG_HANDLE_RESULT_FAIL(x)\n#endif\n\n//! Helper macro, that makes it easy to add result checking to calls in functions/methods that themselves return Result. \n#define SLANG_RETURN_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return _res; } }\n//! Helper macro that can be used to test the return value from a call, and will return in a void method/function\n#define SLANG_RETURN_VOID_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return; } }\n//! Helper macro that will return false on failure.\n#define SLANG_RETURN_FALSE_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return false; } }\n//! Helper macro that will return nullptr on failure.\n#define SLANG_RETURN_NULL_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return nullptr; } }\n\n//! Helper macro that will assert if the return code from a call is failure, also returns the failure.\n#define SLANG_ASSERT_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { assert(false); return _res; } }\n//! Helper macro that will assert if the result from a call is a failure, also returns. \n#define SLANG_ASSERT_VOID_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { assert(false); return; } }\n\n/* !!!!!!!!!!!!!!!!!!!!!!! C++ helpers !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n#if defined(__cplusplus)\nnamespace Slang {\n\n// Alias SlangResult to Slang::Result\ntypedef SlangResult Result;\n// Alias SlangUUID to Slang::Guid\ntypedef SlangUUID Guid;\n\n} // namespace Slang\n\n// Operator == and != for Guid/SlangUUID\n\nSLANG_FORCE_INLINE bool operator==(const Slang::Guid& aIn, const Slang::Guid& bIn)\n{\n    using namespace Slang;\n    // Use the largest type the honors the alignment of Guid\n    typedef uint32_t CmpType;\n    union GuidCompare\n    {\n        Guid guid;\n        CmpType data[sizeof(Guid) / sizeof(CmpType)];\n    };\n    // Type pun - so compiler can 'see' the pun and not break aliasing rules\n    const CmpType* a = reinterpret_cast<const GuidCompare&>(aIn).data;\n    const CmpType* b = reinterpret_cast<const GuidCompare&>(bIn).data;\n    // Make the guid comparison a single branch, by not using short circuit\n    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0;\n}\n\nSLANG_FORCE_INLINE bool operator!=(const Slang::Guid& a, const Slang::Guid& b)\n{\n    return !(a == b);\n}\n\n/* !!!!!!!! Macros to simplify implementing COM interfaces !!!!!!!!!!!!!!!!!!!!!!!!!!!! */\n\n/* Assumes underlying implementation has a member m_refCount that is initialized to 0 and can have ++ and -- operate on it. \nFor SLANG_IUNKNOWN_QUERY_INTERFACE to work - must have a method 'getInterface' that returns valid pointers for the Guid, or nullptr \nif not found. */\n\n#define SLANG_IUNKNOWN_QUERY_INTERFACE \\\nSLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE \\\n{ \\\n    ISlangUnknown* intf = getInterface(uuid); \\\n    if (intf) \\\n    { \\\n        addRef(); \\\n        *outObject = intf; \\\n        return SLANG_OK;\\\n    } \\\n    return SLANG_E_NO_INTERFACE;\\\n}\n\n#define SLANG_IUNKNOWN_ADD_REF \\\nSLANG_NO_THROW uint32_t SLANG_MCALL addRef() \\\n{ \\\n    return ++m_refCount; \\\n}\n\n#define SLANG_IUNKNOWN_RELEASE \\\nSLANG_NO_THROW uint32_t SLANG_MCALL release() \\\n{ \\\n    --m_refCount; \\\n    if (m_refCount == 0) \\\n    { \\\n        delete this; \\\n        return 0; \\\n    } \\\n    return m_refCount; \\\n} \n\n#define SLANG_IUNKNOWN_ALL \\\n    SLANG_IUNKNOWN_QUERY_INTERFACE \\\n    SLANG_IUNKNOWN_ADD_REF \\\n    SLANG_IUNKNOWN_RELEASE \n\n// ------------------------ RefObject IUnknown -----------------------------\n\n#define SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \\\nSLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE \\\n{ \\\n    void* intf = getInterface(uuid); \\\n    if (intf) \\\n    { \\\n        addReference(); \\\n        *outObject = intf; \\\n        return SLANG_OK;\\\n    } \\\n    return SLANG_E_NO_INTERFACE;\\\n}\n\n#define SLANG_REF_OBJECT_IUNKNOWN_ADD_REF SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return (uint32_t)addReference(); }\n#define SLANG_REF_OBJECT_IUNKNOWN_RELEASE SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return (uint32_t)releaseReference(); }\n\n#    define SLANG_REF_OBJECT_IUNKNOWN_ALL         \\\n        SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \\\n        SLANG_REF_OBJECT_IUNKNOWN_ADD_REF         \\\n        SLANG_REF_OBJECT_IUNKNOWN_RELEASE\n\n#endif // defined(__cplusplus)\n\n#endif\n"
  },
  {
    "path": "Source/External/slang/slang-com-ptr.h",
    "content": "#ifndef SLANG_COM_PTR_H\n#define SLANG_COM_PTR_H\n\n#include \"slang-com-helper.h\"\n\n#include <assert.h>\n#include <cstddef>\n\nnamespace Slang {\n\n/*! \\brief ComPtr is a simple smart pointer that manages types which implement COM based interfaces.\n\\details A class that implements a COM, must derive from the IUnknown interface or a type that matches\nit's layout exactly (such as ISlangUnknown). Trying to use this template with a class that doesn't follow\nthese rules, will lead to undefined behavior.\nThis is a 'strong' pointer type, and will AddRef when a non null pointer is set and Release when the pointer\nleaves scope.\nUsing 'detach' allows a pointer to be removed from the management of the ComPtr.\nTo set the smart pointer to null, there is the method setNull, or alternatively just assign SLANG_NULL/nullptr.\n\nOne edge case using the template is that sometimes you want access as a pointer to a pointer. Sometimes this\nis to write into the smart pointer, other times to pass as an array. To handle these different behaviors\nthere are the methods readRef and writeRef, which are used instead of the & (ref) operator. For example\n\n\\code\nVoid doSomething(ID3D12Resource** resources, IndexT numResources);\n// ...\nComPtr<ID3D12Resource> resources[3];\ndoSomething(resources[0].readRef(), SLANG_COUNT_OF(resource));\n\\endcode\n\nA more common scenario writing to the pointer\n\n\\code\nIUnknown* unk = ...;\n\nComPtr<ID3D12Resource> resource;\nResult res = unk->QueryInterface(resource.writeRef());\n\\endcode\n*/\n\n// Enum to force initializing as an attach (without adding a reference)\nenum InitAttach\n{\n    INIT_ATTACH\n};\n\ntemplate <class T>\nclass ComPtr\n{\npublic:\n\ttypedef T Type;\n\ttypedef ComPtr ThisType;\n\ttypedef ISlangUnknown* Ptr;\n\n\t\t/// Constructors\n\t\t/// Default Ctor. Sets to nullptr\n\tSLANG_FORCE_INLINE ComPtr() :m_ptr(nullptr) {}\n    SLANG_FORCE_INLINE ComPtr(std::nullptr_t) : m_ptr(nullptr) {}\n\t\t/// Sets, and ref counts.\n\tSLANG_FORCE_INLINE explicit ComPtr(T* ptr) :m_ptr(ptr) { if (ptr) ((Ptr)ptr)->addRef(); }\n\t\t/// The copy ctor\n\tSLANG_FORCE_INLINE ComPtr(const ThisType& rhs) : m_ptr(rhs.m_ptr) { if (m_ptr) ((Ptr)m_ptr)->addRef(); }\n\n        /// Ctor without adding to ref count.\n    SLANG_FORCE_INLINE explicit ComPtr(InitAttach, T* ptr) :m_ptr(ptr) { }\n        /// Ctor without adding to ref count\n    SLANG_FORCE_INLINE ComPtr(InitAttach, const ThisType& rhs) : m_ptr(rhs.m_ptr) { }\n\n#ifdef SLANG_HAS_MOVE_SEMANTICS\n\t\t/// Move Ctor\n\tSLANG_FORCE_INLINE ComPtr(ThisType&& rhs) : m_ptr(rhs.m_ptr) { rhs.m_ptr = nullptr; }\n\t\t/// Move assign\n\tSLANG_FORCE_INLINE ComPtr& operator=(ThisType&& rhs) { T* swap = m_ptr; m_ptr = rhs.m_ptr; rhs.m_ptr = swap; return *this; }\n#endif\n\n\t/// Destructor releases the pointer, assuming it is set\n\tSLANG_FORCE_INLINE ~ComPtr() { if (m_ptr) ((Ptr)m_ptr)->release(); }\n\n\t// !!! Operators !!!\n\n\t  /// Returns the dumb pointer\n\tSLANG_FORCE_INLINE operator T *() const { return m_ptr; }\n\n\tSLANG_FORCE_INLINE T& operator*() { return *m_ptr; }\n\t\t/// For making method invocations through the smart pointer work through the dumb pointer\n\tSLANG_FORCE_INLINE T* operator->() const { return m_ptr; }\n\n\t\t/// Assign\n\tSLANG_FORCE_INLINE const ThisType &operator=(const ThisType& rhs);\n\t\t/// Assign from dumb ptr\n\tSLANG_FORCE_INLINE T* operator=(T* in);\n\n\t\t/// Get the pointer and don't ref\n\tSLANG_FORCE_INLINE T* get() const { return m_ptr; }\n\t\t/// Release a contained nullptr pointer if set\n\tSLANG_FORCE_INLINE void setNull();\n\n\t\t/// Detach\n\tSLANG_FORCE_INLINE T* detach() { T* ptr = m_ptr; m_ptr = nullptr; return ptr; }\n\t\t/// Set to a pointer without changing the ref count\n\tSLANG_FORCE_INLINE void attach(T* in) { m_ptr = in; }\n\n\t\t/// Get ready for writing (nulls contents)\n\tSLANG_FORCE_INLINE T** writeRef() { setNull(); return &m_ptr; }\n\t\t/// Get for read access\n\tSLANG_FORCE_INLINE T*const* readRef() const { return &m_ptr; }\n\n\t\t/// Swap\n\tvoid swap(ThisType& rhs);\n\nprotected:\n\t/// Gets the address of the dumb pointer.\n    // Disabled: use writeRef and readRef to get a reference based on usage.\n#ifndef SLANG_COM_PTR_ENABLE_REF_OPERATOR\n\tSLANG_FORCE_INLINE T** operator&() = delete;\n#endif\n\n\tT* m_ptr;\n};\n\n//----------------------------------------------------------------------------\ntemplate <typename T>\nvoid ComPtr<T>::setNull()\n{\n\tif (m_ptr)\n\t{\n\t\t((Ptr)m_ptr)->release();\n\t\tm_ptr = nullptr;\n\t}\n}\n//----------------------------------------------------------------------------\ntemplate <typename T>\nconst ComPtr<T>& ComPtr<T>::operator=(const ThisType& rhs)\n{\n\tif (rhs.m_ptr) ((Ptr)rhs.m_ptr)->addRef();\n\tif (m_ptr) ((Ptr)m_ptr)->release();\n\tm_ptr = rhs.m_ptr;\n\treturn *this;\n}\n//----------------------------------------------------------------------------\ntemplate <typename T>\nT* ComPtr<T>::operator=(T* ptr)\n{\n\tif (ptr) ((Ptr)ptr)->addRef();\n\tif (m_ptr) ((Ptr)m_ptr)->release();\n\tm_ptr = ptr;\n\treturn m_ptr;\n}\n//----------------------------------------------------------------------------\ntemplate <typename T>\nvoid ComPtr<T>::swap(ThisType& rhs)\n{\n\tT* tmp = m_ptr;\n\tm_ptr = rhs.m_ptr;\n\trhs.m_ptr = tmp;\n}\n\n} // namespace Slang\n\n#endif // SLANG_COM_PTR_H\n"
  },
  {
    "path": "Source/External/slang/slang-gfx.h",
    "content": "// render.h\n#pragma once\n\n#include <float.h>\n#include <assert.h>\n\n#include \"slang.h\"\n#include \"slang-com-ptr.h\"\n\n\n#if defined(SLANG_GFX_DYNAMIC)\n#    if defined(_MSC_VER)\n#        ifdef SLANG_GFX_DYNAMIC_EXPORT\n#            define SLANG_GFX_API SLANG_DLL_EXPORT\n#        else\n#            define SLANG_GFX_API __declspec(dllimport)\n#        endif\n#    else\n// TODO: need to consider compiler capabilities\n//#     ifdef SLANG_DYNAMIC_EXPORT\n#        define SLANG_GFX_API SLANG_DLL_EXPORT\n//#     endif\n#    endif\n#endif\n\n#ifndef SLANG_GFX_API\n#    define SLANG_GFX_API\n#endif\n\n// Needed for building on cygwin with gcc\n#undef Always\n#undef None\n\n// GLOBAL TODO: doc comments\n// GLOBAL TODO: Rationalize integer types (not a smush of uint/int/Uint/Int/etc)\n//    - need typedefs in gfx namespace for Count, Index, Size, Offset (ex. DeviceAddress)\n//    - Index and Count are for arrays, and indexing into array - like things(XY coordinates of pixels, etc.)\n//         - Count is also for anything where we need to measure how many of something there are. This includes things like extents.\n//    - Offset and Size are almost always for bytes and things measured in bytes.\nnamespace gfx {\n\nusing Slang::ComPtr;\n\ntypedef SlangResult Result;\n\n// Had to move here, because Options needs types defined here\ntypedef SlangInt Int;\ntypedef SlangUInt UInt;\ntypedef uint64_t DeviceAddress;\ntypedef int GfxIndex;\ntypedef int GfxCount;\ntypedef size_t Size;\ntypedef size_t Offset;\n\nconst uint64_t kTimeoutInfinite = 0xFFFFFFFFFFFFFFFF;\n\nenum class StructType\n{\n    D3D12DeviceExtendedDesc, D3D12ExperimentalFeaturesDesc\n};\n\n// TODO: Rename to Stage\nenum class StageType\n{\n    Unknown,\n    Vertex,\n    Hull,\n    Domain,\n    Geometry,\n    Fragment,\n    Compute,\n    RayGeneration,\n    Intersection,\n    AnyHit,\n    ClosestHit,\n    Miss,\n    Callable,\n    Amplification,\n    Mesh,\n    CountOf,\n};\n\n// TODO: Implementation or backend or something else?\nenum class DeviceType\n{\n    Unknown,\n    Default,\n    DirectX11,\n    DirectX12,\n    OpenGl,\n    Vulkan,\n    CPU,\n    CUDA,\n    CountOf,\n};\n\n// TODO: Why does this exist it should go poof\nenum class ProjectionStyle\n{\n    Unknown,\n    OpenGl,\n    DirectX,\n    Vulkan,\n    CountOf,\n};\n\n// TODO: This should also go poof\n/// The style of the binding\nenum class BindingStyle\n{\n    Unknown,\n    DirectX,\n    OpenGl,\n    Vulkan,\n    CPU,\n    CUDA,\n    CountOf,\n};\n\n// TODO: Is this actually a flag when there are no bit fields?\nenum class AccessFlag\n{\n    None,\n    Read,\n    Write,\n};\n\n// TODO: Needed? Shouldn't be hard-coded if so\nconst GfxCount kMaxRenderTargetCount = 8;\n\nclass ITransientResourceHeap;\n\nenum class ShaderModuleSourceType\n{\n    SlangSource, // a slang source string in memory.\n    SlangModuleBinary, // a slang module binary code in memory.\n    SlangSourceFile, // a slang source from file.\n    SlangModuleBinaryFile, // a slang module binary code from file.\n};\n\nclass IShaderProgram: public ISlangUnknown\n{\npublic:\n    // Defines how linking should be performed for a shader program.\n    enum class LinkingStyle\n    {\n        // Compose all entry-points in a single program, then compile all entry-points together with the same\n        // set of root shader arguments.\n        SingleProgram,\n\n        // Link and compile each entry-point individually, potentially with different specializations.\n        SeparateEntryPointCompilation\n    };\n\n    struct Desc\n    {\n        // TODO: Tess doesn't like this but doesn't know what to do about it\n        // The linking style of this program.\n        LinkingStyle linkingStyle = LinkingStyle::SingleProgram;\n\n        // The global scope or a Slang composite component that represents the entire program.\n        slang::IComponentType*  slangGlobalScope;\n\n        // Number of separate entry point components in the `slangEntryPoints` array to link in.\n        // If set to 0, then `slangGlobalScope` must contain Slang EntryPoint components.\n        // If not 0, then `slangGlobalScope` must not contain any EntryPoint components.\n        GfxCount entryPointCount = 0;\n\n        // An array of Slang entry points. The size of the array must be `entryPointCount`.\n        // Each element must define only 1 Slang EntryPoint.\n        slang::IComponentType** slangEntryPoints = nullptr;\n    };\n\n    struct CreateDesc2\n    {\n        ShaderModuleSourceType sourceType;\n        void* sourceData;\n        Size sourceDataSize;\n\n        // Number of entry points to include in the shader program. 0 means include all entry points\n        // defined in the module.\n        GfxCount entryPointCount = 0;\n        // Names of entry points to include in the shader program. The size of the array must be\n        // `entryPointCount`.\n        const char** entryPointNames = nullptr;\n    };\n\n    virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL findTypeByName(const char* name) = 0;\n};\n#define SLANG_UUID_IShaderProgram                                                       \\\n    {                                                                                  \\\n        0x9d32d0ad, 0x915c, 0x4ffd, { 0x91, 0xe2, 0x50, 0x85, 0x54, 0xa0, 0x4a, 0x76 } \\\n    }\n\n// TODO: Confirm with Yong that we really want this naming convention\n// TODO: Rename to what?\n// Dont' change without keeping in sync with Format\n#define GFX_FORMAT(x) \\\n    x( Unknown, 0, 0) \\\n    \\\n    x(R32G32B32A32_TYPELESS, 16, 1) \\\n    x(R32G32B32_TYPELESS, 12, 1) \\\n    x(R32G32_TYPELESS, 8, 1) \\\n    x(R32_TYPELESS, 4, 1) \\\n    \\\n    x(R16G16B16A16_TYPELESS, 8, 1) \\\n    x(R16G16_TYPELESS, 4, 1) \\\n    x(R16_TYPELESS, 2, 1) \\\n    \\\n    x(R8G8B8A8_TYPELESS, 4, 1) \\\n    x(R8G8_TYPELESS, 2, 1) \\\n    x(R8_TYPELESS, 1, 1) \\\n    x(B8G8R8A8_TYPELESS, 4, 1) \\\n    \\\n    x(R32G32B32A32_FLOAT, 16, 1) \\\n    x(R32G32B32_FLOAT, 12, 1) \\\n    x(R32G32_FLOAT, 8, 1) \\\n    x(R32_FLOAT, 4, 1) \\\n    \\\n    x(R16G16B16A16_FLOAT, 8, 1) \\\n    x(R16G16_FLOAT, 4, 1) \\\n    x(R16_FLOAT, 2, 1) \\\n    \\\n    x(R32G32B32A32_UINT, 16, 1) \\\n    x(R32G32B32_UINT, 12, 1) \\\n    x(R32G32_UINT, 8, 1) \\\n    x(R32_UINT, 4, 1) \\\n    \\\n    x(R16G16B16A16_UINT, 8, 1) \\\n    x(R16G16_UINT, 4, 1) \\\n    x(R16_UINT, 2, 1) \\\n    \\\n    x(R8G8B8A8_UINT, 4, 1) \\\n    x(R8G8_UINT, 2, 1) \\\n    x(R8_UINT, 1, 1) \\\n    \\\n    x(R32G32B32A32_SINT, 16, 1) \\\n    x(R32G32B32_SINT, 12, 1) \\\n    x(R32G32_SINT, 8, 1) \\\n    x(R32_SINT, 4, 1) \\\n    \\\n    x(R16G16B16A16_SINT, 8, 1) \\\n    x(R16G16_SINT, 4, 1) \\\n    x(R16_SINT, 2, 1) \\\n    \\\n    x(R8G8B8A8_SINT, 4, 1) \\\n    x(R8G8_SINT, 2, 1) \\\n    x(R8_SINT, 1, 1) \\\n    \\\n    x(R16G16B16A16_UNORM, 8, 1) \\\n    x(R16G16_UNORM, 4, 1) \\\n    x(R16_UNORM, 2, 1) \\\n    \\\n    x(R8G8B8A8_UNORM, 4, 1) \\\n    x(R8G8B8A8_UNORM_SRGB, 4, 1) \\\n    x(R8G8_UNORM, 2, 1) \\\n    x(R8_UNORM, 1, 1) \\\n    x(B8G8R8A8_UNORM, 4, 1) \\\n    x(B8G8R8A8_UNORM_SRGB, 4, 1) \\\n    x(B8G8R8X8_UNORM, 4, 1) \\\n    x(B8G8R8X8_UNORM_SRGB, 4, 1) \\\n    \\\n    x(R16G16B16A16_SNORM, 8, 1) \\\n    x(R16G16_SNORM, 4, 1) \\\n    x(R16_SNORM, 2, 1) \\\n    \\\n    x(R8G8B8A8_SNORM, 4, 1) \\\n    x(R8G8_SNORM, 2, 1) \\\n    x(R8_SNORM, 1, 1) \\\n    \\\n    x(D32_FLOAT, 4, 1) \\\n    x(D16_UNORM, 2, 1) \\\n    \\\n    x(B4G4R4A4_UNORM, 2, 1) \\\n    x(B5G6R5_UNORM, 2, 1) \\\n    x(B5G5R5A1_UNORM, 2, 1) \\\n    \\\n    x(R9G9B9E5_SHAREDEXP, 4, 1) \\\n    x(R10G10B10A2_TYPELESS, 4, 1) \\\n    x(R10G10B10A2_UNORM, 4, 1) \\\n    x(R10G10B10A2_UINT, 4, 1) \\\n    x(R11G11B10_FLOAT, 4, 1) \\\n    \\\n    x(BC1_UNORM, 8, 16) \\\n    x(BC1_UNORM_SRGB, 8, 16) \\\n    x(BC2_UNORM, 16, 16) \\\n    x(BC2_UNORM_SRGB, 16, 16) \\\n    x(BC3_UNORM, 16, 16) \\\n    x(BC3_UNORM_SRGB, 16, 16) \\\n    x(BC4_UNORM, 8, 16) \\\n    x(BC4_SNORM, 8, 16) \\\n    x(BC5_UNORM, 16, 16) \\\n    x(BC5_SNORM, 16, 16) \\\n    x(BC6H_UF16, 16, 16) \\\n    x(BC6H_SF16, 16, 16) \\\n    x(BC7_UNORM, 16, 16) \\\n    x(BC7_UNORM_SRGB, 16, 16)\n\n// TODO: This should be generated from above\n// TODO: enum class should be explicitly uint32_t or whatever's appropriate\n/// Different formats of things like pixels or elements of vertices\n/// NOTE! Any change to this type (adding, removing, changing order) - must also be reflected in changes GFX_FORMAT\nenum class Format\n{\n    // D3D formats omitted: 19-22, 44-47, 65-66, 68-70, 73, 76, 79, 82, 88-89, 92-94, 97, 100-114\n    // These formats are omitted due to lack of a corresponding Vulkan format. D24_UNORM_S8_UINT (DXGI_FORMAT 45)\n    // has a matching Vulkan format but is also omitted as it is only supported by Nvidia.\n    Unknown,\n\n    R32G32B32A32_TYPELESS,\n    R32G32B32_TYPELESS,\n    R32G32_TYPELESS,\n    R32_TYPELESS,\n\n    R16G16B16A16_TYPELESS,\n    R16G16_TYPELESS,\n    R16_TYPELESS,\n\n    R8G8B8A8_TYPELESS,\n    R8G8_TYPELESS,\n    R8_TYPELESS,\n    B8G8R8A8_TYPELESS,\n\n    R32G32B32A32_FLOAT,\n    R32G32B32_FLOAT,\n    R32G32_FLOAT,\n    R32_FLOAT,\n\n    R16G16B16A16_FLOAT,\n    R16G16_FLOAT,\n    R16_FLOAT,\n\n    R32G32B32A32_UINT,\n    R32G32B32_UINT,\n    R32G32_UINT,\n    R32_UINT,\n\n    R16G16B16A16_UINT,\n    R16G16_UINT,\n    R16_UINT,\n\n    R8G8B8A8_UINT,\n    R8G8_UINT,\n    R8_UINT,\n\n    R32G32B32A32_SINT,\n    R32G32B32_SINT,\n    R32G32_SINT,\n    R32_SINT,\n\n    R16G16B16A16_SINT,\n    R16G16_SINT,\n    R16_SINT,\n\n    R8G8B8A8_SINT,\n    R8G8_SINT,\n    R8_SINT,\n\n    R16G16B16A16_UNORM,\n    R16G16_UNORM,\n    R16_UNORM,\n\n    R8G8B8A8_UNORM,\n    R8G8B8A8_UNORM_SRGB,\n    R8G8_UNORM,\n    R8_UNORM,\n    B8G8R8A8_UNORM,\n    B8G8R8A8_UNORM_SRGB,\n    B8G8R8X8_UNORM,\n    B8G8R8X8_UNORM_SRGB,\n\n    R16G16B16A16_SNORM,\n    R16G16_SNORM,\n    R16_SNORM,\n\n    R8G8B8A8_SNORM,\n    R8G8_SNORM,\n    R8_SNORM,\n\n    D32_FLOAT,\n    D16_UNORM,\n\n    B4G4R4A4_UNORM,\n    B5G6R5_UNORM,\n    B5G5R5A1_UNORM,\n\n    R9G9B9E5_SHAREDEXP,\n    R10G10B10A2_TYPELESS,\n    R10G10B10A2_UNORM,\n    R10G10B10A2_UINT,\n    R11G11B10_FLOAT,\n\n    BC1_UNORM,\n    BC1_UNORM_SRGB,\n    BC2_UNORM,\n    BC2_UNORM_SRGB,\n    BC3_UNORM,\n    BC3_UNORM_SRGB,\n    BC4_UNORM,\n    BC4_SNORM,\n    BC5_UNORM,\n    BC5_SNORM,\n    BC6H_UF16,\n    BC6H_SF16,\n    BC7_UNORM,\n    BC7_UNORM_SRGB,\n\n    _Count,\n};\n\n// TODO: Aspect = Color, Depth, Stencil, etc.\n// TODO: Channel = R, G, B, A, D, S, etc.\n// TODO: Pick : pixel or texel\n// TODO: Block is a good term for what it is\n// TODO: Width/Height/Depth/whatever should not be used. We should use extentX, extentY, etc.\nstruct FormatInfo\n{\n    GfxCount channelCount;         ///< The amount of channels in the format. Only set if the channelType is set\n    uint8_t channelType;           ///< One of SlangScalarType None if type isn't made up of elements of type. TODO: Change to uint32_t?\n\n    Size blockSizeInBytes;         ///< The size of a block in bytes.\n    GfxCount pixelsPerBlock;       ///< The number of pixels contained in a block.\n    GfxCount blockWidth;           ///< The width of a block in pixels.\n    GfxCount blockHeight;          ///< The height of a block in pixels.\n};\n\nenum class InputSlotClass\n{\n    PerVertex, PerInstance\n};\n\nstruct InputElementDesc\n{\n    char const* semanticName;      ///< The name of the corresponding parameter in shader code.\n    GfxIndex semanticIndex;        ///< The index of the corresponding parameter in shader code. Only needed if multiple parameters share a semantic name.\n    Format format;                 ///< The format of the data being fetched for this element.\n    Offset offset;                 ///< The offset in bytes of this element from the start of the corresponding chunk of vertex stream data.\n    GfxIndex bufferSlotIndex;      ///< The index of the vertex stream to fetch this element's data from.\n};\n\nstruct VertexStreamDesc\n{\n    Size stride;                   ///< The stride in bytes for this vertex stream.\n    InputSlotClass slotClass;      ///< Whether the stream contains per-vertex or per-instance data.\n    GfxCount instanceDataStepRate; ///< How many instances to draw per chunk of data.\n};\n\nenum class PrimitiveType\n{\n    Point, Line, Triangle, Patch\n};\n\nenum class PrimitiveTopology\n{\n    TriangleList, TriangleStrip, PointList, LineList, LineStrip\n};\n\nenum class ResourceState\n{\n    Undefined,\n    General,\n    PreInitialized,\n    VertexBuffer,\n    IndexBuffer,\n    ConstantBuffer,\n    StreamOutput,\n    ShaderResource,\n    UnorderedAccess,\n    RenderTarget,\n    DepthRead,\n    DepthWrite,\n    Present,\n    IndirectArgument,\n    CopySource,\n    CopyDestination,\n    ResolveSource,\n    ResolveDestination,\n    AccelerationStructure,\n    AccelerationStructureBuildInput,\n    PixelShaderResource,\n    NonPixelShaderResource,\n    _Count\n};\n\nstruct ResourceStateSet\n{\npublic:\n    void add(ResourceState state) { m_bitFields |= (1LL << (uint32_t)state); }\n    template <typename... TResourceState> void add(ResourceState s, TResourceState... states)\n    {\n        add(s);\n        add(states...);\n    }\n    bool contains(ResourceState state) const { return (m_bitFields & (1LL << (uint32_t)state)) != 0; }\n    ResourceStateSet()\n        : m_bitFields(0)\n    {}\n    ResourceStateSet(const ResourceStateSet& other) = default;\n    ResourceStateSet(ResourceState state) { add(state); }\n    template <typename... TResourceState> ResourceStateSet(TResourceState... states)\n    {\n        add(states...);\n    }\n\n    ResourceStateSet operator&(const ResourceStateSet& that) const\n    {\n        ResourceStateSet result;\n        result.m_bitFields = this->m_bitFields & that.m_bitFields;\n        return result;\n    }\n\nprivate:\n    uint64_t m_bitFields = 0;\n    void add() {}\n};\n\n\n/// Describes how memory for the resource should be allocated for CPU access.\nenum class MemoryType\n{\n    DeviceLocal,\n    Upload,\n    ReadBack,\n};\n\nenum class InteropHandleAPI\n{\n    Unknown,\n    D3D12, // A D3D12 object pointer.\n    Vulkan, // A general Vulkan object handle.\n    CUDA, // A general CUDA object handle.\n    Win32, // A general Win32 HANDLE.\n    FileDescriptor, // A file descriptor.\n    DeviceAddress, // A device address.\n    D3D12CpuDescriptorHandle, // A D3D12_CPU_DESCRIPTOR_HANDLE value.\n};\n\nstruct InteropHandle\n{\n    InteropHandleAPI api = InteropHandleAPI::Unknown;\n    uint64_t handleValue = 0;\n};\n\n// Declare opaque type\nclass IInputLayout : public ISlangUnknown\n{\npublic:\n    struct Desc\n    {\n        InputElementDesc const* inputElements = nullptr;\n        GfxCount inputElementCount = 0;\n        VertexStreamDesc const* vertexStreams = nullptr;\n        GfxCount vertexStreamCount = 0;\n    };\n};\n#define SLANG_UUID_IInputLayout                                                         \\\n    {                                                                                  \\\n        0x45223711, 0xa84b, 0x455c, { 0xbe, 0xfa, 0x49, 0x37, 0x42, 0x1e, 0x8e, 0x2e } \\\n    }\n\nclass IResource: public ISlangUnknown\n{\npublic:\n        /// The type of resource.\n        /// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise isTexture won't work correctly)\n    enum class Type\n    {\n        Unknown,            ///< Unknown\n        Buffer,             ///< A buffer (like a constant/index/vertex buffer)\n        Texture1D,          ///< A 1d texture\n        Texture2D,          ///< A 2d texture\n        Texture3D,          ///< A 3d texture\n        TextureCube,        ///< A cubemap consists of 6 Texture2D like faces\n        _Count,\n    };\n\n        /// Base class for Descs\n    struct DescBase\n    {\n        Type type = Type::Unknown;\n        ResourceState defaultState = ResourceState::Undefined;\n        ResourceStateSet allowedStates = ResourceStateSet();\n        MemoryType memoryType = MemoryType::DeviceLocal;\n        InteropHandle existingHandle = {};\n        bool isShared = false;\n    };\n\n    virtual SLANG_NO_THROW Type SLANG_MCALL getType() = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) = 0;\n    virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() = 0;\n\n};\n#define SLANG_UUID_IResource                                                           \\\n    {                                                                                  \\\n        0xa0e39f34, 0x8398, 0x4522, { 0x95, 0xc2, 0xeb, 0xc0, 0xf9, 0x84, 0xef, 0x3f } \\\n    }\n\nstruct MemoryRange\n{\n    // TODO: Change to Offset/Size?\n    uint64_t offset;\n    uint64_t size;\n};\n\nclass IBufferResource: public IResource\n{\npublic:\n    struct Desc: public DescBase\n    {\n        Size sizeInBytes = 0;        ///< Total size in bytes\n        Size elementSize = 0;        ///< Get the element stride. If > 0, this is a structured buffer\n        Format format = Format::Unknown;\n    };\n\n    virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() = 0;\n    virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL map(MemoryRange* rangeToRead, void** outPointer) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL unmap(MemoryRange* writtenRange) = 0;\n};\n#define SLANG_UUID_IBufferResource                                                     \\\n    {                                                                                  \\\n        0x1b274efe, 0x5e37, 0x492b, { 0x82, 0x6e, 0x7e, 0xe7, 0xe8, 0xf5, 0xa4, 0x9b } \\\n    }\n\nstruct DepthStencilClearValue\n{\n    float depth = 1.0f;\n    uint32_t stencil = 0;\n};\nunion ColorClearValue\n{\n    float floatValues[4];\n    uint32_t uintValues[4];\n};\nstruct ClearValue\n{\n    ColorClearValue color = {{0.0f, 0.0f, 0.0f, 0.0f}};\n    DepthStencilClearValue depthStencil;\n};\n\nstruct BufferRange\n{\n    // TODO: Change to Index and Count?\n    uint64_t firstElement;\n    uint64_t elementCount;\n};\n\nenum class TextureAspect : uint32_t\n{\n    Default = 0,\n    Color = 0x00000001,\n    Depth = 0x00000002,\n    Stencil = 0x00000004,\n    MetaData = 0x00000008,\n    Plane0 = 0x00000010,\n    Plane1 = 0x00000020,\n    Plane2 = 0x00000040,\n\n    DepthStencil = Depth | Stencil,\n};\n\nstruct SubresourceRange\n{\n    TextureAspect aspectMask;\n    GfxIndex mipLevel;\n    GfxCount mipLevelCount;\n    GfxIndex baseArrayLayer; // For Texture3D, this is WSlice.\n    GfxCount layerCount; // For cube maps, this is a multiple of 6.\n};\n\nclass ITextureResource: public IResource\n{\npublic:\n    static const Size kRemainingTextureSize = 0xFFFFFFFF;\n    struct Offset3D\n    {\n        GfxIndex x = 0;\n        GfxIndex y = 0;\n        GfxIndex z = 0;\n        Offset3D() = default;\n        Offset3D(GfxIndex _x, GfxIndex _y, GfxIndex _z) :x(_x), y(_y), z(_z) {}\n    };\n\n    struct SampleDesc\n    {\n        GfxCount numSamples = 1;                ///< Number of samples per pixel\n        int quality = 0;                        ///< The quality measure for the samples\n    };\n\n    struct Extents\n    {\n        GfxCount width = 0;              ///< Width in pixels\n        GfxCount height = 0;             ///< Height in pixels (if 2d or 3d)\n        GfxCount depth = 0;              ///< Depth (if 3d)\n    };\n\n    struct Desc: public DescBase\n    {\n        Extents size;\n\n        GfxCount arraySize = 0;          ///< Array size\n\n        GfxCount numMipLevels = 0;       ///< Number of mip levels - if 0 will create all mip levels\n        Format format;                   ///< The resources format\n        SampleDesc sampleDesc;           ///< How the resource is sampled\n        ClearValue* optimalClearValue = nullptr;\n    };\n\n        /// Data for a single subresource of a texture.\n        ///\n        /// Each subresource is a tensor with `1 <= rank <= 3`,\n        /// where the rank is deterined by the base shape of the\n        /// texture (Buffer, 1D, 2D, 3D, or Cube). For the common\n        /// case of a 2D texture, `rank == 2` and each subresource\n        /// is a 2D image.\n        ///\n        /// Subresource tensors must be stored in a row-major layout,\n        /// so that the X axis strides over texels, the Y axis strides\n        /// over 1D rows of texels, and the Z axis strides over 2D\n        /// \"layers\" of texels.\n        ///\n        /// For a texture with multiple mip levels or array elements,\n        /// each mip level and array element is stores as a distinct\n        /// subresource. When indexing into an array of subresources,\n        /// the index of a subresoruce for mip level `m` and array\n        /// index `a` is `m + a*mipLevelCount`.\n        ///\n    struct SubresourceData\n    {\n            /// Pointer to texel data for the subresource tensor.\n        void const* data;\n\n            /// Stride in bytes between rows of the subresource tensor.\n            ///\n            /// This is the number of bytes to add to a pointer to a texel\n            /// at (X,Y,Z) to get to a texel at (X,Y+1,Z).\n            ///\n            /// Devices may not support all possible values for `strideY`.\n            /// In particular, they may only support strictly positive strides.\n            ///\n        gfx::Size strideY;\n\n            /// Stride in bytes between layers of the subresource tensor.\n            ///\n            /// This is the number of bytes to add to a pointer to a texel\n            /// at (X,Y,Z) to get to a texel at (X,Y,Z+1).\n            ///\n            /// Devices may not support all possible values for `strideZ`.\n            /// In particular, they may only support strictly positive strides.\n            ///\n        gfx::Size strideZ;\n    };\n\n    virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() = 0;\n};\n#define SLANG_UUID_ITextureResource                                                    \\\n    {                                                                                  \\\n        0xcf88a31c, 0x6187, 0x46c5, { 0xa4, 0xb7, 0xeb, 0x58, 0xc7, 0x33, 0x40, 0x17 } \\\n    }\n\n\nenum class ComparisonFunc : uint8_t\n{\n    Never           = 0x0,\n    Less            = 0x1,\n    Equal           = 0x2,\n    LessEqual       = 0x3,\n    Greater         = 0x4,\n    NotEqual        = 0x5,\n    GreaterEqual    = 0x6,\n    Always          = 0x7,\n};\n\nenum class TextureFilteringMode\n{\n    Point,\n    Linear,\n};\n\nenum class TextureAddressingMode\n{\n    Wrap,\n    ClampToEdge,\n    ClampToBorder,\n    MirrorRepeat,\n    MirrorOnce,\n};\n\nenum class TextureReductionOp\n{\n    Average,\n    Comparison,\n    Minimum,\n    Maximum,\n};\n\nclass ISamplerState : public ISlangUnknown\n{\npublic:\n    struct Desc\n    {\n        TextureFilteringMode    minFilter       = TextureFilteringMode::Linear;\n        TextureFilteringMode    magFilter       = TextureFilteringMode::Linear;\n        TextureFilteringMode    mipFilter       = TextureFilteringMode::Linear;\n        TextureReductionOp      reductionOp     = TextureReductionOp::Average;\n        TextureAddressingMode   addressU        = TextureAddressingMode::Wrap;\n        TextureAddressingMode   addressV        = TextureAddressingMode::Wrap;\n        TextureAddressingMode   addressW        = TextureAddressingMode::Wrap;\n        float                   mipLODBias      = 0.0f;\n        uint32_t                maxAnisotropy   = 1;\n        ComparisonFunc          comparisonFunc  = ComparisonFunc::Never;\n        float                   borderColor[4]  = { 1.0f, 1.0f, 1.0f, 1.0f };\n        float                   minLOD          = -FLT_MAX;\n        float                   maxLOD          = FLT_MAX;\n    };\n\n    /// Returns a native API handle representing this sampler state object.\n    /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE.\n    /// When using Vulkan, this will be a VkSampler.\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0;\n};\n#define SLANG_UUID_ISamplerState                                                        \\\n    {                                                                                  \\\n        0x8b8055df, 0x9377, 0x401d, { 0x91, 0xff, 0x3f, 0xa3, 0xbf, 0x66, 0x64, 0xf4 } \\\n    }\n\nclass IResourceView : public ISlangUnknown\n{\npublic:\n    enum class Type\n    {\n        Unknown,\n\n        RenderTarget,\n        DepthStencil,\n        ShaderResource,\n        UnorderedAccess,\n        AccelerationStructure,\n\n        CountOf_,\n    };\n\n    struct RenderTargetDesc\n    {\n        // The resource shape of this render target view.\n        IResource::Type shape;\n    };\n\n    struct Desc\n    {\n        Type    type;\n        Format  format;\n\n        // Required fields for `RenderTarget` and `DepthStencil` views.\n        RenderTargetDesc renderTarget;\n        // Specifies the range of a texture resource for a ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view.\n        SubresourceRange subresourceRange;\n        // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view.\n        BufferRange bufferRange;\n        // Specifies the element size in bytes of a structured buffer. Pass 0 for a raw buffer view.\n        Size bufferElementSize;\n    };\n    virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0;\n\n    /// Returns a native API handle representing this resource view object.\n    /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE or a buffer device address depending\n    /// on the type of the resource view.\n    /// When using Vulkan, this will be a VkImageView, VkBufferView, VkAccelerationStructure or a VkBuffer\n    /// depending on the type of the resource view.\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0;\n};\n#define SLANG_UUID_IResourceView                                                      \\\n    {                                                                                 \\\n        0x7b6c4926, 0x884, 0x408c, { 0xad, 0x8a, 0x50, 0x3a, 0x8e, 0x23, 0x98, 0xa4 } \\\n    }\n\nclass IAccelerationStructure : public IResourceView\n{\npublic:\n    enum class Kind\n    {\n        TopLevel,\n        BottomLevel\n    };\n\n    struct BuildFlags\n    {\n        // The enum values are intentionally consistent with\n        // D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS.\n        enum Enum\n        {\n            None,\n            AllowUpdate = 1,\n            AllowCompaction = 2,\n            PreferFastTrace = 4,\n            PreferFastBuild = 8,\n            MinimizeMemory = 16,\n            PerformUpdate = 32\n        };\n    };\n\n    enum class GeometryType\n    {\n        Triangles, ProcedurePrimitives\n    };\n\n    struct GeometryFlags\n    {\n        // The enum values are intentionally consistent with\n        // D3D12_RAYTRACING_GEOMETRY_FLAGS.\n        enum Enum\n        {\n            None,\n            Opaque = 1,\n            NoDuplicateAnyHitInvocation = 2\n        };\n    };\n\n    struct TriangleDesc\n    {\n        DeviceAddress transform3x4;\n        Format indexFormat;\n        Format vertexFormat;\n        GfxCount indexCount;\n        GfxCount vertexCount;\n        DeviceAddress indexData;\n        DeviceAddress vertexData;\n        Size vertexStride;\n    };\n\n    struct ProceduralAABB\n    {\n        float minX;\n        float minY;\n        float minZ;\n        float maxX;\n        float maxY;\n        float maxZ;\n    };\n\n    struct ProceduralAABBDesc\n    {\n        /// Number of AABBs.\n        GfxCount count;\n\n        /// Pointer to an array of `ProceduralAABB` values in device memory.\n        DeviceAddress data;\n\n        /// Stride in bytes of the AABB values array.\n        Size stride;\n    };\n\n    struct GeometryDesc\n    {\n        GeometryType type;\n        GeometryFlags::Enum flags;\n        union\n        {\n            TriangleDesc triangles;\n            ProceduralAABBDesc proceduralAABBs;\n        } content;\n    };\n\n    struct GeometryInstanceFlags\n    {\n        // The enum values are kept consistent with D3D12_RAYTRACING_INSTANCE_FLAGS\n        // and VkGeometryInstanceFlagBitsKHR.\n        enum Enum : uint32_t\n        {\n            None = 0,\n            TriangleFacingCullDisable = 0x00000001,\n            TriangleFrontCounterClockwise = 0x00000002,\n            ForceOpaque = 0x00000004,\n            NoOpaque = 0x00000008\n        };\n    };\n\n    // TODO: Should any of these be changed?\n    // The layout of this struct is intentionally consistent with D3D12_RAYTRACING_INSTANCE_DESC\n    // and VkAccelerationStructureInstanceKHR.\n    struct InstanceDesc\n    {\n        float transform[3][4];\n        uint32_t instanceID : 24;\n        uint32_t instanceMask : 8;\n        uint32_t instanceContributionToHitGroupIndex : 24;\n        uint32_t flags : 8; // Combination of GeometryInstanceFlags::Enum values.\n        DeviceAddress accelerationStructure;\n    };\n\n    struct PrebuildInfo\n    {\n        Size resultDataMaxSize;\n        Size scratchDataSize;\n        Size updateScratchDataSize;\n    };\n\n    struct BuildInputs\n    {\n        Kind kind;\n\n        BuildFlags::Enum flags;\n\n        GfxCount descCount;\n\n        /// Array of `InstanceDesc` values in device memory.\n        /// Used when `kind` is `TopLevel`.\n        DeviceAddress instanceDescs;\n\n        /// Array of `GeometryDesc` values.\n        /// Used when `kind` is `BottomLevel`.\n        const GeometryDesc* geometryDescs;\n    };\n\n    struct CreateDesc\n    {\n        Kind kind;\n        IBufferResource* buffer;\n        Offset offset;\n        Size size;\n    };\n\n    struct BuildDesc\n    {\n        BuildInputs inputs;\n        IAccelerationStructure* source;\n        IAccelerationStructure* dest;\n        DeviceAddress scratchData;\n    };\n\n    virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0;\n};\n#define SLANG_UUID_IAccelerationStructure                                             \\\n    {                                                                                 \\\n        0xa5cdda3c, 0x1d4e, 0x4df7, { 0x8e, 0xf2, 0xb7, 0x3f, 0xce, 0x4, 0xde, 0x3b } \\\n    }\n\nclass IFence : public ISlangUnknown\n{\npublic:\n    struct Desc\n    {\n        uint64_t initialValue = 0;\n        bool isShared = false;\n    };\n\n    /// Returns the currently signaled value on the device.\n    virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) = 0;\n\n    /// Signals the fence from the host with the specified value.\n    virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0;\n};\n#define SLANG_UUID_IFence                                                             \\\n    {                                                                                 \\\n        0x7fe1c283, 0xd3f4, 0x48ed, { 0xaa, 0xf3, 0x1, 0x51, 0x96, 0x4e, 0x7c, 0xb5 } \\\n    }\n\nstruct ShaderOffset\n{\n    SlangInt uniformOffset = 0; // TODO: Change to Offset?\n    GfxIndex bindingRangeIndex = 0;\n    GfxIndex bindingArrayIndex = 0;\n    uint32_t getHashCode() const\n    {\n        return (uint32_t)(((bindingRangeIndex << 20) + bindingArrayIndex) ^ uniformOffset);\n    }\n    bool operator==(const ShaderOffset& other) const\n    {\n        return uniformOffset == other.uniformOffset\n            && bindingRangeIndex == other.bindingRangeIndex\n            && bindingArrayIndex == other.bindingArrayIndex;\n    }\n    bool operator!=(const ShaderOffset& other) const\n    {\n        return !this->operator==(other);\n    }\n    bool operator<(const ShaderOffset& other) const\n    {\n        if (bindingRangeIndex < other.bindingRangeIndex)\n            return true;\n        if (bindingRangeIndex > other.bindingRangeIndex)\n            return false;\n        if (bindingArrayIndex < other.bindingArrayIndex)\n            return true;\n        if (bindingArrayIndex > other.bindingArrayIndex)\n            return false;\n        return uniformOffset < other.uniformOffset;\n    }\n    bool operator<=(const ShaderOffset& other) const { return (*this == other) || (*this) < other; }\n    bool operator>(const ShaderOffset& other) const { return other < *this; }\n    bool operator>=(const ShaderOffset& other) const { return other <= *this; }\n};\n\nenum class ShaderObjectContainerType\n{\n    None, Array, StructuredBuffer\n};\n\nclass IShaderObject : public ISlangUnknown\n{\npublic:\n    virtual SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL getElementTypeLayout() = 0;\n    virtual SLANG_NO_THROW ShaderObjectContainerType SLANG_MCALL getContainerType() = 0;\n    virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount() = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        getEntryPoint(GfxIndex index, IShaderObject** entryPoint) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        setData(ShaderOffset const& offset, void const* data, Size size) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        getObject(ShaderOffset const& offset, IShaderObject** object) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        setObject(ShaderOffset const& offset, IShaderObject* object) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        setResource(ShaderOffset const& offset, IResourceView* resourceView) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        setSampler(ShaderOffset const& offset, ISamplerState* sampler) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler(\n        ShaderOffset const& offset, IResourceView* textureView, ISamplerState* sampler) = 0;\n\n        /// Manually overrides the specialization argument for the sub-object binding at `offset`.\n        /// Specialization arguments are passed to the shader compiler to specialize the type\n        /// of interface-typed shader parameters.\n    virtual SLANG_NO_THROW Result SLANG_MCALL setSpecializationArgs(\n        ShaderOffset const& offset,\n        const slang::SpecializationArg* args,\n        GfxCount count) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentVersion(\n        ITransientResourceHeap* transientHeap,\n        IShaderObject** outObject) = 0;\n\n    virtual SLANG_NO_THROW const void* SLANG_MCALL getRawData() = 0;\n\n    virtual SLANG_NO_THROW Size SLANG_MCALL getSize() = 0;\n\n        /// Use the provided constant buffer instead of the internally created one.\n    virtual SLANG_NO_THROW Result SLANG_MCALL setConstantBufferOverride(IBufferResource* constantBuffer) = 0;\n\n\n    inline ComPtr<IShaderObject> getObject(ShaderOffset const& offset)\n    {\n        ComPtr<IShaderObject> object = nullptr;\n        SLANG_RETURN_NULL_ON_FAIL(getObject(offset, object.writeRef()));\n        return object;\n    }\n    inline ComPtr<IShaderObject> getEntryPoint(GfxIndex index)\n    {\n        ComPtr<IShaderObject> entryPoint = nullptr;\n        SLANG_RETURN_NULL_ON_FAIL(getEntryPoint(index, entryPoint.writeRef()));\n        return entryPoint;\n    }\n};\n#define SLANG_UUID_IShaderObject                                                       \\\n    {                                                                                 \\\n        0xc1fa997e, 0x5ca2, 0x45ae, { 0x9b, 0xcb, 0xc4, 0x35, 0x9e, 0x85, 0x5, 0x85 } \\\n    }\n\nenum class StencilOp : uint8_t\n{\n    Keep,\n    Zero,\n    Replace,\n    IncrementSaturate,\n    DecrementSaturate,\n    Invert,\n    IncrementWrap,\n    DecrementWrap,\n};\n\nenum class FillMode : uint8_t\n{\n    Solid,\n    Wireframe,\n};\n\nenum class CullMode : uint8_t\n{\n    None,\n    Front,\n    Back,\n};\n\nenum class FrontFaceMode : uint8_t\n{\n    CounterClockwise,\n    Clockwise,\n};\n\nstruct DepthStencilOpDesc\n{\n    StencilOp       stencilFailOp       = StencilOp::Keep;\n    StencilOp       stencilDepthFailOp  = StencilOp::Keep;\n    StencilOp       stencilPassOp       = StencilOp::Keep;\n    ComparisonFunc  stencilFunc         = ComparisonFunc::Always;\n};\n\nstruct DepthStencilDesc\n{\n    bool            depthTestEnable     = false;\n    bool            depthWriteEnable    = true;\n    ComparisonFunc  depthFunc           = ComparisonFunc::Less;\n\n    bool                stencilEnable       = false;\n    uint32_t            stencilReadMask     = 0xFFFFFFFF;\n    uint32_t            stencilWriteMask    = 0xFFFFFFFF;\n    DepthStencilOpDesc  frontFace;\n    DepthStencilOpDesc  backFace;\n\n    uint32_t stencilRef = 0;\n};\n\nstruct RasterizerDesc\n{\n    FillMode fillMode = FillMode::Solid;\n    CullMode cullMode = CullMode::None;\n    FrontFaceMode frontFace = FrontFaceMode::CounterClockwise;\n    int32_t depthBias = 0;\n    float depthBiasClamp = 0.0f;\n    float slopeScaledDepthBias = 0.0f;\n    bool depthClipEnable = true;\n    bool scissorEnable = false;\n    bool multisampleEnable = false;\n    bool antialiasedLineEnable = false;\n    bool enableConservativeRasterization = false;\n    uint32_t forcedSampleCount = 0;\n};\n\nenum class LogicOp\n{\n    NoOp,\n};\n\nenum class BlendOp\n{\n    Add,\n    Subtract,\n    ReverseSubtract,\n    Min,\n    Max,\n};\n\nenum class BlendFactor\n{\n    Zero,\n    One,\n    SrcColor,\n    InvSrcColor,\n    SrcAlpha,\n    InvSrcAlpha,\n    DestAlpha,\n    InvDestAlpha,\n    DestColor,\n    InvDestColor,\n    SrcAlphaSaturate,\n    BlendColor,\n    InvBlendColor,\n    SecondarySrcColor,\n    InvSecondarySrcColor,\n    SecondarySrcAlpha,\n    InvSecondarySrcAlpha,\n};\n\nnamespace RenderTargetWriteMask\n{\n    typedef uint8_t Type;\n    enum\n    {\n        EnableNone  = 0,\n        EnableRed   = 0x01,\n        EnableGreen = 0x02,\n        EnableBlue  = 0x04,\n        EnableAlpha = 0x08,\n        EnableAll   = 0x0F,\n    };\n};\ntypedef RenderTargetWriteMask::Type RenderTargetWriteMaskT;\n\nstruct AspectBlendDesc\n{\n    BlendFactor     srcFactor   = BlendFactor::One;\n    BlendFactor     dstFactor   = BlendFactor::Zero;\n    BlendOp         op          = BlendOp::Add;\n};\n\nstruct TargetBlendDesc\n{\n    AspectBlendDesc color;\n    AspectBlendDesc alpha;\n    bool enableBlend = false;\n    LogicOp                 logicOp     = LogicOp::NoOp;\n    RenderTargetWriteMaskT  writeMask   = RenderTargetWriteMask::EnableAll;\n};\n\nstruct BlendDesc\n{\n    TargetBlendDesc         targets[kMaxRenderTargetCount];\n    GfxCount                targetCount = 0;\n\n    bool alphaToCoverageEnable  = false;\n};\n\nclass IFramebufferLayout : public ISlangUnknown\n{\npublic:\n    struct TargetLayout\n    {\n        Format format;\n        GfxCount sampleCount;\n    };\n    struct Desc\n    {\n        GfxCount renderTargetCount;\n        TargetLayout* renderTargets = nullptr;\n        TargetLayout* depthStencil = nullptr;\n    };\n};\n#define SLANG_UUID_IFramebufferLayout                                                \\\n    {                                                                                \\\n        0xa838785, 0xc13a, 0x4832, { 0xad, 0x88, 0x64, 0x6, 0xb5, 0x4b, 0x5e, 0xba } \\\n    }\n\nstruct GraphicsPipelineStateDesc\n{\n    IShaderProgram*      program = nullptr;\n\n    IInputLayout*       inputLayout = nullptr;\n    IFramebufferLayout* framebufferLayout = nullptr;\n    PrimitiveType       primitiveType = PrimitiveType::Triangle;\n    DepthStencilDesc    depthStencil;\n    RasterizerDesc      rasterizer;\n    BlendDesc           blend;\n};\n\nstruct ComputePipelineStateDesc\n{\n    IShaderProgram*  program = nullptr;\n    void* d3d12RootSignatureOverride = nullptr;\n};\n\nstruct RayTracingPipelineFlags\n{\n    enum Enum : uint32_t\n    {\n        None = 0,\n        SkipTriangles = 1,\n        SkipProcedurals = 2,\n    };\n};\n\nstruct HitGroupDesc\n{\n    const char* hitGroupName = nullptr;\n    const char* closestHitEntryPoint = nullptr;\n    const char* anyHitEntryPoint = nullptr;\n    const char* intersectionEntryPoint = nullptr;\n};\n\nstruct RayTracingPipelineStateDesc\n{\n    IShaderProgram* program = nullptr;\n    GfxCount hitGroupCount = 0;\n    const HitGroupDesc* hitGroups = nullptr;\n    int maxRecursion = 0;\n    Size maxRayPayloadSize = 0;\n    Size maxAttributeSizeInBytes = 8;\n    RayTracingPipelineFlags::Enum flags = RayTracingPipelineFlags::None;\n};\n\nclass IShaderTable : public ISlangUnknown\n{\npublic:\n    // Specifies the bytes to overwrite into a record in the shader table.\n    struct ShaderRecordOverwrite\n    {\n        Offset offset; // Offset within the shader record.\n        Size size; // Number of bytes to overwrite.\n        uint8_t data[8]; // Content to overwrite.\n    };\n\n    struct Desc\n    {\n        GfxCount rayGenShaderCount;\n        const char** rayGenShaderEntryPointNames;\n        const ShaderRecordOverwrite* rayGenShaderRecordOverwrites;\n\n        GfxCount missShaderCount;\n        const char** missShaderEntryPointNames;\n        const ShaderRecordOverwrite* missShaderRecordOverwrites;\n\n        GfxCount hitGroupCount;\n        const char** hitGroupNames;\n        const ShaderRecordOverwrite* hitGroupRecordOverwrites;\n\n        IShaderProgram* program;\n    };\n};\n#define SLANG_UUID_IShaderTable                                                        \\\n    {                                                                                  \\\n        0xa721522c, 0xdf31, 0x4c2f, { 0xa5, 0xe7, 0x3b, 0xe0, 0x12, 0x4b, 0x31, 0x78 } \\\n    }\n\nclass IPipelineState : public ISlangUnknown\n{\npublic:\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0;\n};\n#define SLANG_UUID_IPipelineState                                                      \\\n    {                                                                                 \\\n        0xca7e57d, 0x8a90, 0x44f3, { 0xbd, 0xb1, 0xfe, 0x9b, 0x35, 0x3f, 0x5a, 0x72 } \\\n    }\n\n\nstruct ScissorRect\n{\n    int32_t minX;\n    int32_t minY;\n    int32_t maxX;\n    int32_t maxY;\n};\n\nstruct Viewport\n{\n    float originX = 0.0f;\n    float originY = 0.0f;\n    float extentX = 0.0f;\n    float extentY = 0.0f;\n    float minZ    = 0.0f;\n    float maxZ    = 1.0f;\n};\n\nclass IFramebuffer : public ISlangUnknown\n{\npublic:\n    struct Desc\n    {\n        GfxCount renderTargetCount;\n        IResourceView* const* renderTargetViews;\n        IResourceView* depthStencilView;\n        IFramebufferLayout* layout;\n    };\n};\n#define SLANG_UUID_IFrameBuffer                                                       \\\n    {                                                                                 \\\n        0xf0c0d9a, 0x4ef3, 0x4e18, { 0x9b, 0xa9, 0x34, 0x60, 0xea, 0x69, 0x87, 0x95 } \\\n    }\n\nstruct WindowHandle\n{\n    enum class Type\n    {\n        Unknown,\n        Win32Handle,\n        XLibHandle,\n    };\n    Type type;\n    intptr_t handleValues[2];\n    static WindowHandle FromHwnd(void* hwnd)\n    {\n        WindowHandle handle = {};\n        handle.type = WindowHandle::Type::Win32Handle;\n        handle.handleValues[0] = (intptr_t)(hwnd);\n        return handle;\n    }\n    static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow)\n    {\n        WindowHandle handle = {};\n        handle.type = WindowHandle::Type::XLibHandle;\n        handle.handleValues[0] = (intptr_t)(xdisplay);\n        handle.handleValues[1] = xwindow;\n        return handle;\n    }\n};\n\nstruct FaceMask\n{\n    enum Enum\n    {\n        Front = 1, Back = 2\n    };\n};\n\nclass IRenderPassLayout : public ISlangUnknown\n{\npublic:\n    enum class TargetLoadOp\n    {\n        Load, Clear, DontCare\n    };\n    enum class TargetStoreOp\n    {\n        Store, DontCare\n    };\n    struct TargetAccessDesc\n    {\n        TargetLoadOp loadOp;\n        TargetLoadOp stencilLoadOp;\n        TargetStoreOp storeOp;\n        TargetStoreOp stencilStoreOp;\n        ResourceState initialState;\n        ResourceState finalState;\n    };\n    struct Desc\n    {\n        IFramebufferLayout* framebufferLayout = nullptr;\n        GfxCount renderTargetCount;\n        TargetAccessDesc* renderTargetAccess = nullptr;\n        TargetAccessDesc* depthStencilAccess = nullptr;\n    };\n};\n#define SLANG_UUID_IRenderPassLayout                                                   \\\n    {                                                                                  \\\n        0xdaab0b1a, 0xf45d, 0x4ae9, { 0xbf, 0x2c, 0xe0, 0xbb, 0x76, 0x7d, 0xfa, 0xd1 } \\\n    }\n\nenum class QueryType\n{\n    Timestamp,\n    AccelerationStructureCompactedSize,\n    AccelerationStructureSerializedSize,\n    AccelerationStructureCurrentSize,\n};\n\nclass IQueryPool : public ISlangUnknown\n{\npublic:\n    struct Desc\n    {\n        QueryType type;\n        GfxCount count;\n    };\npublic:\n    virtual SLANG_NO_THROW Result SLANG_MCALL getResult(GfxIndex queryIndex, GfxCount count, uint64_t* data) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL reset() = 0;\n};\n#define SLANG_UUID_IQueryPool                                                         \\\n    { 0xc2cc3784, 0x12da, 0x480a, { 0xa8, 0x74, 0x8b, 0x31, 0x96, 0x1c, 0xa4, 0x36 } }\n\n\nclass ICommandEncoder : public ISlangUnknown\n{\n    SLANG_COM_INTERFACE( 0x77ea6383, 0xbe3d, 0x40aa, { 0x8b, 0x45, 0xfd, 0xf0, 0xd7, 0x5b, 0xfa, 0x34 });\npublic:\n    virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, GfxIndex queryIndex) = 0;\n};\n\nstruct IndirectDispatchArguments\n{\n    GfxCount ThreadGroupCountX;\n    GfxCount ThreadGroupCountY;\n    GfxCount ThreadGroupCountZ;\n};\n\nstruct IndirectDrawArguments\n{\n    GfxCount VertexCountPerInstance;\n    GfxCount InstanceCount;\n    GfxIndex StartVertexLocation;\n    GfxIndex StartInstanceLocation;\n};\n\nstruct IndirectDrawIndexedArguments\n{\n    GfxCount IndexCountPerInstance;\n    GfxCount InstanceCount;\n    GfxIndex StartIndexLocation;\n    GfxIndex BaseVertexLocation;\n    GfxIndex StartInstanceLocation;\n};\n\nstruct SamplePosition\n{\n    int8_t x;\n    int8_t y;\n};\n\nstruct ClearResourceViewFlags\n{\n    enum Enum : uint32_t\n    {\n        None = 0,\n        ClearDepth = 1,\n        ClearStencil = 2,\n        FloatClearValues = 4\n    };\n};\n\nclass IResourceCommandEncoder : public ICommandEncoder\n{\n    // {F99A00E9-ED50-4088-8A0E-3B26755031EA}\n    SLANG_COM_INTERFACE(0xf99a00e9, 0xed50, 0x4088, { 0x8a, 0xe, 0x3b, 0x26, 0x75, 0x50, 0x31, 0xea });\n\npublic:\n    virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer(\n        IBufferResource* dst,\n        Offset dstOffset,\n        IBufferResource* src,\n        Offset srcOffset,\n        Size size) = 0;\n\n    /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0\n    /// and layerCount = 0, the entire resource is being copied and dstOffset, srcOffset and extent\n    /// arguments are ignored.\n    virtual SLANG_NO_THROW void SLANG_MCALL copyTexture(\n        ITextureResource* dst,\n        ResourceState dstState,\n        SubresourceRange dstSubresource,\n        ITextureResource::Offset3D dstOffset,\n        ITextureResource* src,\n        ResourceState srcState,\n        SubresourceRange srcSubresource,\n        ITextureResource::Offset3D srcOffset,\n        ITextureResource::Extents extent) = 0;\n\n    /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment.\n    virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(\n        IBufferResource* dst,\n        Offset dstOffset,\n        Size dstSize,\n        Size dstRowStride,\n        ITextureResource* src,\n        ResourceState srcState,\n        SubresourceRange srcSubresource,\n        ITextureResource::Offset3D srcOffset,\n        ITextureResource::Extents extent) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData(\n        ITextureResource* dst,\n        SubresourceRange subResourceRange,\n        ITextureResource::Offset3D offset,\n        ITextureResource::Extents extent,\n        ITextureResource::SubresourceData* subResourceData,\n        GfxCount subResourceDataCount) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        uploadBufferData(IBufferResource* dst, Offset offset, Size size, void* data) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier(\n        GfxCount count, ITextureResource* const* textures, ResourceState src, ResourceState dst) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier(\n        ITextureResource* texture,\n        SubresourceRange subresourceRange,\n        ResourceState src,\n        ResourceState dst) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier(\n        GfxCount count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView(\n        IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(\n        ITextureResource* source,\n        ResourceState sourceState,\n        SubresourceRange sourceRange,\n        ITextureResource* dest,\n        ResourceState destState,\n        SubresourceRange destRange) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(\n        IQueryPool* queryPool,\n        GfxIndex index,\n        GfxCount count,\n        IBufferResource* buffer,\n        Offset offset) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() = 0;\n    inline void textureBarrier(ITextureResource* texture, ResourceState src, ResourceState dst)\n    {\n        textureBarrier(1, &texture, src, dst);\n    }\n    inline void bufferBarrier(IBufferResource* buffer, ResourceState src, ResourceState dst)\n    {\n        bufferBarrier(1, &buffer, src, dst);\n    }\n};\n\nclass IRenderCommandEncoder : public IResourceCommandEncoder\n{\n    // {7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE}\n    SLANG_COM_INTERFACE(0x7a8d56d0, 0x53e6, 0x4ad6, { 0x85, 0xf7, 0xd1, 0x4d, 0xc1, 0x10, 0xfd, 0xce })\npublic:\n    // Sets the current pipeline state. This method returns a transient shader object for\n    // writing shader parameters. This shader object will not retain any resources or\n    // sub-shader-objects bound to it. The user must be responsible for ensuring that any\n    // resources or shader objects that is set into `outRootShaderObject` stays alive during\n    // the execution of the command buffer.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0;\n    inline IShaderObject* bindPipeline(IPipelineState* state)\n    {\n        IShaderObject* rootObject = nullptr;\n        SLANG_RETURN_NULL_ON_FAIL(bindPipeline(state, &rootObject));\n        return rootObject;\n    }\n\n    // Sets the current pipeline state along with a pre-created mutable root shader object.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0;\n\n    virtual SLANG_NO_THROW void\n        SLANG_MCALL setViewports(GfxCount count, const Viewport* viewports) = 0;\n    virtual SLANG_NO_THROW void\n        SLANG_MCALL setScissorRects(GfxCount count, const ScissorRect* scissors) = 0;\n\n    /// Sets the viewport, and sets the scissor rect to match the viewport.\n    inline void setViewportAndScissor(Viewport const& viewport)\n    {\n        setViewports(1, &viewport);\n        ScissorRect rect = {};\n        rect.maxX = static_cast<gfx::Int>(viewport.extentX);\n        rect.maxY = static_cast<gfx::Int>(viewport.extentY);\n        setScissorRects(1, &rect);\n    }\n\n    virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers(\n        GfxIndex startSlot,\n        GfxCount slotCount,\n        IBufferResource* const* buffers,\n        const Offset* offsets) = 0;\n    inline void setVertexBuffer(\n        GfxIndex slot, IBufferResource* buffer, Offset offset = 0)\n    {\n        setVertexBuffers(slot, 1, &buffer, &offset);\n    }\n\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        draw(GfxCount vertexCount, GfxIndex startVertex = 0) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect(\n        GfxCount maxDrawCount,\n        IBufferResource* argBuffer,\n        Offset argOffset,\n        IBufferResource* countBuffer = nullptr,\n        Offset countOffset = 0) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect(\n        GfxCount maxDrawCount,\n        IBufferResource* argBuffer,\n        Offset argOffset,\n        IBufferResource* countBuffer = nullptr,\n        Offset countOffset = 0) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions(\n        GfxCount samplesPerPixel, GfxCount pixelCount, const SamplePosition* samplePositions) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced(\n        GfxCount vertexCount,\n        GfxCount instanceCount,\n        GfxIndex startVertex,\n        GfxIndex startInstanceLocation) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced(\n        GfxCount indexCount,\n        GfxCount instanceCount,\n        GfxIndex startIndexLocation,\n        GfxIndex baseVertexLocation,\n        GfxIndex startInstanceLocation) = 0;\n};\n\nclass IComputeCommandEncoder : public IResourceCommandEncoder\n{\n    // {88AA9322-82F7-4FE6-A68A-29C7FE798737}\n    SLANG_COM_INTERFACE(0x88aa9322, 0x82f7, 0x4fe6, { 0xa6, 0x8a, 0x29, 0xc7, 0xfe, 0x79, 0x87, 0x37 })\n\npublic:\n    // Sets the current pipeline state. This method returns a transient shader object for\n    // writing shader parameters. This shader object will not retain any resources or\n    // sub-shader-objects bound to it. The user must be responsible for ensuring that any\n    // resources or shader objects that is set into `outRooShaderObject` stays alive during\n    // the execution of the command buffer.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0;\n    inline IShaderObject* bindPipeline(IPipelineState* state)\n    {\n        IShaderObject* rootObject = nullptr;\n        SLANG_RETURN_NULL_ON_FAIL(bindPipeline(state, &rootObject));\n        return rootObject;\n    }\n    // Sets the current pipeline state along with a pre-created mutable root shader object.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL dispatchComputeIndirect(IBufferResource* cmdBuffer, Offset offset) = 0;\n};\n\nenum class AccelerationStructureCopyMode\n{\n    Clone, Compact\n};\n\nstruct AccelerationStructureQueryDesc\n{\n    QueryType queryType;\n\n    IQueryPool* queryPool;\n\n    GfxIndex firstQueryIndex;\n};\n\nclass IRayTracingCommandEncoder : public IResourceCommandEncoder\n{\n    SLANG_COM_INTERFACE(0x9a672b87, 0x5035, 0x45e3, { 0x96, 0x7c, 0x1f, 0x85, 0xcd, 0xb3, 0x63, 0x4f })\npublic:\n    virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure(\n        const IAccelerationStructure::BuildDesc& desc,\n        GfxCount propertyQueryCount,\n        AccelerationStructureQueryDesc* queryDescs) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL copyAccelerationStructure(\n        IAccelerationStructure* dest,\n        IAccelerationStructure* src,\n        AccelerationStructureCopyMode mode) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL queryAccelerationStructureProperties(\n        GfxCount accelerationStructureCount,\n        IAccelerationStructure* const* accelerationStructures,\n        GfxCount queryCount,\n        AccelerationStructureQueryDesc* queryDescs) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0;\n\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        bindPipeline(IPipelineState* state, IShaderObject** outRootObject) = 0;\n    // Sets the current pipeline state along with a pre-created mutable root shader object.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0;\n\n    /// Issues a dispatch command to start ray tracing workload with a ray tracing pipeline.\n    /// `rayGenShaderIndex` specifies the index into the shader table that identifies the ray generation shader.\n    virtual SLANG_NO_THROW void SLANG_MCALL dispatchRays(\n        GfxIndex rayGenShaderIndex,\n        IShaderTable* shaderTable,\n        GfxCount width,\n        GfxCount height,\n        GfxCount depth) = 0;\n};\n\nclass ICommandBuffer : public ISlangUnknown\n{\npublic:\n    // Only one encoder may be open at a time. User must call `ICommandEncoder::endEncoding`\n    // before calling other `encode*Commands` methods.\n    // Once `endEncoding` is called, the `ICommandEncoder` object becomes obsolete and is\n    // invalid for further use. To continue recording, the user must request a new encoder\n    // object by calling one of the `encode*Commands` methods again.\n    virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands(\n        IRenderPassLayout* renderPass,\n        IFramebuffer* framebuffer,\n        IRenderCommandEncoder** outEncoder) = 0;\n    inline IRenderCommandEncoder*\n        encodeRenderCommands(IRenderPassLayout* renderPass, IFramebuffer* framebuffer)\n    {\n        IRenderCommandEncoder* result;\n        encodeRenderCommands(renderPass, framebuffer, &result);\n        return result;\n    }\n\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        encodeComputeCommands(IComputeCommandEncoder** outEncoder) = 0;\n    inline IComputeCommandEncoder* encodeComputeCommands()\n    {\n        IComputeCommandEncoder* result;\n        encodeComputeCommands(&result);\n        return result;\n    }\n\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        encodeResourceCommands(IResourceCommandEncoder** outEncoder) = 0;\n    inline IResourceCommandEncoder* encodeResourceCommands()\n    {\n        IResourceCommandEncoder* result;\n        encodeResourceCommands(&result);\n        return result;\n    }\n\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) = 0;\n    inline IRayTracingCommandEncoder* encodeRayTracingCommands()\n    {\n        IRayTracingCommandEncoder* result;\n        encodeRayTracingCommands(&result);\n        return result;\n    }\n\n    virtual SLANG_NO_THROW void SLANG_MCALL close() = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0;\n};\n#define SLANG_UUID_ICommandBuffer                                                      \\\n    {                                                                                  \\\n        0x5d56063f, 0x91d4, 0x4723, { 0xa7, 0xa7, 0x7a, 0x15, 0xaf, 0x93, 0xeb, 0x48 } \\\n    }\n\nclass ICommandBufferD3D12 : public ICommandBuffer\n{\npublic:\n    virtual SLANG_NO_THROW void SLANG_MCALL invalidateDescriptorHeapBinding() = 0;\n    virtual SLANG_NO_THROW void SLANG_MCALL ensureInternalDescriptorHeapsBound() = 0;\n};\n#define SLANG_UUID_ICommandBufferD3D12                                                 \\\n    {                                                                                  \\\n        0xd56b7616, 0x6c14, 0x4841, { 0x9d, 0x9c, 0x7b, 0x7f, 0xdb, 0x9f, 0xd9, 0xb8 } \\\n    }\n\nclass ICommandQueue : public ISlangUnknown\n{\npublic:\n    enum class QueueType\n    {\n        Graphics\n    };\n    struct Desc\n    {\n        QueueType type;\n    };\n\n    // For D3D12, this is the pointer to the queue. For Vulkan, this is the queue itself.\n    typedef uint64_t NativeHandle;\n\n    virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0;\n\n    virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(\n        GfxCount count,\n        ICommandBuffer* const* commandBuffers,\n        IFence* fenceToSignal,\n        uint64_t newFenceValue) = 0;\n    inline void executeCommandBuffer(\n        ICommandBuffer* commandBuffer, IFence* fenceToSignal = nullptr, uint64_t newFenceValue = 0)\n    {\n        executeCommandBuffers(1, &commandBuffer, fenceToSignal, newFenceValue);\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0;\n\n    virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() = 0;\n\n    /// Queues a device side wait for the given fences.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        waitForFenceValuesOnDevice(GfxCount fenceCount, IFence** fences, uint64_t* waitValues) = 0;\n};\n#define SLANG_UUID_ICommandQueue                                                    \\\n    {                                                                               \\\n        0x14e2bed0, 0xad0, 0x4dc8, { 0xb3, 0x41, 0x6, 0x3f, 0xe7, 0x2d, 0xbf, 0xe } \\\n    }\n\nclass ITransientResourceHeap : public ISlangUnknown\n{\npublic:\n    struct Flags\n    {\n        enum Enum\n        {\n            None = 0,\n            AllowResizing = 0x1,\n        };\n    };\n    struct Desc\n    {\n        Flags::Enum flags;\n        Size constantBufferSize;\n        GfxCount samplerDescriptorCount;\n        GfxCount uavDescriptorCount;\n        GfxCount srvDescriptorCount;\n        GfxCount constantBufferDescriptorCount;\n        GfxCount accelerationStructureDescriptorCount;\n    };\n\n    // Waits until GPU commands issued before last call to `finish()` has been completed, and resets\n    // all transient resources holds by the heap.\n    // This method must be called before using the transient heap to issue new GPU commands.\n    // In most situations this method should be called at the beginning of each frame.\n    virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() = 0;\n\n    // Must be called when the application has done using this heap to issue commands. In most situations\n    // this method should be called at the end of each frame.\n    virtual SLANG_NO_THROW Result SLANG_MCALL finish() = 0;\n\n    // Command buffers are one-time use. Once it is submitted to the queue via\n    // `executeCommandBuffers` a command buffer is no longer valid to be used any more. Command\n    // buffers must be closed before submission. The current D3D12 implementation has a limitation\n    // that only one command buffer maybe recorded at a time. User must finish recording a command\n    // buffer before creating another command buffer.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createCommandBuffer(ICommandBuffer** outCommandBuffer) = 0;\n    inline ComPtr<ICommandBuffer> createCommandBuffer()\n    {\n        ComPtr<ICommandBuffer> result;\n        SLANG_RETURN_NULL_ON_FAIL(createCommandBuffer(result.writeRef()));\n        return result;\n    }\n};\n#define SLANG_UUID_ITransientResourceHeap                                             \\\n    {                                                                                 \\\n        0xcd48bd29, 0xee72, 0x41b8, { 0xbc, 0xff, 0xa, 0x2b, 0x3a, 0xaa, 0x6d, 0xeb } \\\n    }\n\nclass ITransientResourceHeapD3D12 : public ISlangUnknown\n{\npublic:\n    enum class DescriptorType\n    {\n        ResourceView, Sampler\n    };\n    virtual SLANG_NO_THROW Result SLANG_MCALL allocateTransientDescriptorTable(\n        DescriptorType type,\n        GfxCount count,\n        Offset& outDescriptorOffset,\n        void** outD3DDescriptorHeapHandle) = 0;\n};\n#define SLANG_UUID_ITransientResourceHeapD3D12                                             \\\n    {                                                                                  \\\n        0x9bc6a8bc, 0x5f7a, 0x454a, { 0x93, 0xef, 0x3b, 0x10, 0x5b, 0xb7, 0x63, 0x7e } \\\n    }\n\nclass ISwapchain : public ISlangUnknown\n{\npublic:\n    struct Desc\n    {\n        Format format;\n        GfxCount width, height;\n        GfxCount imageCount;\n        ICommandQueue* queue;\n        bool enableVSync;\n    };\n    virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0;\n\n    /// Returns the back buffer image at `index`.\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        getImage(GfxIndex index, ITextureResource** outResource) = 0;\n\n    /// Present the next image in the swapchain.\n    virtual SLANG_NO_THROW Result SLANG_MCALL present() = 0;\n\n    /// Returns the index of next back buffer image that will be presented in the next\n    /// `present` call. If the swapchain is invalid/out-of-date, this method returns -1.\n    virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() = 0;\n\n    /// Resizes the back buffers of this swapchain. All render target views and framebuffers\n    /// referencing the back buffer images must be freed before calling this method.\n    virtual SLANG_NO_THROW Result SLANG_MCALL resize(GfxCount width, GfxCount height) = 0;\n\n    // Check if the window is occluded.\n    virtual SLANG_NO_THROW bool SLANG_MCALL isOccluded() = 0;\n\n    // Toggle full screen mode.\n    virtual SLANG_NO_THROW Result SLANG_MCALL setFullScreenMode(bool mode) = 0;\n};\n#define SLANG_UUID_ISwapchain                                                        \\\n    {                                                                                \\\n        0xbe91ba6c, 0x784, 0x4308, { 0xa1, 0x0, 0x19, 0xc3, 0x66, 0x83, 0x44, 0xb2 } \\\n    }\n\n// These are exclusively used to track hit/miss counts for shader cache entries. Entry hit and\n// miss counts specifically indicate if the file containing relevant shader code was found in\n// the cache, while the general hit and miss counts indicate whether the file was both found and\n// up-to-date.\nclass IShaderCacheStatistics : public ISlangUnknown\n{\npublic:\n    virtual SLANG_NO_THROW GfxCount SLANG_MCALL getCacheMissCount() = 0;\n    virtual SLANG_NO_THROW GfxCount SLANG_MCALL getCacheHitCount() = 0;\n    virtual SLANG_NO_THROW GfxCount SLANG_MCALL getCacheEntryDirtyCount() = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL resetCacheStatistics() = 0;\n};\n\n#define SLANG_UUID_IShaderCacheStatistics                                                \\\n    {                                                                                    \\\n          0x8eccc8ec, 0x5c04, 0x4a51, { 0x99, 0x75, 0x13, 0xf8, 0xfe, 0xa1, 0x59, 0xf3 } \\\n    }\n\nstruct AdapterLUID\n{\n    uint8_t luid[16];\n\n    bool operator==(const AdapterLUID& other) const\n    {\n        for (int i = 0; i < sizeof(AdapterLUID::luid); ++i)\n            if (luid[i] != other.luid[i])\n                return false;\n        return true;\n    }\n    bool operator!=(const AdapterLUID& other) const\n    {\n        return !this->operator==(other);\n    }\n};\n\nstruct AdapterInfo\n{\n    // Descriptive name of the adapter.\n    char name[128];\n\n    // Unique identifier for the vendor (only available for D3D and Vulkan).\n    uint32_t vendorID;\n\n    // Unique identifier for the physical device among devices from the vendor (only available for D3D and Vulkan)\n    uint32_t deviceID;\n\n    // Logically unique identifier of the adapter.\n    AdapterLUID luid;\n};\n\nclass AdapterList\n{\npublic:\n    AdapterList(ISlangBlob* blob) : m_blob(blob) {}\n\n    const AdapterInfo* getAdapters() const\n    {\n        return reinterpret_cast<const AdapterInfo*>(m_blob ? m_blob->getBufferPointer() : nullptr);\n    }\n\n    GfxCount getCount() const\n    {\n        return (GfxCount)(m_blob ? m_blob->getBufferSize() / sizeof(AdapterInfo) : 0);\n    }\n\nprivate:\n    ComPtr<ISlangBlob> m_blob;\n};\n\nstruct DeviceLimits\n{\n    /// Maximum dimension for 1D textures.\n    uint32_t maxTextureDimension1D;\n    /// Maximum dimensions for 2D textures.\n    uint32_t maxTextureDimension2D;\n    /// Maximum dimensions for 3D textures.\n    uint32_t maxTextureDimension3D;\n    /// Maximum dimensions for cube textures.\n    uint32_t maxTextureDimensionCube;\n    /// Maximum number of texture layers.\n    uint32_t maxTextureArrayLayers;\n\n    /// Maximum number of vertex input elements in a graphics pipeline.\n    uint32_t maxVertexInputElements;\n    /// Maximum offset of a vertex input element in the vertex stream.\n    uint32_t maxVertexInputElementOffset;\n    /// Maximum number of vertex streams in a graphics pipeline.\n    uint32_t maxVertexStreams;\n    /// Maximum stride of a vertex stream.\n    uint32_t maxVertexStreamStride;\n\n    /// Maximum number of threads per thread group.\n    uint32_t maxComputeThreadsPerGroup;\n    /// Maximum dimensions of a thread group.\n    uint32_t maxComputeThreadGroupSize[3];\n    /// Maximum number of thread groups per dimension in a single dispatch.\n    uint32_t maxComputeDispatchThreadGroups[3];\n\n    /// Maximum number of viewports per pipeline.\n    uint32_t maxViewports;\n    /// Maximum viewport dimensions.\n    uint32_t maxViewportDimensions[2];\n    /// Maximum framebuffer dimensions.\n    uint32_t maxFramebufferDimensions[3];\n\n    /// Maximum samplers visible in a shader stage.\n    uint32_t maxShaderVisibleSamplers;\n};\n\nstruct DeviceInfo\n{\n    DeviceType deviceType;\n\n    DeviceLimits limits;\n\n    BindingStyle bindingStyle;\n\n    ProjectionStyle projectionStyle;\n\n    /// An projection matrix that ensures x, y mapping to pixels\n    /// is the same on all targets\n    float identityProjectionMatrix[16];\n\n    /// The name of the graphics API being used by this device.\n    const char* apiName = nullptr;\n\n    /// The name of the graphics adapter.\n    const char* adapterName = nullptr;\n\n    /// The clock frequency used in timestamp queries.\n    uint64_t timestampFrequency = 0;\n};\n\nenum class DebugMessageType\n{\n    Info, Warning, Error\n};\nenum class DebugMessageSource\n{\n    Layer, Driver, Slang\n};\nclass IDebugCallback\n{\npublic:\n    virtual SLANG_NO_THROW void SLANG_MCALL\n        handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) = 0;\n};\n\nclass IDevice : public ISlangUnknown\n{\npublic:\n    struct SlangDesc\n    {\n        slang::IGlobalSession* slangGlobalSession = nullptr; // (optional) A slang global session object. If null will create automatically.\n\n        SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR;\n\n        char const* const* searchPaths = nullptr;\n        GfxCount           searchPathCount = 0;\n\n        slang::PreprocessorMacroDesc const* preprocessorMacros = nullptr;\n        GfxCount                            preprocessorMacroCount = 0;\n\n        const char* targetProfile = nullptr; // (optional) Target shader profile. If null this will be set to platform dependent default.\n        SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT;\n        SlangOptimizationLevel optimizationLevel = SLANG_OPTIMIZATION_LEVEL_DEFAULT;\n        SlangTargetFlags targetFlags = 0;\n        SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT;\n    };\n\n    struct ShaderCacheDesc\n    {\n        // The filename for the file the cache's state should be saved to or loaded from.\n        const char* cacheFilename = \"cache.txt\";\n        // The root directory for the shader cache.\n        const char* shaderCachePath = nullptr;\n        // The file system for loading cached shader kernels. The layer does not maintain a strong reference to the object,\n        // instead the user is responsible for holding the object alive during the lifetime of an `IDevice`.\n        ISlangFileSystem* shaderCacheFileSystem = nullptr;\n        // The maximum number of entries stored in the cache. By default, there is no limit.\n        GfxCount entryCountLimit = 0;\n    };\n\n    struct InteropHandles\n    {\n        InteropHandle handles[3] = {};\n    };\n\n    struct Desc\n    {\n        // The underlying API/Platform of the device.\n        DeviceType deviceType = DeviceType::Default;\n        // The device's handles (if they exist) and their associated API. For D3D12, this contains a single InteropHandle\n        // for the ID3D12Device. For Vulkan, the first InteropHandle is the VkInstance, the second is the VkPhysicalDevice,\n        // and the third is the VkDevice. For CUDA, this only contains a single value for the CUDADevice.\n        InteropHandles existingDeviceHandles;\n        // LUID of the adapter to use. Use getGfxAdapters() to get a list of available adapters.\n        const AdapterLUID* adapterLUID = nullptr;\n        // Number of required features.\n        GfxCount requiredFeatureCount = 0;\n        // Array of required feature names, whose size is `requiredFeatureCount`.\n        const char** requiredFeatures = nullptr;\n        // A command dispatcher object that intercepts and handles actual low-level API call.\n        ISlangUnknown* apiCommandDispatcher = nullptr;\n        // The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required.\n        GfxIndex nvapiExtnSlot = -1;\n        // Configurations for the shader cache.\n        ShaderCacheDesc shaderCache = {};\n        // Configurations for Slang compiler.\n        SlangDesc slang = {};\n\n        GfxCount extendedDescCount = 0;\n        void** extendedDescs = nullptr;\n    };\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) = 0;\n\n    virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* feature) = 0;\n\n        /// Returns a list of features supported by the renderer.\n    virtual SLANG_NO_THROW Result SLANG_MCALL getFeatures(const char** outFeatures, Size bufferSize, GfxCount* outFeatureCount) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getSlangSession(slang::ISession** outSlangSession) = 0;\n\n    inline ComPtr<slang::ISession> getSlangSession()\n    {\n        ComPtr<slang::ISession> result;\n        getSlangSession(result.writeRef());\n        return result;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap(\n        const ITransientResourceHeap::Desc& desc,\n        ITransientResourceHeap** outHeap) = 0;\n    inline ComPtr<ITransientResourceHeap> createTransientResourceHeap(\n        const ITransientResourceHeap::Desc& desc)\n    {\n        ComPtr<ITransientResourceHeap> result;\n        createTransientResourceHeap(desc, result.writeRef());\n        return result;\n    }\n\n        /// Create a texture resource.\n        ///\n        /// If `initData` is non-null, then it must point to an array of\n        /// `ITextureResource::SubresourceData` with one element for each\n        /// subresource of the texture being created.\n        ///\n        /// The number of subresources in a texture is:\n        ///\n        ///     effectiveElementCount * mipLevelCount\n        ///\n        /// where the effective element count is computed as:\n        ///\n        ///     effectiveElementCount = (isArray ? arrayElementCount : 1) * (isCube ? 6 : 1);\n        ///\n    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(\n        const ITextureResource::Desc& desc,\n        const ITextureResource::SubresourceData* initData,\n        ITextureResource** outResource) = 0;\n\n        /// Create a texture resource. initData holds the initialize data to set the contents of the texture when constructed.\n    inline SLANG_NO_THROW ComPtr<ITextureResource> createTextureResource(\n        const ITextureResource::Desc& desc,\n        const ITextureResource::SubresourceData* initData = nullptr)\n    {\n        ComPtr<ITextureResource> resource;\n        SLANG_RETURN_NULL_ON_FAIL(createTextureResource(desc, initData, resource.writeRef()));\n        return resource;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromNativeHandle(\n        InteropHandle handle,\n        const ITextureResource::Desc& srcDesc,\n        ITextureResource** outResource) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle(\n        InteropHandle handle,\n        const ITextureResource::Desc& srcDesc,\n        const Size size,\n        ITextureResource** outResource) = 0;\n\n        /// Create a buffer resource\n    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource(\n        const IBufferResource::Desc& desc,\n        const void* initData,\n        IBufferResource** outResource) = 0;\n\n    inline SLANG_NO_THROW ComPtr<IBufferResource> createBufferResource(\n        const IBufferResource::Desc& desc,\n        const void* initData = nullptr)\n    {\n        ComPtr<IBufferResource> resource;\n        SLANG_RETURN_NULL_ON_FAIL(createBufferResource(desc, initData, resource.writeRef()));\n        return resource;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle(\n        InteropHandle handle,\n        const IBufferResource::Desc& srcDesc,\n        IBufferResource** outResource) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromSharedHandle(\n        InteropHandle handle,\n        const IBufferResource::Desc& srcDesc,\n        IBufferResource** outResource) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) = 0;\n\n    inline ComPtr<ISamplerState> createSamplerState(ISamplerState::Desc const& desc)\n    {\n        ComPtr<ISamplerState> sampler;\n        SLANG_RETURN_NULL_ON_FAIL(createSamplerState(desc, sampler.writeRef()));\n        return sampler;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView(\n        ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) = 0;\n\n    inline ComPtr<IResourceView> createTextureView(ITextureResource* texture, IResourceView::Desc const& desc)\n    {\n        ComPtr<IResourceView> view;\n        SLANG_RETURN_NULL_ON_FAIL(createTextureView(texture, desc, view.writeRef()));\n        return view;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView(\n        IBufferResource* buffer,\n        IBufferResource* counterBuffer,\n        IResourceView::Desc const& desc,\n        IResourceView** outView) = 0;\n\n    inline ComPtr<IResourceView> createBufferView(\n        IBufferResource* buffer, IBufferResource* counterBuffer, IResourceView::Desc const& desc)\n    {\n        ComPtr<IResourceView> view;\n        SLANG_RETURN_NULL_ON_FAIL(createBufferView(buffer, counterBuffer, desc, view.writeRef()));\n        return view;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createFramebufferLayout(IFramebufferLayout::Desc const& desc, IFramebufferLayout** outFrameBuffer) = 0;\n    inline ComPtr<IFramebufferLayout> createFramebufferLayout(IFramebufferLayout::Desc const& desc)\n    {\n        ComPtr<IFramebufferLayout> fb;\n        SLANG_RETURN_NULL_ON_FAIL(createFramebufferLayout(desc, fb.writeRef()));\n        return fb;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) = 0;\n    inline ComPtr<IFramebuffer> createFramebuffer(IFramebuffer::Desc const& desc)\n    {\n        ComPtr<IFramebuffer> fb;\n        SLANG_RETURN_NULL_ON_FAIL(createFramebuffer(desc, fb.writeRef()));\n        return fb;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createRenderPassLayout(\n        const IRenderPassLayout::Desc& desc,\n        IRenderPassLayout** outRenderPassLayout) = 0;\n    inline ComPtr<IRenderPassLayout> createRenderPassLayout(const IRenderPassLayout::Desc& desc)\n    {\n        ComPtr<IRenderPassLayout> rs;\n        SLANG_RETURN_NULL_ON_FAIL(createRenderPassLayout(desc, rs.writeRef()));\n        return rs;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(\n        ISwapchain::Desc const& desc, WindowHandle window, ISwapchain** outSwapchain) = 0;\n    inline ComPtr<ISwapchain> createSwapchain(ISwapchain::Desc const& desc, WindowHandle window)\n    {\n        ComPtr<ISwapchain> swapchain;\n        SLANG_RETURN_NULL_ON_FAIL(createSwapchain(desc, window, swapchain.writeRef()));\n        return swapchain;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout(\n        IInputLayout::Desc const& desc, IInputLayout** outLayout) = 0;\n\n    inline ComPtr<IInputLayout> createInputLayout(IInputLayout::Desc const& desc)\n    {\n        ComPtr<IInputLayout> layout;\n        SLANG_RETURN_NULL_ON_FAIL(createInputLayout(desc, layout.writeRef()));\n        return layout;\n    }\n\n    inline Result createInputLayout(Size vertexSize, InputElementDesc const* inputElements, GfxCount inputElementCount, IInputLayout** outLayout)\n    {\n        VertexStreamDesc streamDesc = { vertexSize, InputSlotClass::PerVertex, 0 };\n\n        IInputLayout::Desc inputLayoutDesc = {};\n        inputLayoutDesc.inputElementCount = inputElementCount;\n        inputLayoutDesc.inputElements = inputElements;\n        inputLayoutDesc.vertexStreamCount = 1;\n        inputLayoutDesc.vertexStreams = &streamDesc;\n        return createInputLayout(inputLayoutDesc, outLayout);\n    }\n\n    inline ComPtr<IInputLayout> createInputLayout(Size vertexSize, InputElementDesc const* inputElements, GfxCount inputElementCount)\n    {\n        ComPtr<IInputLayout> layout;\n        SLANG_RETURN_NULL_ON_FAIL(createInputLayout(vertexSize, inputElements, inputElementCount, layout.writeRef()));\n        return layout;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) = 0;\n    inline ComPtr<ICommandQueue> createCommandQueue(const ICommandQueue::Desc& desc)\n    {\n        ComPtr<ICommandQueue> queue;\n        SLANG_RETURN_NULL_ON_FAIL(createCommandQueue(desc, queue.writeRef()));\n        return queue;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject(\n        slang::TypeReflection* type,\n        ShaderObjectContainerType container,\n        IShaderObject** outObject) = 0;\n\n    inline ComPtr<IShaderObject> createShaderObject(slang::TypeReflection* type)\n    {\n        ComPtr<IShaderObject> object;\n        SLANG_RETURN_NULL_ON_FAIL(createShaderObject(type, ShaderObjectContainerType::None, object.writeRef()));\n        return object;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObject(\n        slang::TypeReflection* type,\n        ShaderObjectContainerType container,\n        IShaderObject** outObject) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectFromTypeLayout(\n        slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObjectFromTypeLayout(\n        slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createMutableRootShaderObject(\n        IShaderProgram* program,\n        IShaderObject** outObject) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outTable) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createProgram(\n        const IShaderProgram::Desc& desc,\n        IShaderProgram** outProgram,\n        ISlangBlob** outDiagnosticBlob = nullptr) = 0;\n\n    inline ComPtr<IShaderProgram> createProgram(const IShaderProgram::Desc& desc)\n    {\n        ComPtr<IShaderProgram> program;\n        SLANG_RETURN_NULL_ON_FAIL(createProgram(desc, program.writeRef()));\n        return program;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createProgram2(\n        const IShaderProgram::CreateDesc2& createDesc,\n        IShaderProgram** outProgram,\n        ISlangBlob** outDiagnosticBlob = nullptr) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState(\n        const GraphicsPipelineStateDesc&    desc,\n        IPipelineState**                    outState) = 0;\n\n    inline ComPtr<IPipelineState> createGraphicsPipelineState(\n        const GraphicsPipelineStateDesc& desc)\n    {\n        ComPtr<IPipelineState> state;\n        SLANG_RETURN_NULL_ON_FAIL(createGraphicsPipelineState(desc, state.writeRef()));\n        return state;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(\n        const ComputePipelineStateDesc&    desc,\n        IPipelineState**                     outState) = 0;\n\n    inline ComPtr<IPipelineState> createComputePipelineState(\n        const ComputePipelineStateDesc& desc)\n    {\n        ComPtr<IPipelineState> state;\n        SLANG_RETURN_NULL_ON_FAIL(createComputePipelineState(desc, state.writeRef()));\n        return state;\n    }\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipelineState(\n        const RayTracingPipelineStateDesc& desc, IPipelineState** outState) = 0;\n\n        /// Read back texture resource and stores the result in `outBlob`.\n    virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(\n        ITextureResource* resource,\n        ResourceState state,\n        ISlangBlob** outBlob,\n        Size* outRowPitch,\n        Size* outPixelSize) = 0;\n\n    virtual SLANG_NO_THROW SlangResult SLANG_MCALL readBufferResource(\n        IBufferResource* buffer,\n        Offset offset,\n        Size size,\n        ISlangBlob** outBlob) = 0;\n\n        /// Get the type of this renderer\n    virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool(\n        const IQueryPool::Desc& desc, IQueryPool** outPool) = 0;\n\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo(\n        const IAccelerationStructure::BuildInputs& buildInputs,\n        IAccelerationStructure::PrebuildInfo* outPrebuildInfo) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL createAccelerationStructure(\n        const IAccelerationStructure::CreateDesc& desc,\n        IAccelerationStructure** outView) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        createFence(const IFence::Desc& desc, IFence** outFence) = 0;\n\n    /// Wait on the host for the fences to signals.\n    /// `timeout` is in nanoseconds, can be set to `kTimeoutInfinite`.\n    virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences(\n        GfxCount fenceCount,\n        IFence** fences,\n        uint64_t* values,\n        bool waitForAll,\n        uint64_t timeout) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo(\n        const ITextureResource::Desc& desc, Size* outSize, Size* outAlignment) = 0;\n\n    virtual SLANG_NO_THROW Result SLANG_MCALL getTextureRowAlignment(Size* outAlignment) = 0;\n};\n\n#define SLANG_UUID_IDevice                                                               \\\n    {                                                                                    \\\n          0x715bdf26, 0x5135, 0x11eb, { 0xAE, 0x93, 0x02, 0x42, 0xAC, 0x13, 0x00, 0x02 } \\\n    }\n\nclass IPipelineCreationAPIDispatcher : public ISlangUnknown\n{\npublic:\n    virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(\n        IDevice* device,\n        slang::IComponentType* program,\n        void* pipelineDesc,\n        void** outPipelineState) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState(\n        IDevice* device,\n        slang::IComponentType* program,\n        void* pipelineDesc,\n        void** outPipelineState) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        beforeCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0;\n    virtual SLANG_NO_THROW Result SLANG_MCALL\n        afterCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0;\n};\n#define SLANG_UUID_IPipelineCreationAPIDispatcher                                     \\\n    {                                                                                 \\\n        0xc3d5f782, 0xeae1, 0x4da6, { 0xab, 0x40, 0x75, 0x32, 0x31, 0x2, 0xb7, 0xdc } \\\n    }\n\n\n// Global public functions\n\nextern \"C\"\n{\n    /// Checks if format is compressed\n    SLANG_GFX_API bool SLANG_MCALL gfxIsCompressedFormat(Format format);\n\n    /// Checks if format is typeless\n    SLANG_GFX_API bool SLANG_MCALL gfxIsTypelessFormat(Format format);\n\n    /// Gets information about the format\n    SLANG_GFX_API SlangResult SLANG_MCALL gfxGetFormatInfo(Format format, FormatInfo* outInfo);\n\n    /// Gets a list of available adapters for a given device type\n    SLANG_GFX_API SlangResult SLANG_MCALL gfxGetAdapters(DeviceType type, ISlangBlob** outAdaptersBlob);\n\n    /// Given a type returns a function that can construct it, or nullptr if there isn't one\n    SLANG_GFX_API SlangResult SLANG_MCALL\n        gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice);\n\n    /// Sets a callback for receiving debug messages.\n    /// The layer does not hold a strong reference to the callback object.\n    /// The user is responsible for holding the callback object alive.\n    SLANG_GFX_API SlangResult SLANG_MCALL\n        gfxSetDebugCallback(IDebugCallback* callback);\n\n    /// Enables debug layer. The debug layer will check all `gfx` calls and verify that uses are valid.\n    SLANG_GFX_API void SLANG_MCALL gfxEnableDebugLayer();\n\n    SLANG_GFX_API const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type);\n}\n\n/// Gets a list of available adapters for a given device type\ninline AdapterList gfxGetAdapters(DeviceType type)\n{\n    ComPtr<ISlangBlob> blob;\n    gfxGetAdapters(type, blob.writeRef());\n    return AdapterList(blob);\n}\n\n// Extended descs.\nstruct D3D12ExperimentalFeaturesDesc\n{\n    StructType structType = StructType::D3D12ExperimentalFeaturesDesc;\n    uint32_t numFeatures;\n    const void* featureIIDs;\n    void* configurationStructs;\n    uint32_t* configurationStructSizes;\n};\n\nstruct D3D12DeviceExtendedDesc\n{\n    StructType structType = StructType::D3D12DeviceExtendedDesc;\n    const char* rootParameterShaderAttributeName = nullptr;\n    bool debugBreakOnD3D12Error = false;\n    uint32_t highestShaderModel = 0;\n};\n\n}\n"
  },
  {
    "path": "Source/External/slang/slang-tag-version.h",
    "content": "#define SLANG_TAG_VERSION \"v0.24.45\" \n"
  },
  {
    "path": "Source/External/slang/slang.h",
    "content": "#ifndef SLANG_H\n#define SLANG_H\n\n/** \\file slang.h\n\nThe Slang API provides services to compile, reflect, and specialize code\nwritten in the Slang shading language.\n*/\n\n/*\nThe following section attempts to detect the compiler and version in use.\n\nIf an application defines `SLANG_COMPILER` before including this header,\nthey take responsibility for setting any compiler-dependent macros\nused later in the file.\n\nMost applications should not need to touch this section.\n*/\n#ifndef SLANG_COMPILER\n#    define SLANG_COMPILER\n\n/*\nCompiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/\nNOTE that SLANG_VC holds the compiler version - not just 1 or 0\n*/\n#    if defined(_MSC_VER)\n#        if _MSC_VER >= 1900\n#            define SLANG_VC 14\n#        elif _MSC_VER >= 1800\n#            define SLANG_VC 12\n#        elif _MSC_VER >= 1700\n#            define SLANG_VC 11\n#        elif _MSC_VER >= 1600\n#            define SLANG_VC 10\n#        elif _MSC_VER >= 1500\n#            define SLANG_VC 9\n#        else\n#            error \"unknown version of Visual C++ compiler\"\n#        endif\n#    elif defined(__clang__)\n#        define SLANG_CLANG 1\n#    elif defined(__SNC__)\n#        define SLANG_SNC 1\n#    elif defined(__ghs__)\n#        define SLANG_GHS 1\n#    elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */\n#        define SLANG_GCC 1\n#    else\n#        error \"unknown compiler\"\n#    endif\n/*\nAny compilers not detected by the above logic are now now explicitly zeroed out.\n*/\n#    ifndef SLANG_VC\n#        define SLANG_VC 0\n#    endif\n#    ifndef SLANG_CLANG\n#        define SLANG_CLANG 0\n#    endif\n#    ifndef SLANG_SNC\n#        define SLANG_SNC 0\n#    endif\n#    ifndef SLANG_GHS\n#        define SLANG_GHS 0\n#    endif\n#    ifndef SLANG_GCC\n#        define SLANG_GCC 0\n#    endif\n#endif /* SLANG_COMPILER */\n\n/*\nThe following section attempts to detect the target platform being compiled for.\n\nIf an application defines `SLANG_PLATFORM` before including this header,\nthey take responsibility for setting any compiler-dependent macros\nused later in the file.\n\nMost applications should not need to touch this section.\n*/\n#ifndef SLANG_PLATFORM\n#    define SLANG_PLATFORM\n/**\nOperating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/\n*/\n#    if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP\n#        define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */\n#    elif defined(XBOXONE)\n#        define SLANG_XBOXONE 1\n#    elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */\n#        define SLANG_WIN64 1\n#    elif defined(_M_PPC)\n#        define SLANG_X360 1\n#    elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */\n#        define SLANG_WIN32 1\n#    elif defined(__ANDROID__)\n#        define SLANG_ANDROID 1\n#    elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */\n#        define SLANG_LINUX 1\n#    elif defined(__APPLE__)\n#        include \"TargetConditionals.h\"\n#        if TARGET_OS_MAC\n#            define SLANG_OSX 1\n#        else\n#            define SLANG_IOS 1\n#        endif\n#    elif defined(__CELLOS_LV2__)\n#        define SLANG_PS3 1\n#    elif defined(__ORBIS__)\n#        define SLANG_PS4 1\n#    elif defined(__SNC__) && defined(__arm__)\n#        define SLANG_PSP2 1\n#    elif defined(__ghs__)\n#        define SLANG_WIIU 1\n#    else\n#        error \"unknown target platform\"\n#    endif\n/*\nAny platforms not detected by the above logic are now now explicitly zeroed out.\n*/\n#    ifndef SLANG_WINRT\n#        define SLANG_WINRT 0\n#    endif\n#    ifndef SLANG_XBOXONE\n#        define SLANG_XBOXONE 0\n#    endif\n#    ifndef SLANG_WIN64\n#        define SLANG_WIN64 0\n#    endif\n#    ifndef SLANG_X360\n#        define SLANG_X360 0\n#    endif\n#    ifndef SLANG_WIN32\n#        define SLANG_WIN32 0\n#    endif\n#    ifndef SLANG_ANDROID\n#        define SLANG_ANDROID 0\n#    endif\n#    ifndef SLANG_LINUX\n#        define SLANG_LINUX 0\n#    endif\n#    ifndef SLANG_IOS\n#        define SLANG_IOS 0\n#    endif\n#    ifndef SLANG_OSX\n#        define SLANG_OSX 0\n#    endif\n#    ifndef SLANG_PS3\n#        define SLANG_PS3 0\n#    endif\n#    ifndef SLANG_PS4\n#        define SLANG_PS4 0\n#    endif\n#    ifndef SLANG_PSP2\n#        define SLANG_PSP2 0\n#    endif\n#    ifndef SLANG_WIIU\n#        define SLANG_WIIU 0\n#    endif\n#endif /* SLANG_PLATFORM */\n\n/* Shorthands for \"families\" of compilers/platforms */\n#define SLANG_GCC_FAMILY (SLANG_CLANG || SLANG_SNC || SLANG_GHS || SLANG_GCC)\n#define SLANG_WINDOWS_FAMILY (SLANG_WINRT || SLANG_WIN32 || SLANG_WIN64)\n#define SLANG_MICROSOFT_FAMILY (SLANG_XBOXONE || SLANG_X360 || SLANG_WINDOWS_FAMILY)\n#define SLANG_LINUX_FAMILY (SLANG_LINUX || SLANG_ANDROID)\n#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX)                  /* equivalent to #if __APPLE__ */\n#define SLANG_UNIX_FAMILY (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */\n\n/* Macro for declaring if a method is no throw. Should be set before the return parameter. */\n#ifndef SLANG_NO_THROW\n#   if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS)\n#       define SLANG_NO_THROW __declspec(nothrow)\n#   endif\n#endif\n#ifndef SLANG_NO_THROW\n#   define SLANG_NO_THROW\n#endif\n\n/* The `SLANG_STDCALL` and `SLANG_MCALL` defines are used to set the calling\nconvention for interface methods.\n*/\n#ifndef SLANG_STDCALL\n#   if SLANG_MICROSOFT_FAMILY\n#       define SLANG_STDCALL __stdcall\n#   else\n#       define SLANG_STDCALL\n#   endif\n#endif\n#ifndef SLANG_MCALL\n#   define SLANG_MCALL SLANG_STDCALL\n#endif\n\n\n#if !defined(SLANG_STATIC) && !defined(SLANG_STATIC)\n    #define SLANG_DYNAMIC\n#endif\n\n#if defined(_MSC_VER)\n#   define SLANG_DLL_EXPORT __declspec(dllexport)\n#else\n#   if 0 && __GNUC__ >= 4\n// Didn't work on latest gcc on linux.. so disable for now\n// https://gcc.gnu.org/wiki/Visibility\n#       define SLANG_DLL_EXPORT __attribute__ ((dllexport))\n#   else\n#       define SLANG_DLL_EXPORT __attribute__((__visibility__(\"default\")))\n#   endif\n#endif\n\n#if defined(SLANG_DYNAMIC)\n#   if defined(_MSC_VER)\n#       ifdef SLANG_DYNAMIC_EXPORT\n#           define SLANG_API SLANG_DLL_EXPORT\n#       else\n#           define SLANG_API __declspec(dllimport)\n#       endif\n#   else\n        // TODO: need to consider compiler capabilities\n//#     ifdef SLANG_DYNAMIC_EXPORT\n#       define SLANG_API SLANG_DLL_EXPORT \n//#     endif\n#   endif\n#endif\n\n#ifndef SLANG_API\n#   define SLANG_API\n#endif\n\n// GCC Specific\n#if SLANG_GCC_FAMILY\n// This doesn't work on clang - because the typedef is seen as multiply defined, use the line numbered version defined later\n#\tif !defined(__clang__) && (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__ORBIS__))\n#\t\tdefine SLANG_COMPILE_TIME_ASSERT(exp) typedef char SlangCompileTimeAssert_Dummy[(exp) ? 1 : -1] __attribute__((unused))\n#\tendif\n\n#\tdefine SLANG_NO_INLINE __attribute__((noinline))\n#\tdefine SLANG_FORCE_INLINE inline __attribute__((always_inline))\n#   define SLANG_BREAKPOINT(id) __builtin_trap();\n#\tdefine SLANG_ALIGN_OF(T)\t__alignof__(T)\n\n// Use this macro instead of offsetof, because gcc produces warning if offsetof is used on a \n// non POD type, even though it produces the correct result\n#   define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1)\n#endif // SLANG_GCC_FAMILY\n\n// Microsoft VC specific\n#if SLANG_MICROSOFT_FAMILY\n#\tdefine SLANG_NO_INLINE __declspec(noinline)\n#\tdefine SLANG_FORCE_INLINE __forceinline\n#\tdefine SLANG_BREAKPOINT(id) __debugbreak();\n#\tdefine SLANG_ALIGN_OF(T) __alignof(T)\n\n#   define SLANG_INT64(x) (x##i64)\n#   define SLANG_UINT64(x) (x##ui64)\n#endif // SLANG_MICROSOFT_FAMILY\n\n#ifndef SLANG_FORCE_INLINE\n#\tdefine SLANG_FORCE_INLINE inline\n#endif\n#ifndef SLANG_NO_INLINE\n#\tdefine SLANG_NO_INLINE\n#endif\n\n#ifndef SLANG_COMPILE_TIME_ASSERT\n#\tdefine SLANG_COMPILE_TIME_ASSERT(exp) typedef char SLANG_CONCAT(SlangCompileTimeAssert,__LINE__)[(exp) ? 1 : -1]\n#endif\n\n#ifndef SLANG_OFFSET_OF\n#\tdefine SLANG_OFFSET_OF(X, Y) offsetof(X, Y)\n#endif\n\n#ifndef SLANG_BREAKPOINT\n// Make it crash with a write to 0!\n#   define SLANG_BREAKPOINT(id) (*((int*)0) = int(id));\n#endif\n\n// Use for getting the amount of members of a standard C array.\n#define SLANG_COUNT_OF(x) (sizeof(x)/sizeof(x[0]))\n/// SLANG_INLINE exists to have a way to inline consistent with SLANG_ALWAYS_INLINE\n#define SLANG_INLINE inline\n\n// If explicilty disabled and not set, set to not available\n#if !defined(SLANG_HAS_EXCEPTIONS) && defined(SLANG_DISABLE_EXCEPTIONS)\n#   define SLANG_HAS_EXCEPTIONS 0\n#endif\n\n// If not set, the default is exceptions are available\n#ifndef SLANG_HAS_EXCEPTIONS\n#   define SLANG_HAS_EXCEPTIONS 1\n#endif\n\n// Other defines\n#define SLANG_STRINGIZE_HELPER(X) #X\n#define SLANG_STRINGIZE(X) SLANG_STRINGIZE_HELPER(X)\n\n#define SLANG_CONCAT_HELPER(X, Y) X##Y\n#define SLANG_CONCAT(X, Y) SLANG_CONCAT_HELPER(X, Y)\n\n#ifndef SLANG_UNUSED\n#\tdefine SLANG_UNUSED(v) (void)v;\n#endif\n\n// Used for doing constant literals\n#ifndef SLANG_INT64\n#\tdefine SLANG_INT64(x) (x##ll)\n#endif\n#ifndef SLANG_UINT64\n#\tdefine SLANG_UINT64(x) (x##ull)\n#endif\n\n\n#ifdef __cplusplus\n#   define SLANG_EXTERN_C extern \"C\"\n#else\n#   define SLANG_EXTERN_C\n#endif\n\n#ifdef __cplusplus\n// C++ specific macros\n// Clang\n#if SLANG_CLANG\n#    if (__clang_major__*10 + __clang_minor__) >= 33\n#       define SLANG_HAS_MOVE_SEMANTICS 1\n#       define SLANG_HAS_ENUM_CLASS 1\n#       define SLANG_OVERRIDE override\n#    endif\n\n// Gcc\n#elif SLANG_GCC_FAMILY\n// Check for C++11\n#\t\tif (__cplusplus >= 201103L)\n#\t\t\tif (__GNUC__ * 100 + __GNUC_MINOR__) >= 405\n#\t\t\t\tdefine SLANG_HAS_MOVE_SEMANTICS 1\n#\t\t\tendif\n#\t\t\tif (__GNUC__ * 100 + __GNUC_MINOR__) >= 406\n#\t\t\t\tdefine SLANG_HAS_ENUM_CLASS 1\n#\t\t\tendif\n#\t\t\tif (__GNUC__ * 100 + __GNUC_MINOR__) >= 407\n#\t\t\t\tdefine SLANG_OVERRIDE override\n#\t\t\tendif\n#\t\tendif\n\n// TODO(JS): Not used in previous code. Left here as may be useful on some other version. \n// #define SLANG_RETURN_NEVER __attribute__((__noreturn__))\n\n#       define SLANG_RETURN_NEVER [[noreturn]]\n\n#\tendif // SLANG_GCC_FAMILY\n\n// Visual Studio\n\n#\tif SLANG_VC\n// C4481: nonstandard extension used: override specifier 'override'\n#\t\tif _MSC_VER < 1700\n#\t\t\tpragma warning(disable : 4481)\n#\t\tendif\n#\t\tdefine SLANG_OVERRIDE\toverride\n#\t\tif _MSC_VER >= 1600\n#\t\t\tdefine SLANG_HAS_MOVE_SEMANTICS 1\n#\t\tendif\n#\t    if _MSC_VER >= 1700\n#\t\t    define SLANG_HAS_ENUM_CLASS 1\n#       endif\n\n#   define SLANG_RETURN_NEVER __declspec(noreturn)\n\n#   endif // SLANG_VC\n\n// Set non set\n#   ifndef SLANG_OVERRIDE\n#\t    define SLANG_OVERRIDE\n#   endif\n#   ifndef SLANG_HAS_ENUM_CLASS\n#\t    define SLANG_HAS_ENUM_CLASS 0\n#   endif\n#   ifndef SLANG_HAS_MOVE_SEMANTICS\n#\t    define SLANG_HAS_MOVE_SEMANTICS 0\n#   endif\n\n#endif // __cplusplus\n\n#ifndef SLANG_RETURN_NEVER\n#   define SLANG_RETURN_NEVER [[noreturn]]\n#endif // SLANG_RETURN_NEVER\n\n/* Macros for detecting processor */\n#if defined(_M_ARM) || defined(__ARM_EABI__)\n// This is special case for nVidia tegra\n#   define SLANG_PROCESSOR_ARM 1\n#elif defined(__i386__) || defined(_M_IX86)\n#   define SLANG_PROCESSOR_X86 1\n#elif defined(_M_AMD64) || defined(_M_X64) || defined(__amd64) || defined(__x86_64)\n#   define SLANG_PROCESSOR_X86_64 1\n#elif defined(_PPC_) || defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC)\n#   if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(__64BIT__) || defined(_LP64) || defined(__LP64__)\n#       define SLANG_PROCESSOR_POWER_PC_64 1\n#   else\n#       define SLANG_PROCESSOR_POWER_PC 1\n#   endif\n#elif defined(__arm__)\n#   define SLANG_PROCESSOR_ARM 1\n#elif defined(_M_ARM64) || defined(__aarch64__)\n#   define SLANG_PROCESSOR_ARM_64 1\n#endif \n\n#ifndef SLANG_PROCESSOR_ARM\n#   define SLANG_PROCESSOR_ARM 0\n#endif\n\n#ifndef SLANG_PROCESSOR_ARM_64\n#   define SLANG_PROCESSOR_ARM_64 0\n#endif\n\n#ifndef SLANG_PROCESSOR_X86\n#   define SLANG_PROCESSOR_X86 0\n#endif\n\n#ifndef SLANG_PROCESSOR_X86_64\n#   define SLANG_PROCESSOR_X86_64 0\n#endif\n\n#ifndef SLANG_PROCESSOR_POWER_PC\n#   define SLANG_PROCESSOR_POWER_PC 0\n#endif\n\n#ifndef SLANG_PROCESSOR_POWER_PC_64\n#   define SLANG_PROCESSOR_POWER_PC_64 0\n#endif\n\n// Processor families\n\n#define SLANG_PROCESSOR_FAMILY_X86 (SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_X86)\n#define SLANG_PROCESSOR_FAMILY_ARM (SLANG_PROCESSOR_ARM | SLANG_PROCESSOR_ARM_64)\n#define SLANG_PROCESSOR_FAMILY_POWER_PC (SLANG_PROCESSOR_POWER_PC_64 | SLANG_PROCESSOR_POWER_PC)\n\n// Pointer size\n#define SLANG_PTR_IS_64 (SLANG_PROCESSOR_ARM_64 | SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_POWER_PC_64)\n#define SLANG_PTR_IS_32 (SLANG_PTR_IS_64 ^ 1)\n\n// Processor features\n#if SLANG_PROCESSOR_FAMILY_X86\n#   define SLANG_LITTLE_ENDIAN 1\n#   define SLANG_UNALIGNED_ACCESS 1\n#elif SLANG_PROCESSOR_FAMILY_ARM\n#   if defined(__ARMEB__)\n#       define SLANG_BIG_ENDIAN 1\n#   else\n#       define SLANG_LITTLE_ENDIAN 1\n#   endif\n#elif SLANG_PROCESSOR_FAMILY_POWER_PC\n#       define SLANG_BIG_ENDIAN 1\n#endif\n\n#ifndef SLANG_LITTLE_ENDIAN\n#   define SLANG_LITTLE_ENDIAN 0\n#endif\n\n#ifndef SLANG_BIG_ENDIAN\n#   define SLANG_BIG_ENDIAN 0\n#endif\n\n#ifndef SLANG_UNALIGNED_ACCESS\n#   define SLANG_UNALIGNED_ACCESS 0\n#endif\n\n// One endianess must be set\n#if ((SLANG_BIG_ENDIAN | SLANG_LITTLE_ENDIAN) == 0)\n#   error \"Couldn't determine endianess\"\n#endif\n\n#ifndef  SLANG_NO_INTTYPES\n#include <inttypes.h>\n#endif // ! SLANG_NO_INTTYPES\n\n#ifndef  SLANG_NO_STDDEF\n#include <stddef.h>\n#endif // ! SLANG_NO_STDDEF\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n    /*!\n    @mainpage Introduction\n\n    API Reference: slang.h\n\n    @file slang.h\n    */\n\n    typedef uint32_t    SlangUInt32;\n    typedef int32_t     SlangInt32;\n\n    // Use SLANG_PTR_ macros to determine SlangInt/SlangUInt types.\n    // This is used over say using size_t/ptrdiff_t/intptr_t/uintptr_t, because on some targets, these types are distinct from\n    // their uint_t/int_t equivalents and so produce ambiguity with function overloading.\n    //\n    // SlangSizeT is helpful as on some compilers size_t is distinct from a regular integer type and so overloading doesn't work.\n    // Casting to SlangSizeT works around this.\n#if SLANG_PTR_IS_64\n    typedef int64_t    SlangInt;\n    typedef uint64_t   SlangUInt;\n\n    typedef uint64_t   SlangSizeT;\n#else\n    typedef int32_t    SlangInt;\n    typedef uint32_t   SlangUInt;\n\n    typedef uint32_t   SlangSizeT;\n#endif\n\n    typedef bool SlangBool;\n\n    \n    /*!\n    @brief Severity of a diagnostic generated by the compiler.\n    Values come from the enum below, with higher values representing more severe\n    conditions, and all values >= SLANG_SEVERITY_ERROR indicating compilation\n    failure.\n    */\n    typedef int SlangSeverityIntegral;\n    enum SlangSeverity : SlangSeverityIntegral\n    {\n        SLANG_SEVERITY_DISABLED = 0, /**< A message that is disabled, filtered out. */\n        SLANG_SEVERITY_NOTE,         /**< An informative message. */\n        SLANG_SEVERITY_WARNING,      /**< A warning, which indicates a possible proble. */\n        SLANG_SEVERITY_ERROR,        /**< An error, indicating that compilation failed. */\n        SLANG_SEVERITY_FATAL,        /**< An unrecoverable error, which forced compilation to abort. */\n        SLANG_SEVERITY_INTERNAL,     /**< An internal error, indicating a logic error in the compiler. */\n    };\n\n    typedef int SlangDiagnosticFlags;\n    enum\n    {\n        SLANG_DIAGNOSTIC_FLAG_VERBOSE_PATHS = 0x01,\n        SLANG_DIAGNOSTIC_FLAG_TREAT_WARNINGS_AS_ERRORS = 0x02\n    };\n\n    typedef int SlangBindableResourceIntegral;\n    enum SlangBindableResourceType : SlangBindableResourceIntegral\n    {\n        SLANG_NON_BINDABLE = 0,\n        SLANG_TEXTURE,\n        SLANG_SAMPLER,\n        SLANG_UNIFORM_BUFFER,\n        SLANG_STORAGE_BUFFER,\n    };\n\n    typedef int SlangCompileTargetIntegral;\n    enum SlangCompileTarget : SlangCompileTargetIntegral\n    {\n        SLANG_TARGET_UNKNOWN,\n        SLANG_TARGET_NONE,\n        SLANG_GLSL,\n        SLANG_GLSL_VULKAN,          //< deprecated: just use `SLANG_GLSL`\n        SLANG_GLSL_VULKAN_ONE_DESC, //< deprecated\n        SLANG_HLSL,\n        SLANG_SPIRV,\n        SLANG_SPIRV_ASM,\n        SLANG_DXBC,\n        SLANG_DXBC_ASM,\n        SLANG_DXIL,\n        SLANG_DXIL_ASM,\n        SLANG_C_SOURCE,             ///< The C language\n        SLANG_CPP_SOURCE,           ///< C++ code for shader kernels.\n        SLANG_HOST_EXECUTABLE,           ///<  Standalone binary executable (for hosting CPU/OS)\n        SLANG_SHADER_SHARED_LIBRARY,     ///< A shared library/Dll for shader kernels (for hosting CPU/OS)\n        SLANG_SHADER_HOST_CALLABLE,      ///< A CPU target that makes the compiled shader code available to be run immediately\n        SLANG_CUDA_SOURCE,          ///< Cuda source\n        SLANG_PTX,                  ///< PTX\n        SLANG_OBJECT_CODE,          ///< Object code that can be used for later linking\n        SLANG_HOST_CPP_SOURCE,      ///< C++ code for host library or executable.\n        SLANG_HOST_HOST_CALLABLE,   ///< \n        SLANG_TARGET_COUNT_OF,\n    };\n\n    /* A \"container format\" describes the way that the outputs\n    for multiple files, entry points, targets, etc. should be\n    combined into a single artifact for output. */\n    typedef int SlangContainerFormatIntegral;\n    enum SlangContainerFormat : SlangContainerFormatIntegral\n    {\n        /* Don't generate a container. */\n        SLANG_CONTAINER_FORMAT_NONE,\n\n        /* Generate a container in the `.slang-module` format,\n        which includes reflection information, compiled kernels, etc. */\n        SLANG_CONTAINER_FORMAT_SLANG_MODULE,\n    };\n\n    typedef int SlangPassThroughIntegral;\n    enum SlangPassThrough : SlangPassThroughIntegral\n    {\n        SLANG_PASS_THROUGH_NONE,\n        SLANG_PASS_THROUGH_FXC,\n        SLANG_PASS_THROUGH_DXC,\n        SLANG_PASS_THROUGH_GLSLANG,\n        SLANG_PASS_THROUGH_CLANG,                   ///< Clang C/C++ compiler \n        SLANG_PASS_THROUGH_VISUAL_STUDIO,           ///< Visual studio C/C++ compiler\n        SLANG_PASS_THROUGH_GCC,                     ///< GCC C/C++ compiler\n        SLANG_PASS_THROUGH_GENERIC_C_CPP,           ///< Generic C or C++ compiler, which is decided by the source type\n        SLANG_PASS_THROUGH_NVRTC,                   ///< NVRTC Cuda compiler\n        SLANG_PASS_THROUGH_LLVM,                    ///< LLVM 'compiler' - includes LLVM and Clang\n        SLANG_PASS_THROUGH_COUNT_OF,\n    };\n\n    /* Defines an archive type used to holds a 'file system' type structure. */\n    typedef int SlangArchiveTypeIntegral;\n    enum SlangArchiveType : SlangArchiveTypeIntegral\n    {\n        SLANG_ARCHIVE_TYPE_UNDEFINED,\n        SLANG_ARCHIVE_TYPE_ZIP,\n        SLANG_ARCHIVE_TYPE_RIFF,                ///< Riff container with no compression\n        SLANG_ARCHIVE_TYPE_RIFF_DEFLATE,\n        SLANG_ARCHIVE_TYPE_RIFF_LZ4,\n        SLANG_ARCHIVE_TYPE_COUNT_OF,\n    };\n\n    /*!\n    Flags to control compilation behavior.\n    */\n    typedef unsigned int SlangCompileFlags;\n    enum\n    {\n        /* Do as little mangling of names as possible, to try to preserve original names */\n        SLANG_COMPILE_FLAG_NO_MANGLING          = 1 << 3,\n\n        /* Skip code generation step, just check the code and generate layout */\n        SLANG_COMPILE_FLAG_NO_CODEGEN           = 1 << 4,\n\n        /* Obfuscate shader names on release products */\n        SLANG_COMPILE_FLAG_OBFUSCATE = 1 << 5,\n\n        /* Deprecated flags: kept around to allow existing applications to\n        compile. Note that the relevant features will still be left in\n        their default state. */\n        SLANG_COMPILE_FLAG_NO_CHECKING          = 0,\n        SLANG_COMPILE_FLAG_SPLIT_MIXED_TYPES    = 0,\n    };\n\n    /*!\n    @brief Flags to control code generation behavior of a compilation target */\n    typedef unsigned int SlangTargetFlags;\n    enum \n    {\n        /* When compiling for a D3D Shader Model 5.1 or higher target, allocate\n           distinct register spaces for parameter blocks.\n\n           @deprecated This behavior is now enabled unconditionally.\n        */\n        SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES = 1 << 4,\n\n        /* When set, will generate target code that contains all entrypoints defined\n           in the input source or specified via the `spAddEntryPoint` function in a\n           single output module (library/source file).\n        */\n        SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM = 1 << 8,\n\n        /* When set, will dump out the IR between intermediate compilation steps.*/\n        SLANG_TARGET_FLAG_DUMP_IR = 1 << 9,\n\n        /* When set, will generate SPIRV directly instead of going through glslang. */\n        SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY = 1 << 10,\n    };\n\n    /*!\n    @brief Options to control floating-point precision guarantees for a target.\n    */\n    typedef unsigned int SlangFloatingPointModeIntegral;\n    enum SlangFloatingPointMode : SlangFloatingPointModeIntegral\n    {\n        SLANG_FLOATING_POINT_MODE_DEFAULT = 0,\n        SLANG_FLOATING_POINT_MODE_FAST,\n        SLANG_FLOATING_POINT_MODE_PRECISE,\n    };\n\n    /*!\n    @brief Options to control emission of `#line` directives\n    */\n    typedef unsigned int SlangLineDirectiveModeIntegral;\n    enum SlangLineDirectiveMode : SlangLineDirectiveModeIntegral\n    {\n        SLANG_LINE_DIRECTIVE_MODE_DEFAULT = 0,  /**< Default behavior: pick behavior base on target. */\n        SLANG_LINE_DIRECTIVE_MODE_NONE,         /**< Don't emit line directives at all. */\n        SLANG_LINE_DIRECTIVE_MODE_STANDARD,     /**< Emit standard C-style `#line` directives. */\n        SLANG_LINE_DIRECTIVE_MODE_GLSL,         /**< Emit GLSL-style directives with file *number* instead of name */\n    };\n\n    typedef int SlangSourceLanguageIntegral;\n    enum SlangSourceLanguage : SlangSourceLanguageIntegral\n    {\n        SLANG_SOURCE_LANGUAGE_UNKNOWN,\n        SLANG_SOURCE_LANGUAGE_SLANG,\n        SLANG_SOURCE_LANGUAGE_HLSL,\n        SLANG_SOURCE_LANGUAGE_GLSL,\n        SLANG_SOURCE_LANGUAGE_C,\n        SLANG_SOURCE_LANGUAGE_CPP,\n        SLANG_SOURCE_LANGUAGE_CUDA,\n        SLANG_SOURCE_LANGUAGE_COUNT_OF,\n    };\n\n    typedef unsigned int SlangProfileIDIntegral;\n    enum SlangProfileID : SlangProfileIDIntegral\n    {\n        SLANG_PROFILE_UNKNOWN,\n    };\n\n\n    typedef SlangInt32 SlangCapabilityIDIntegral;\n    enum SlangCapabilityID : SlangCapabilityIDIntegral\n    {\n        SLANG_CAPABILITY_UNKNOWN = 0,\n    };\n\n    typedef unsigned int SlangMatrixLayoutModeIntegral;\n    enum SlangMatrixLayoutMode : SlangMatrixLayoutModeIntegral\n    {\n        SLANG_MATRIX_LAYOUT_MODE_UNKNOWN = 0,\n        SLANG_MATRIX_LAYOUT_ROW_MAJOR,\n        SLANG_MATRIX_LAYOUT_COLUMN_MAJOR,\n    };\n\n    typedef SlangUInt32 SlangStageIntegral;\n    enum SlangStage : SlangStageIntegral\n    {\n        SLANG_STAGE_NONE,\n        SLANG_STAGE_VERTEX,\n        SLANG_STAGE_HULL,\n        SLANG_STAGE_DOMAIN,\n        SLANG_STAGE_GEOMETRY,\n        SLANG_STAGE_FRAGMENT,\n        SLANG_STAGE_COMPUTE,\n        SLANG_STAGE_RAY_GENERATION,\n        SLANG_STAGE_INTERSECTION,\n        SLANG_STAGE_ANY_HIT,\n        SLANG_STAGE_CLOSEST_HIT,\n        SLANG_STAGE_MISS,\n        SLANG_STAGE_CALLABLE,\n        SLANG_STAGE_MESH,\n        SLANG_STAGE_AMPLIFICATION,\n\n        // alias:\n        SLANG_STAGE_PIXEL = SLANG_STAGE_FRAGMENT,\n    };\n\n    typedef SlangUInt32 SlangDebugInfoLevelIntegral;\n    enum SlangDebugInfoLevel : SlangDebugInfoLevelIntegral\n    {\n        SLANG_DEBUG_INFO_LEVEL_NONE = 0,    /**< Don't emit debug information at all. */\n        SLANG_DEBUG_INFO_LEVEL_MINIMAL,     /**< Emit as little debug information as possible, while still supporting stack trackes. */\n        SLANG_DEBUG_INFO_LEVEL_STANDARD,    /**< Emit whatever is the standard level of debug information for each target. */\n        SLANG_DEBUG_INFO_LEVEL_MAXIMAL,     /**< Emit as much debug infromation as possible for each target. */\n        \n    };\n\n    typedef SlangUInt32 SlangOptimizationLevelIntegral;\n    enum SlangOptimizationLevel : SlangOptimizationLevelIntegral\n    {\n        SLANG_OPTIMIZATION_LEVEL_NONE = 0,  /**< Don't optimize at all. */\n        SLANG_OPTIMIZATION_LEVEL_DEFAULT,   /**< Default optimization level: balance code quality and compilation time. */\n        SLANG_OPTIMIZATION_LEVEL_HIGH,      /**< Optimize aggressively. */\n        SLANG_OPTIMIZATION_LEVEL_MAXIMAL,   /**< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs */\n    };\n\n    /** A result code for a Slang API operation.\n\n    This type is generally compatible with the Windows API `HRESULT` type. In particular, negative values indicate\n    failure results, while zero or positive results indicate success.\n\n    In general, Slang APIs always return a zero result on success, unless documented otherwise. Strictly speaking\n    a negative value indicates an error, a positive (or 0) value indicates success. This can be tested for with the macros\n    SLANG_SUCCEEDED(x) or SLANG_FAILED(x).\n\n    It can represent if the call was successful or not. It can also specify in an extensible manner what facility\n    produced the result (as the integral 'facility') as well as what caused it (as an integral 'code').\n    Under the covers SlangResult is represented as a int32_t.\n\n    SlangResult is designed to be compatible with COM HRESULT.\n\n    It's layout in bits is as follows\n\n    Severity | Facility | Code\n    ---------|----------|-----\n    31       |    30-16 | 15-0\n\n    Severity - 1 fail, 0 is success - as SlangResult is signed 32 bits, means negative number indicates failure.\n    Facility is where the error originated from. Code is the code specific to the facility.\n\n    Result codes have the following styles,\n    1) SLANG_name\n    2) SLANG_s_f_name\n    3) SLANG_s_name\n\n    where s is S for success, E for error\n    f is the short version of the facility name\n\n    Style 1 is reserved for SLANG_OK and SLANG_FAIL as they are so commonly used.\n\n    It is acceptable to expand 'f' to a longer name to differentiate a name or drop if unique without it.\n    ie for a facility 'DRIVER' it might make sense to have an error of the form SLANG_E_DRIVER_OUT_OF_MEMORY\n    */\n\n    typedef int32_t SlangResult;\n\n    //! Use to test if a result was failure. Never use result != SLANG_OK to test for failure, as there may be successful codes != SLANG_OK.\n#define SLANG_FAILED(status) ((status) < 0)\n    //! Use to test if a result succeeded. Never use result == SLANG_OK to test for success, as will detect other successful codes as a failure.\n#define SLANG_SUCCEEDED(status) ((status) >= 0)\n\n    //! Get the facility the result is associated with\n#define SLANG_GET_RESULT_FACILITY(r)    ((int32_t)(((r) >> 16) & 0x7fff))\n    //! Get the result code for the facility\n#define SLANG_GET_RESULT_CODE(r)        ((int32_t)((r) & 0xffff))\n\n#define SLANG_MAKE_ERROR(fac, code)        ((((int32_t)(fac)) << 16) | ((int32_t)(code)) | int32_t(0x80000000))\n#define SLANG_MAKE_SUCCESS(fac, code)    ((((int32_t)(fac)) << 16) | ((int32_t)(code)))\n\n    /*************************** Facilities ************************************/\n\n    //! Facilities compatible with windows COM - only use if known code is compatible\n#define SLANG_FACILITY_WIN_GENERAL      0\n#define SLANG_FACILITY_WIN_INTERFACE    4\n#define SLANG_FACILITY_WIN_API          7\n\n    //! Base facility -> so as to not clash with HRESULT values (values in 0x200 range do not appear used)\n#define SLANG_FACILITY_BASE         0x200\n\n    /*! Facilities numbers must be unique across a project to make the resulting result a unique number.\n    It can be useful to have a consistent short name for a facility, as used in the name prefix */\n#define SLANG_FACILITY_CORE             SLANG_FACILITY_BASE\n    /* Facility for codes, that are not uniquely defined/protected. Can be used to pass back a specific error without requiring system wide facility uniqueness. Codes\n    should never be part of a public API. */\n#define SLANG_FACILITY_INTERNAL         SLANG_FACILITY_BASE + 1\n\n    /// Base for external facilities. Facilities should be unique across modules.\n#define SLANG_FACILITY_EXTERNAL_BASE 0x210\n\n    /* ************************ Win COM compatible Results ******************************/\n    // https://msdn.microsoft.com/en-us/library/windows/desktop/aa378137(v=vs.85).aspx\n\n    //! SLANG_OK indicates success, and is equivalent to SLANG_MAKE_SUCCESS(SLANG_FACILITY_WIN_GENERAL, 0)\n#define SLANG_OK                          0\n    //! SLANG_FAIL is the generic failure code - meaning a serious error occurred and the call couldn't complete\n#define SLANG_FAIL                          SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_GENERAL, 0x4005)\n\n#define SLANG_MAKE_WIN_GENERAL_ERROR(code)  SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_GENERAL, code)\n\n    //! Functionality is not implemented\n#define SLANG_E_NOT_IMPLEMENTED             SLANG_MAKE_WIN_GENERAL_ERROR(0x4001)\n    //! Interface not be found\n#define SLANG_E_NO_INTERFACE                SLANG_MAKE_WIN_GENERAL_ERROR(0x4002)\n    //! Operation was aborted (did not correctly complete)\n#define SLANG_E_ABORT                       SLANG_MAKE_WIN_GENERAL_ERROR(0x4004) \n\n    //! Indicates that a handle passed in as parameter to a method is invalid.\n#define SLANG_E_INVALID_HANDLE              SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 6)\n    //! Indicates that an argument passed in as parameter to a method is invalid.\n#define SLANG_E_INVALID_ARG                 SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 0x57)\n    //! Operation could not complete - ran out of memory\n#define SLANG_E_OUT_OF_MEMORY               SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 0xe)\n\n    /* *************************** other Results **************************************/\n\n#define SLANG_MAKE_CORE_ERROR(code)         SLANG_MAKE_ERROR(SLANG_FACILITY_CORE, code)\n\n    // Supplied buffer is too small to be able to complete\n#define SLANG_E_BUFFER_TOO_SMALL            SLANG_MAKE_CORE_ERROR(1)\n    //! Used to identify a Result that has yet to be initialized.\n    //! It defaults to failure such that if used incorrectly will fail, as similar in concept to using an uninitialized variable.\n#define SLANG_E_UNINITIALIZED               SLANG_MAKE_CORE_ERROR(2)\n    //! Returned from an async method meaning the output is invalid (thus an error), but a result for the request is pending, and will be returned on a subsequent call with the async handle.\n#define SLANG_E_PENDING                     SLANG_MAKE_CORE_ERROR(3)\n    //! Indicates a file/resource could not be opened\n#define SLANG_E_CANNOT_OPEN                 SLANG_MAKE_CORE_ERROR(4)\n    //! Indicates a file/resource could not be found\n#define SLANG_E_NOT_FOUND                   SLANG_MAKE_CORE_ERROR(5)\n    //! An unhandled internal failure (typically from unhandled exception)\n#define SLANG_E_INTERNAL_FAIL               SLANG_MAKE_CORE_ERROR(6)\n    //! Could not complete because some underlying feature (hardware or software) was not available \n#define SLANG_E_NOT_AVAILABLE               SLANG_MAKE_CORE_ERROR(7)\n        //! Could not complete because the operation times out. \n#define SLANG_E_TIME_OUT                    SLANG_MAKE_CORE_ERROR(8)\n\n    /** A \"Universally Unique Identifier\" (UUID)\n\n    The Slang API uses UUIDs to identify interfaces when\n    using `queryInterface`.\n\n    This type is compatible with the `GUID` type defined\n    by the Component Object Model (COM), but Slang is\n    not dependent on COM.\n    */\n    struct SlangUUID\n    {\n        uint32_t data1;\n        uint16_t data2;\n        uint16_t data3;\n        uint8_t  data4[8];\n    };\n\n// Place at the start of an interface with the guid.\n// Guid should be specified as SLANG_COM_INTERFACE(0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 })\n// NOTE: it's the typical guid struct definition, without the surrounding {}\n// It is not necessary to use the multiple parameters (we can wrap in parens), but this is simple.\n#define SLANG_COM_INTERFACE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \\\n    public: \\\n    SLANG_FORCE_INLINE static const SlangUUID& getTypeGuid() \\\n    { \\\n        static const SlangUUID guid = { a, b, c, d0, d1, d2, d3, d4, d5, d6, d7 }; \\\n        return guid; \\\n    }\n\n// Sometimes it's useful to associate a guid with a class to identify it. This macro can used for this,\n// and the guid extracted via the getTypeGuid() function defined in the type\n#define SLANG_CLASS_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \\\n    SLANG_FORCE_INLINE static const SlangUUID& getTypeGuid() \\\n    { \\\n        static const SlangUUID guid = { a, b, c, d0, d1, d2, d3, d4, d5, d6, d7 }; \\\n        return guid; \\\n    }\n\n    /** Base interface for components exchanged through the API.\n\n    This interface definition is compatible with the COM `IUnknown`,\n    and uses the same UUID, but Slang does not require applications\n    to use or initialize COM.\n    */\n    struct ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 })\n\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) = 0;\n        virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0;\n        virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0;\n\n        /*\n        Inline methods are provided to allow the above operations to be called\n        using their traditional COM names/signatures:\n        */\n        SlangResult QueryInterface(struct _GUID const& uuid, void** outObject) { return queryInterface(*(SlangUUID const*)&uuid, outObject); }\n        uint32_t AddRef() { return addRef(); }\n        uint32_t Release() { return release(); }\n    };\n    #define SLANG_UUID_ISlangUnknown ISlangUnknown::getTypeGuid()\n\n\n    /* An interface to provide a mechanism to cast, that doesn't require ref counting\n    and doesn't have to return a pointer to a ISlangUnknown derived class */\n    class ISlangCastable : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0x87ede0e1, 0x4852, 0x44b0, { 0x8b, 0xf2, 0xcb, 0x31, 0x87, 0x4d, 0xe2, 0x39 });\n\n            /// Can be used to cast to interfaces without reference counting. \n            /// Also provides access to internal implementations, when they provide a guid\n            /// Can simulate a 'generated' interface as long as kept in scope by cast from. \n        virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) = 0;\n    };\n\n    class ISlangClonable : public ISlangCastable\n    {\n        SLANG_COM_INTERFACE(0x1ec36168, 0xe9f4, 0x430d, { 0xbb, 0x17, 0x4, 0x8a, 0x80, 0x46, 0xb3, 0x1f });\n\n            /// Note the use of guid is for the desired interface/object.\n            /// The object is returned *not* ref counted. Any type that can implements the interface, \n            /// derives from ICastable, and so (not withstanding some other issue) will always return\n            /// an ICastable interface which other interfaces/types are accessible from via castAs\n        SLANG_NO_THROW virtual void* SLANG_MCALL clone(const SlangUUID& guid) = 0;\n    };\n\n    /** A \"blob\" of binary data.\n\n    This interface definition is compatible with the `ID3DBlob` and `ID3D10Blob` interfaces.\n    */\n    struct ISlangBlob : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0x8BA5FB08, 0x5195, 0x40e2, { 0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02 })\n\n        virtual SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() = 0;\n        virtual SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() = 0;\n    };\n    #define SLANG_UUID_ISlangBlob ISlangBlob::getTypeGuid()\n\n    /* Can be requested from ISlangCastable cast to indicate the contained chars are null terminated.  \n    */\n    struct SlangTerminatedChars\n    {\n        SLANG_CLASS_GUID(0xbe0db1a8, 0x3594, 0x4603, { 0xa7, 0x8b, 0xc4, 0x86, 0x84, 0x30, 0xdf, 0xbb });\n        operator const char*() const { return chars; }\n        char chars[1];\n    };\n\n    /** A (real or virtual) file system.\n\n    Slang can make use of this interface whenever it would otherwise try to load files\n    from disk, allowing applications to hook and/or override filesystem access from\n    the compiler.\n\n    It is the responsibility of \n    the caller of any method that returns a ISlangBlob to release the blob when it is no \n    longer used (using 'release').\n    */\n\n    struct ISlangFileSystem : public ISlangCastable\n    {\n        SLANG_COM_INTERFACE(0x003A09FC, 0x3A4D, 0x4BA0, { 0xAD, 0x60, 0x1F, 0xD8, 0x63, 0xA9, 0x15, 0xAB })\n\n        /** Load a file from `path` and return a blob of its contents\n        @param path The path to load from, as a null-terminated UTF-8 string.\n        @param outBlob A destination pointer to receive the blob of the file contents.\n        @returns A `SlangResult` to indicate success or failure in loading the file.\n\n        NOTE! This is a *binary* load - the blob should contain the exact same bytes\n        as are found in the backing file. \n\n        If load is successful, the implementation should create a blob to hold\n        the file's content, store it to `outBlob`, and return 0.\n        If the load fails, the implementation should return a failure status\n        (any negative value will do).\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(\n            char const*     path,\n            ISlangBlob** outBlob) = 0;\n    };\n    #define SLANG_UUID_ISlangFileSystem ISlangFileSystem::getTypeGuid()\n\n\n    typedef void(*SlangFuncPtr)(void);\n\n    /** \n    (DEPRECIATED) ISlangSharedLibrary\n    */\n    struct ISlangSharedLibrary_Dep1: public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE( 0x9c9d5bc5, 0xeb61, 0x496f,{ 0x80, 0xd7, 0xd1, 0x47, 0xc4, 0xa2, 0x37, 0x30 })\n\n        virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) = 0;\n    };\n    #define SLANG_UUID_ISlangSharedLibrary_Dep1 ISlangSharedLibrary_Dep1::getTypeGuid()\n\n    /** An interface that can be used to encapsulate access to a shared library. An implementation\n    does not have to implement the library as a shared library\n    */\n    struct ISlangSharedLibrary : public ISlangCastable\n    {\n        SLANG_COM_INTERFACE(0x70dbc7c4, 0xdc3b, 0x4a07, { 0xae, 0x7e, 0x75, 0x2a, 0xf6, 0xa8, 0x15, 0x55 })\n\n        /** Get a function by name. If the library is unloaded will only return nullptr.\n        @param name The name of the function\n        @return The function pointer related to the name or nullptr if not found\n        */\n        SLANG_FORCE_INLINE SlangFuncPtr findFuncByName(char const* name) { return (SlangFuncPtr)findSymbolAddressByName(name); }\n\n        /** Get a symbol by name. If the library is unloaded will only return nullptr.\n        @param name The name of the symbol\n        @return The pointer related to the name or nullptr if not found\n        */\n        virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) = 0;\n    };\n    #define SLANG_UUID_ISlangSharedLibrary ISlangSharedLibrary::getTypeGuid()\n\n    struct ISlangSharedLibraryLoader: public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0x6264ab2b, 0xa3e8, 0x4a06, { 0x97, 0xf1, 0x49, 0xbc, 0x2d, 0x2a, 0xb1, 0x4d })\n\n            /** Load a shared library. In typical usage the library name should *not* contain any platform\n            specific elements. For example on windows a dll name should *not* be passed with a '.dll' extension,\n            and similarly on linux a shared library should *not* be passed with the 'lib' prefix and '.so' extension\n            @path path The unadorned filename and/or path for the shared library\n            @ param sharedLibraryOut Holds the shared library if successfully loaded */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(\n            const char*     path,\n            ISlangSharedLibrary** sharedLibraryOut) = 0;\n    };\n    #define SLANG_UUID_ISlangSharedLibraryLoader ISlangSharedLibraryLoader::getTypeGuid()\n    \n    /* Type that identifies how a path should be interpreted */\n    typedef unsigned int SlangPathTypeIntegral;\n    enum SlangPathType : SlangPathTypeIntegral\n    {\n        SLANG_PATH_TYPE_DIRECTORY,      /**< Path specified specifies a directory. */\n        SLANG_PATH_TYPE_FILE,           /**< Path specified is to a file. */\n    };\n\n    /* Callback to enumerate the contents of of a directory in a ISlangFileSystemExt.\n    The name is the name of a file system object (directory/file) in the specified path (ie it is without a path) */\n    typedef void (*FileSystemContentsCallBack)(SlangPathType pathType, const char* name, void* userData);\n\n    /* Determines how paths map to files on the OS file system */\n    enum class OSPathKind : uint8_t\n    {\n        None,                ///< Paths do not map to the file system\n        Direct,              ///< Paths map directly to the file system\n        OperatingSystem,     ///< Only paths gained via PathKind::OperatingSystem map to the operating system file system\n    };\n\n    /* Used to determine what kind of path is required from an input path */\n    enum class PathKind\n    {\n            /// Given a path, returns a simplified version of that path.  \n            /// This typically means removing '..' and/or '.' from the path.\n            /// A simplified path must point to the same object as the original.\n        Simplified,             \n\n            /// Given a path, returns a 'canonical path' to the item. \n            /// This may be the operating system 'canonical path' that is the unique path to the item.\n            /// \n            /// If the item exists the returned canonical path should always be usable to access the item.\n            /// \n            /// If the item the path specifies doesn't exist, the canonical path may not be returnable\n            /// or be a path simplification.             \n            /// Not all file systems support canonical paths.\n        Canonical,\n\n            /// Given a path returns a path such that it is suitable to be displayed to the user.\n            /// \n            /// For example if the file system is a zip file - it might include the path to the zip\n            /// container as well as the path to the specific file.\n            /// \n            /// NOTE! The display path won't necessarily work on the file system to access the item\n        Display,\n\n            /// Get the path to the item on the *operating system* file system, if available.\n        OperatingSystem,\n\n        CountOf,\n    };\n\n    /** An extended file system abstraction.\n    \n    Implementing and using this interface over ISlangFileSystem gives much more control over how paths\n    are managed, as well as how it is determined if two files 'are the same'.\n\n    All paths as input char*, or output as ISlangBlobs are always encoded as UTF-8 strings.\n    Blobs that contain strings are always zero terminated.\n    */\n    struct ISlangFileSystemExt : public ISlangFileSystem\n    {\n        SLANG_COM_INTERFACE(0x5fb632d2, 0x979d, 0x4481, { 0x9f, 0xee, 0x66, 0x3c, 0x3f, 0x14, 0x49, 0xe1 })\n\n        /** Get a uniqueIdentity which uniquely identifies an object of the file system.\n           \n        Given a path, returns a 'uniqueIdentity' which ideally is the same value for the same object on the file system.\n\n        The uniqueIdentity is used to compare if two paths are the same - which amongst other things allows Slang to\n        cache source contents internally. It is also used for #pragma once functionality.\n\n        A *requirement* is for any implementation is that two paths can only return the same uniqueIdentity if the\n        contents of the two files are *identical*. If an implementation breaks this constraint it can produce incorrect compilation.\n        If an implementation cannot *strictly* identify *the same* files, this will only have an effect on #pragma once behavior.\n\n        The string for the uniqueIdentity is held zero terminated in the ISlangBlob of outUniqueIdentity.\n   \n        Note that there are many ways a uniqueIdentity may be generated for a file. For example it could be the\n        'canonical path' - assuming it is available and unambiguous for a file system. Another possible mechanism\n        could be to store the filename combined with the file date time to uniquely identify it.\n     \n        The client must ensure the blob be released when no longer used, otherwise memory will leak.\n\n        NOTE! Ideally this method would be called 'getPathUniqueIdentity' but for historical reasons and\n        backward compatibility it's name remains with 'File' even though an implementation should be made to work\n        with directories too.\n\n        @param path\n        @param outUniqueIdentity\n        @returns A `SlangResult` to indicate success or failure getting the uniqueIdentity.\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(\n            const char* path,\n            ISlangBlob** outUniqueIdentity) = 0;\n\n        /** Calculate a path combining the 'fromPath' with 'path'\n\n        The client must ensure the blob be released when no longer used, otherwise memory will leak.\n\n        @param fromPathType How to interpret the from path - as a file or a directory.\n        @param fromPath The from path. \n        @param path Path to be determined relative to the fromPath\n        @param pathOut Holds the string which is the relative path. The string is held in the blob zero terminated.  \n        @returns A `SlangResult` to indicate success or failure in loading the file.\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(\n            SlangPathType fromPathType,\n            const char* fromPath,\n            const char* path,\n            ISlangBlob** pathOut) = 0;          \n            \n        /** Gets the type of path that path is on the file system. \n        @param path\n        @param pathTypeOut\n        @returns SLANG_OK if located and type is known, else an error. SLANG_E_NOT_FOUND if not found.\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(\n            const char* path, \n            SlangPathType* pathTypeOut) = 0;\n\n        /** Get a path based on the kind.\n\n        @param kind The kind of path wanted\n        @param path The input path\n        @param outPath The output path held in a blob\n        @returns SLANG_OK if successfully simplified the path (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other error code)\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPath(\n            PathKind kind,\n            const char* path,\n            ISlangBlob** outPath) = 0;\n\n        /** Clears any cached information */\n        virtual SLANG_NO_THROW void SLANG_MCALL clearCache() = 0;\n\n        /** Enumerate the contents of the path\n        \n        Note that for normal Slang operation it isn't necessary to enumerate contents this can return SLANG_E_NOT_IMPLEMENTED.\n        \n        @param The path to enumerate\n        @param callback This callback is called for each entry in the path. \n        @param userData This is passed to the callback\n        @returns SLANG_OK if successful \n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(\n            const char* path,\n            FileSystemContentsCallBack callback,\n            void* userData) = 0;\n\n        /** Returns how paths map to the OS file system\n        \n        @returns OSPathKind that describes how paths map to the Operating System file system\n        */\n        virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() = 0;\n    };\n\n    #define SLANG_UUID_ISlangFileSystemExt ISlangFileSystemExt::getTypeGuid()\n\n    struct ISlangMutableFileSystem : public ISlangFileSystemExt\n    {\n        SLANG_COM_INTERFACE(0xa058675c, 0x1d65, 0x452a, { 0x84, 0x58, 0xcc, 0xde, 0xd1, 0x42, 0x71, 0x5 })\n\n        /** Write data to the specified path.\n\n        @param path The path for data to be saved to\n        @param data The data to be saved\n        @param size The size of the data in bytes\n        @returns SLANG_OK if successful (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other error code)\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(\n            const char* path,\n            const void* data,\n            size_t size) = 0;\n\n        /** Write data in the form of a blob to the specified path.\n\n        Depending on the implementation writing a blob might be faster/use less memory. It is assumed the \n        blob is *immutable* and that an implementation can reference count it.\n\n        It is not guaranteed loading the same file will return the *same* blob - just a blob with same \n        contents.\n\n        @param path The path for data to be saved to\n        @param dataBlob The data to be saved\n        @returns SLANG_OK if successful (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other error code)\n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFileBlob(\n            const char* path,\n            ISlangBlob* dataBlob) = 0;\n\n        /** Remove the entry in the path (directory of file). Will only delete an empty directory, if not empty\n        will return an error.\n\n        @param path The path to remove \n        @returns SLANG_OK if successful \n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(\n            const char* path) = 0;\n\n        /** Create a directory.\n\n        The path to the directory must exist\n\n        @param path To the directory to create. The parent path *must* exist otherwise will return an error.\n        @returns SLANG_OK if successful \n        */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(\n            const char* path) = 0;\n    };\n\n    #define SLANG_UUID_ISlangMutableFileSystem ISlangMutableFileSystem::getTypeGuid()\n\n    /* Identifies different types of writer target*/\n    typedef unsigned int SlangWriterChannelIntegral;\n    enum SlangWriterChannel : SlangWriterChannelIntegral\n    {\n        SLANG_WRITER_CHANNEL_DIAGNOSTIC,\n        SLANG_WRITER_CHANNEL_STD_OUTPUT,\n        SLANG_WRITER_CHANNEL_STD_ERROR,\n        SLANG_WRITER_CHANNEL_COUNT_OF,\n    };\n\n    typedef unsigned int SlangWriterModeIntegral;\n    enum SlangWriterMode : SlangWriterModeIntegral\n    {\n        SLANG_WRITER_MODE_TEXT,\n        SLANG_WRITER_MODE_BINARY,\n    };\n\n    /** A stream typically of text, used for outputting diagnostic as well as other information.\n    */\n    struct ISlangWriter : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0xec457f0e, 0x9add, 0x4e6b,{ 0x85, 0x1c, 0xd7, 0xfa, 0x71, 0x6d, 0x15, 0xfd })\n\n            /** Begin an append buffer.\n            NOTE! Only one append buffer can be active at any time.\n            @param maxNumChars The maximum of chars that will be appended\n            @returns The start of the buffer for appending to. */    \n        virtual SLANG_NO_THROW char* SLANG_MCALL beginAppendBuffer(size_t maxNumChars) = 0;\n            /** Ends the append buffer, and is equivalent to a write of the append buffer.\n            NOTE! That an endAppendBuffer is not necessary if there are no characters to write.\n            @param buffer is the start of the data to append and must be identical to last value returned from beginAppendBuffer\n            @param numChars must be a value less than or equal to what was returned from last call to beginAppendBuffer\n            @returns Result, will be SLANG_OK on success */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL endAppendBuffer(char* buffer, size_t numChars) = 0;\n            /** Write text to the writer\n            @param chars The characters to write out\n            @param numChars The amount of characters\n            @returns SLANG_OK on success */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL write(const char* chars, size_t numChars) = 0;\n            /** Flushes any content to the output */\n        virtual SLANG_NO_THROW void SLANG_MCALL flush() = 0;\n            /** Determines if the writer stream is to the console, and can be used to alter the output \n            @returns Returns true if is a console writer */\n        virtual SLANG_NO_THROW SlangBool SLANG_MCALL isConsole() = 0;\n            /** Set the mode for the writer to use\n            @param mode The mode to use\n            @returns SLANG_OK on success */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL setMode(SlangWriterMode mode) = 0;\n    };\n    \n    #define SLANG_UUID_ISlangWriter ISlangWriter::getTypeGuid()\n\n    namespace slang {\n    struct IGlobalSession;\n    struct ICompileRequest;\n\n    } // namespace slang\n\n    /*!\n    @brief An instance of the Slang library.\n    */\n    typedef slang::IGlobalSession SlangSession;\n    \n\n    typedef struct SlangProgramLayout SlangProgramLayout;\n\n    /*!\n    @brief A request for one or more compilation actions to be performed.\n    */\n    typedef struct slang::ICompileRequest SlangCompileRequest;\n\n\n    /*!\n    @brief Initialize an instance of the Slang library.\n    */\n    SLANG_API SlangSession* spCreateSession(const char* deprecated = 0);\n\n    /*!\n    @brief Clean up after an instance of the Slang library.\n    */\n    SLANG_API void spDestroySession(\n        SlangSession*   session);\n\n    /** @see slang::IGlobalSession::setSharedLibraryLoader\n    */\n    SLANG_API void spSessionSetSharedLibraryLoader(\n        SlangSession*               session,\n        ISlangSharedLibraryLoader*  loader);\n\n    /** @see slang::IGlobalSession::getSharedLibraryLoader\n    */\n    SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader(\n        SlangSession*   session);\n\n    /** @see slang::IGlobalSession::checkCompileTargetSupport\n    */\n    SLANG_API SlangResult spSessionCheckCompileTargetSupport(\n        SlangSession*       session,\n        SlangCompileTarget  target);\n\n    /** @see slang::IGlobalSession::checkPassThroughSupport\n    */\n    SLANG_API SlangResult spSessionCheckPassThroughSupport(\n        SlangSession*       session,\n        SlangPassThrough    passThrough\n    );\n\n    /** @see slang::IGlobalSession::addBuiltins\n    */\n    SLANG_API void spAddBuiltins(\n        SlangSession*   session,\n        char const*     sourcePath,\n        char const*     sourceString);\n\n        /*!\n    @brief Callback type used for diagnostic output. \n    */\n    typedef void(*SlangDiagnosticCallback)(\n        char const* message,\n        void*       userData);\n\n    /*!\n    @brief Get the build version 'tag' string. The string is the same as produced via `git describe --tags`\n    for the project. If Slang is built separately from the automated build scripts\n    the contents will by default be 'unknown'. Any string can be set by changing the\n    contents of 'slang-tag-version.h' file and recompiling the project.\n\n    This function will return exactly the same result as the method getBuildTag string on IGlobalSession.\n\n    An advantage of using this function over the method is that doing so does not require the creation of\n    a session, which can be a fairly costly operation.\n\n    @return The build tag string\n    */\n    SLANG_API const char* spGetBuildTagString();\n\n    /* @see slang::IGlobalSession::createCompileRequest\n    */\n    SLANG_API SlangCompileRequest* spCreateCompileRequest(\n        SlangSession* session);\n\n    /*!\n    @brief Destroy a compile request.\n    Note a request is a COM object and can be destroyed via 'Release'.\n    */\n    SLANG_API void spDestroyCompileRequest(\n        SlangCompileRequest*    request);\n\n    /*! @see slang::ICompileRequest::setFileSystem */\n    SLANG_API void spSetFileSystem(\n        SlangCompileRequest*    request,\n        ISlangFileSystem*       fileSystem);\n\n    /*! @see slang::ICompileRequest::setCompileFlags */\n    SLANG_API void spSetCompileFlags(\n        SlangCompileRequest*    request,\n        SlangCompileFlags       flags);\n\n    /*! @see slang::ICompileRequest::getCompileFlags */\n    SLANG_API SlangCompileFlags spGetCompileFlags(\n        SlangCompileRequest*    request);\n\n    /*! @see slang::ICompileRequest::setDumpIntermediates */\n    SLANG_API void spSetDumpIntermediates(\n        SlangCompileRequest*    request,\n        int                     enable);\n\n    /*! @see slang::ICompileRequest::setDumpIntermediatePrefix */\n    SLANG_API void spSetDumpIntermediatePrefix(\n        SlangCompileRequest*    request,\n        const char* prefix);\n\n    /*! DEPRECATED: use `spSetTargetLineDirectiveMode` instead.\n        @see slang::ICompileRequest::setLineDirectiveMode */\n    SLANG_API void spSetLineDirectiveMode(\n        SlangCompileRequest*    request,\n        SlangLineDirectiveMode  mode);\n        \n    /*! @see slang::ICompileRequest::setTargetLineDirectiveMode */\n    SLANG_API void spSetTargetLineDirectiveMode(\n        SlangCompileRequest*    request,\n        int targetIndex,\n        SlangLineDirectiveMode  mode);\n\n    /*! @see slang::ICompileRequest::setTargetLineDirectiveMode */\n    SLANG_API void spSetTargetForceGLSLScalarBufferLayout(\n        SlangCompileRequest*    request,\n        int targetIndex,\n        bool forceScalarLayout);\n\n    /*! @see slang::ICompileRequest::setCodeGenTarget */\n    SLANG_API void spSetCodeGenTarget(\n        SlangCompileRequest*    request,\n        SlangCompileTarget target);\n\n    /*! @see slang::ICompileRequest::addCodeGenTarget */\n    SLANG_API int spAddCodeGenTarget(\n        SlangCompileRequest*    request,\n        SlangCompileTarget      target);\n\n    /*! @see slang::ICompileRequest::setTargetProfile */\n    SLANG_API void spSetTargetProfile(\n        SlangCompileRequest*    request,\n        int                     targetIndex,\n        SlangProfileID          profile);\n\n    /*! @see slang::ICompileRequest::setTargetFlags */\n    SLANG_API void spSetTargetFlags(\n        SlangCompileRequest*    request,\n        int                     targetIndex,\n        SlangTargetFlags        flags);\n\n\n\n    /*! @see slang::ICompileRequest::setTargetFloatingPointMode */\n    SLANG_API void spSetTargetFloatingPointMode(\n        SlangCompileRequest*    request,\n        int                     targetIndex,\n        SlangFloatingPointMode  mode);\n\n    /*! @see slang::ICompileRequest::addTargetCapability */\n    SLANG_API void spAddTargetCapability(\n        slang::ICompileRequest* request,\n        int                     targetIndex,\n        SlangCapabilityID       capability);\n\n    /* DEPRECATED: use `spSetMatrixLayoutMode` instead. */\n    SLANG_API void spSetTargetMatrixLayoutMode(\n        SlangCompileRequest*    request,\n        int                     targetIndex,\n        SlangMatrixLayoutMode   mode);\n\n    /*! @see slang::ICompileRequest::setMatrixLayoutMode */\n    SLANG_API void spSetMatrixLayoutMode(\n        SlangCompileRequest*    request,\n        SlangMatrixLayoutMode   mode);\n\n    /*! @see slang::ICompileRequest::setDebugInfoLevel */\n    SLANG_API void spSetDebugInfoLevel(\n        SlangCompileRequest*    request,\n        SlangDebugInfoLevel     level);\n\n    /*! @see slang::ICompileRequest::setOptimizationLevel */\n    SLANG_API void spSetOptimizationLevel(\n        SlangCompileRequest*    request,\n        SlangOptimizationLevel  level);\n\n\n    \n    /*! @see slang::ICompileRequest::setOutputContainerFormat */\n    SLANG_API void spSetOutputContainerFormat(\n        SlangCompileRequest*    request,\n        SlangContainerFormat    format);\n\n    /*! @see slang::ICompileRequest::setPassThrough */\n    SLANG_API void spSetPassThrough(\n        SlangCompileRequest*    request,\n        SlangPassThrough        passThrough);\n\n     /*! @see slang::ICompileRequest::setDiagnosticCallback */\n    SLANG_API void spSetDiagnosticCallback(\n        SlangCompileRequest*    request,\n        SlangDiagnosticCallback callback,\n        void const*             userData);\n\n    /*! @see slang::ICompileRequest::setWriter */\n    SLANG_API void spSetWriter(\n        SlangCompileRequest*    request,\n        SlangWriterChannel      channel, \n        ISlangWriter*           writer);\n\n    /*! @see slang::ICompileRequest::getWriter */\n    SLANG_API ISlangWriter* spGetWriter(\n        SlangCompileRequest*    request,\n        SlangWriterChannel      channel);\n\n    /*! @see slang::ICompileRequest::addSearchPath */\n    SLANG_API void spAddSearchPath(\n        SlangCompileRequest*    request,\n        const char*             searchDir);\n\n   /*! @see slang::ICompileRequest::addPreprocessorDefine */\n    SLANG_API void spAddPreprocessorDefine(\n        SlangCompileRequest*    request,\n        const char*             key,\n        const char*             value);\n\n    /*! @see slang::ICompileRequest::processCommandLineArguments */\n    SLANG_API SlangResult spProcessCommandLineArguments(\n        SlangCompileRequest*    request,\n        char const* const*      args,\n        int                     argCount);\n\n    /*! @see slang::ICompileRequest::addTranslationUnit */\n    SLANG_API int spAddTranslationUnit(\n        SlangCompileRequest*    request,\n        SlangSourceLanguage     language,\n        char const*             name);\n\n    \n    /*! @see slang::ICompileRequest::setDefaultModuleName */\n    SLANG_API void spSetDefaultModuleName(\n        SlangCompileRequest*    request,\n        const char* defaultModuleName);\n\n    /*! @see slang::ICompileRequest::addPreprocessorDefine */\n    SLANG_API void spTranslationUnit_addPreprocessorDefine(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        const char*             key,\n        const char*             value);\n\n\n    /*! @see slang::ICompileRequest::addTranslationUnitSourceFile */\n    SLANG_API void spAddTranslationUnitSourceFile(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        char const*             path);\n\n    /*! @see slang::ICompileRequest::addTranslationUnitSourceString */\n    SLANG_API void spAddTranslationUnitSourceString(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        char const*             path,\n        char const*             source);\n\n\n    /*! @see slang::ICompileRequest::addLibraryReference */\n    SLANG_API SlangResult spAddLibraryReference(\n        SlangCompileRequest*    request,\n        const void* libData,\n        size_t libDataSize);\n\n    /*! @see slang::ICompileRequest::addTranslationUnitSourceStringSpan */\n    SLANG_API void spAddTranslationUnitSourceStringSpan(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        char const*             path,\n        char const*             sourceBegin,\n        char const*             sourceEnd);\n\n    /*! @see slang::ICompileRequest::addTranslationUnitSourceBlob */\n    SLANG_API void spAddTranslationUnitSourceBlob(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        char const*             path,\n        ISlangBlob*             sourceBlob);\n\n    /*! @see slang::IGlobalSession::findProfile */\n    SLANG_API SlangProfileID spFindProfile(\n        SlangSession*   session,\n        char const*     name);\n\n    /*! @see slang::IGlobalSession::findCapability */\n    SLANG_API SlangCapabilityID spFindCapability(\n        SlangSession*   session,\n        char const*     name);\n\n    /*! @see slang::ICompileRequest::addEntryPoint */\n    SLANG_API int spAddEntryPoint(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        char const*             name,\n        SlangStage              stage);\n\n    /*! @see slang::ICompileRequest::addEntryPointEx */\n    SLANG_API int spAddEntryPointEx(\n        SlangCompileRequest*    request,\n        int                     translationUnitIndex,\n        char const*             name,\n        SlangStage              stage,\n        int                     genericArgCount,\n        char const**            genericArgs);\n\n    /*! @see slang::ICompileRequest::setGlobalGenericArgs */\n    SLANG_API SlangResult spSetGlobalGenericArgs(\n        SlangCompileRequest*    request,\n        int                     genericArgCount,\n        char const**            genericArgs);\n\n    /*! @see slang::ICompileRequest::setTypeNameForGlobalExistentialTypeParam */\n    SLANG_API SlangResult spSetTypeNameForGlobalExistentialTypeParam(\n        SlangCompileRequest*    request,\n        int                     slotIndex,\n        char const*             typeName);\n\n    /*! @see slang::ICompileRequest::setTypeNameForEntryPointExistentialTypeParam */\n    SLANG_API SlangResult spSetTypeNameForEntryPointExistentialTypeParam(\n        SlangCompileRequest*    request,\n        int                     entryPointIndex,\n        int                     slotIndex,\n        char const*             typeName);\n\n    /*! @see slang::ICompileRequest::compile */\n    SLANG_API SlangResult spCompile(\n        SlangCompileRequest*    request);\n\n\n    /*! @see slang::ICompileRequest::getDiagnosticOutput */\n    SLANG_API char const* spGetDiagnosticOutput(\n        SlangCompileRequest*    request);\n\n    /*! @see slang::ICompileRequest::getDiagnosticOutputBlob */\n    SLANG_API SlangResult spGetDiagnosticOutputBlob(\n        SlangCompileRequest*    request,\n        ISlangBlob**            outBlob);\n\n\n    /*! @see slang::ICompileRequest::getDependencyFileCount */\n    SLANG_API int\n    spGetDependencyFileCount(\n        SlangCompileRequest*    request);\n\n    /*! @see slang::ICompileRequest::getDependencyFilePath */\n    SLANG_API char const*\n    spGetDependencyFilePath(\n        SlangCompileRequest*    request,\n        int                     index);\n\n    /*! @see slang::ICompileRequest::getTranslationUnitCount */\n    SLANG_API int\n    spGetTranslationUnitCount(\n        SlangCompileRequest*    request);\n\n    /*! @see slang::ICompileRequest::getEntryPointSource */\n    SLANG_API char const* spGetEntryPointSource(\n        SlangCompileRequest*    request,\n        int                     entryPointIndex);\n\n    /*! @see slang::ICompileRequest::getEntryPointCode */\n    SLANG_API void const* spGetEntryPointCode(\n        SlangCompileRequest*    request,\n        int                     entryPointIndex,\n        size_t*                 outSize);\n\n    /*! @see slang::ICompileRequest::getEntryPointCodeBlob */\n    SLANG_API SlangResult spGetEntryPointCodeBlob(\n        SlangCompileRequest*    request,\n        int                     entryPointIndex,\n        int                     targetIndex,\n        ISlangBlob**            outBlob);\n\n    /*! @see slang::ICompileRequest::getEntryPointHostCallable */\n    SLANG_API SlangResult spGetEntryPointHostCallable(\n        SlangCompileRequest*    request,\n        int                     entryPointIndex,\n        int                     targetIndex,\n        ISlangSharedLibrary**   outSharedLibrary);\n\n    /*! @see slang::ICompileRequest::getTargetCodeBlob */\n    SLANG_API SlangResult spGetTargetCodeBlob(\n        SlangCompileRequest*    request,\n        int                     targetIndex,\n        ISlangBlob**            outBlob);\n\n    /*! @see slang::ICompileRequest::getTargetHostCallable */\n    SLANG_API SlangResult spGetTargetHostCallable(\n        SlangCompileRequest*    request,\n        int                     targetIndex,\n        ISlangSharedLibrary**   outSharedLibrary);\n\n    /*! @see slang::ICompileRequest::getCompileRequestCode */\n    SLANG_API void const* spGetCompileRequestCode(\n        SlangCompileRequest*    request,\n        size_t*                 outSize);\n\n    /*! @see slang::ICompileRequest::getContainerCode */\n    SLANG_API SlangResult spGetContainerCode(\n        SlangCompileRequest*    request,\n        ISlangBlob**            outBlob);\n\n    /*! @see slang::ICompileRequest::loadRepro */\n    SLANG_API SlangResult spLoadRepro(\n        SlangCompileRequest* request,\n        ISlangFileSystem* fileSystem,\n        const void* data,\n        size_t size);\n\n    /*! @see slang::ICompileRequest::saveRepro */\n    SLANG_API SlangResult spSaveRepro(\n        SlangCompileRequest* request,\n        ISlangBlob** outBlob\n    );\n\n    /*! @see slang::ICompileRequest::enableReproCapture */\n    SLANG_API SlangResult spEnableReproCapture(\n        SlangCompileRequest* request);\n\n\n    /** Extract contents of a repro.\n\n    Writes the contained files and manifest with their 'unique' names into fileSystem. For more details read the\n    docs/repro.md documentation. \n\n    @param session          The slang session\n    @param reproData        Holds the repro data\n    @param reproDataSize    The size of the repro data\n    @param fileSystem       File system that the contents of the repro will be written to\n    @returns                A `SlangResult` to indicate success or failure.\n    */\n    SLANG_API SlangResult spExtractRepro(\n        SlangSession* session,\n        const void* reproData,\n        size_t reproDataSize,\n        ISlangMutableFileSystem* fileSystem);\n\n    /* Turns a repro into a file system.\n\n    Makes the contents of the repro available as a file system - that is able to access the files with the same\n    paths as were used on the original repro file system. \n\n    @param session          The slang session\n    @param reproData        The repro data\n    @param reproDataSize    The size of the repro data\n    @param replaceFileSystem  Will attempt to load by unique names from this file system before using contents of the repro. Optional.\n    @param outFileSystem    The file system that can be used to access contents\n    @returns                A `SlangResult` to indicate success or failure.\n    */\n    SLANG_API SlangResult spLoadReproAsFileSystem(\n        SlangSession* session,\n        const void* reproData,\n        size_t reproDataSize,\n        ISlangFileSystem* replaceFileSystem,\n        ISlangFileSystemExt** outFileSystem);\n\n    /*! @see slang::ICompileRequest::overrideDiagnosticSeverity */\n    SLANG_API void spOverrideDiagnosticSeverity(\n        SlangCompileRequest* request,\n        SlangInt messageID,\n        SlangSeverity overrideSeverity);\n\n    /*! @see slang::ICompileRequest::getDiagnosticFlags */\n    SLANG_API SlangDiagnosticFlags spGetDiagnosticFlags(SlangCompileRequest* request);\n\n    /*! @see slang::ICompileRequest::setDiagnosticFlags */\n    SLANG_API void spSetDiagnosticFlags(SlangCompileRequest* request, SlangDiagnosticFlags flags);\n\n    /*\n    Forward declarations of types used in the reflection interface;\n    */\n\n    typedef struct SlangProgramLayout SlangProgramLayout;\n    typedef struct SlangEntryPoint SlangEntryPoint;\n    typedef struct SlangEntryPointLayout SlangEntryPointLayout;\n\n    typedef struct SlangReflectionModifier          SlangReflectionModifier;\n    typedef struct SlangReflectionType              SlangReflectionType;\n    typedef struct SlangReflectionTypeLayout        SlangReflectionTypeLayout;\n    typedef struct SlangReflectionVariable          SlangReflectionVariable;\n    typedef struct SlangReflectionVariableLayout    SlangReflectionVariableLayout;\n    typedef struct SlangReflectionTypeParameter     SlangReflectionTypeParameter;\n    typedef struct SlangReflectionUserAttribute     SlangReflectionUserAttribute;\n\n    /*\n    Type aliases to maintain backward compatibility.\n    */\n    typedef SlangProgramLayout SlangReflection;\n    typedef SlangEntryPointLayout SlangReflectionEntryPoint;\n\n    // get reflection data from a compilation request\n    SLANG_API SlangReflection* spGetReflection(\n        SlangCompileRequest*    request);\n\n    // type reflection\n\n    typedef unsigned int SlangTypeKindIntegral;\n    enum SlangTypeKind : SlangTypeKindIntegral\n    {\n        SLANG_TYPE_KIND_NONE,\n        SLANG_TYPE_KIND_STRUCT,\n        SLANG_TYPE_KIND_ARRAY,\n        SLANG_TYPE_KIND_MATRIX,\n        SLANG_TYPE_KIND_VECTOR,\n        SLANG_TYPE_KIND_SCALAR,\n        SLANG_TYPE_KIND_CONSTANT_BUFFER,\n        SLANG_TYPE_KIND_RESOURCE,\n        SLANG_TYPE_KIND_SAMPLER_STATE,\n        SLANG_TYPE_KIND_TEXTURE_BUFFER,\n        SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER,\n        SLANG_TYPE_KIND_PARAMETER_BLOCK,\n        SLANG_TYPE_KIND_GENERIC_TYPE_PARAMETER,\n        SLANG_TYPE_KIND_INTERFACE,\n        SLANG_TYPE_KIND_OUTPUT_STREAM,\n        SLANG_TYPE_KIND_MESH_OUTPUT,\n        SLANG_TYPE_KIND_SPECIALIZED,\n        SLANG_TYPE_KIND_FEEDBACK,\n        SLANG_TYPE_KIND_COUNT,\n    };\n\n    typedef unsigned int SlangScalarTypeIntegral;\n    enum SlangScalarType : SlangScalarTypeIntegral\n    {\n        SLANG_SCALAR_TYPE_NONE,\n        SLANG_SCALAR_TYPE_VOID,\n        SLANG_SCALAR_TYPE_BOOL,\n        SLANG_SCALAR_TYPE_INT32,\n        SLANG_SCALAR_TYPE_UINT32,\n        SLANG_SCALAR_TYPE_INT64,\n        SLANG_SCALAR_TYPE_UINT64,\n        SLANG_SCALAR_TYPE_FLOAT16,\n        SLANG_SCALAR_TYPE_FLOAT32,\n        SLANG_SCALAR_TYPE_FLOAT64,\n        SLANG_SCALAR_TYPE_INT8,\n        SLANG_SCALAR_TYPE_UINT8,\n        SLANG_SCALAR_TYPE_INT16,\n        SLANG_SCALAR_TYPE_UINT16,\n        SLANG_SCALAR_TYPE_INTPTR,\n        SLANG_SCALAR_TYPE_UINTPTR\n    };\n\n#ifndef SLANG_RESOURCE_SHAPE\n#    define SLANG_RESOURCE_SHAPE\n    typedef unsigned int SlangResourceShapeIntegral;\n    enum SlangResourceShape : SlangResourceShapeIntegral\n    {\n        SLANG_RESOURCE_BASE_SHAPE_MASK      = 0x0F,\n\n        SLANG_RESOURCE_NONE                 = 0x00,\n\n        SLANG_TEXTURE_1D                    = 0x01,\n        SLANG_TEXTURE_2D                    = 0x02,\n        SLANG_TEXTURE_3D                    = 0x03,\n        SLANG_TEXTURE_CUBE                  = 0x04,\n        SLANG_TEXTURE_BUFFER                = 0x05,\n\n        SLANG_STRUCTURED_BUFFER             = 0x06,\n        SLANG_BYTE_ADDRESS_BUFFER           = 0x07,\n        SLANG_RESOURCE_UNKNOWN              = 0x08,\n        SLANG_ACCELERATION_STRUCTURE        = 0x09,\n\n        SLANG_RESOURCE_EXT_SHAPE_MASK       = 0xF0,\n\n        SLANG_TEXTURE_FEEDBACK_FLAG         = 0x10,\n        SLANG_TEXTURE_ARRAY_FLAG            = 0x40,\n        SLANG_TEXTURE_MULTISAMPLE_FLAG      = 0x80,\n\n        SLANG_TEXTURE_1D_ARRAY              = SLANG_TEXTURE_1D   | SLANG_TEXTURE_ARRAY_FLAG,\n        SLANG_TEXTURE_2D_ARRAY              = SLANG_TEXTURE_2D   | SLANG_TEXTURE_ARRAY_FLAG,\n        SLANG_TEXTURE_CUBE_ARRAY            = SLANG_TEXTURE_CUBE | SLANG_TEXTURE_ARRAY_FLAG,\n\n        SLANG_TEXTURE_2D_MULTISAMPLE        = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG,\n        SLANG_TEXTURE_2D_MULTISAMPLE_ARRAY  = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG | SLANG_TEXTURE_ARRAY_FLAG,\n    };\n#endif\n    typedef unsigned int SlangResourceAccessIntegral;\n    enum SlangResourceAccess : SlangResourceAccessIntegral\n    {\n        SLANG_RESOURCE_ACCESS_NONE,\n        SLANG_RESOURCE_ACCESS_READ,\n        SLANG_RESOURCE_ACCESS_READ_WRITE,\n        SLANG_RESOURCE_ACCESS_RASTER_ORDERED,\n        SLANG_RESOURCE_ACCESS_APPEND,\n        SLANG_RESOURCE_ACCESS_CONSUME,\n        SLANG_RESOURCE_ACCESS_WRITE,\n    };\n\n    typedef unsigned int SlangParameterCategoryIntegral;\n    enum SlangParameterCategory : SlangParameterCategoryIntegral\n    {\n        SLANG_PARAMETER_CATEGORY_NONE,\n        SLANG_PARAMETER_CATEGORY_MIXED,\n        SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER,\n        SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE,\n        SLANG_PARAMETER_CATEGORY_UNORDERED_ACCESS,\n        SLANG_PARAMETER_CATEGORY_VARYING_INPUT,\n        SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT,\n        SLANG_PARAMETER_CATEGORY_SAMPLER_STATE,\n        SLANG_PARAMETER_CATEGORY_UNIFORM,\n        SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT,\n        SLANG_PARAMETER_CATEGORY_SPECIALIZATION_CONSTANT,\n        SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER,\n\n        // HLSL register `space`, Vulkan GLSL `set`\n        SLANG_PARAMETER_CATEGORY_REGISTER_SPACE,\n\n        // TODO: Ellie, Both APIs treat mesh outputs as more or less varying output,\n        // Does it deserve to be represented here??\n\n        // A parameter whose type is to be specialized by a global generic type argument\n        SLANG_PARAMETER_CATEGORY_GENERIC,\n\n        SLANG_PARAMETER_CATEGORY_RAY_PAYLOAD,\n        SLANG_PARAMETER_CATEGORY_HIT_ATTRIBUTES,\n        SLANG_PARAMETER_CATEGORY_CALLABLE_PAYLOAD,\n        SLANG_PARAMETER_CATEGORY_SHADER_RECORD,\n\n        // An existential type parameter represents a \"hole\" that\n        // needs to be filled with a concrete type to enable\n        // generation of specialized code.\n        //\n        // Consider this example:\n        //\n        //      struct MyParams\n        //      {\n        //          IMaterial material;\n        //          ILight lights[3];\n        //      };\n        //\n        // This `MyParams` type introduces two existential type parameters:\n        // one for `material` and one for `lights`. Even though `lights`\n        // is an array, it only introduces one type parameter, because\n        // we need to hae a *single* concrete type for all the array\n        // elements to be able to generate specialized code.\n        //\n        SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM,\n\n        // An existential object parameter represents a value\n        // that needs to be passed in to provide data for some\n        // interface-type shader paameter.\n        //\n        // Consider this example:\n        //\n        //      struct MyParams\n        //      {\n        //          IMaterial material;\n        //          ILight lights[3];\n        //      };\n        //\n        // This `MyParams` type introduces four existential object parameters:\n        // one for `material` and three for `lights` (one for each array\n        // element). This is consistent with the number of interface-type\n        // \"objects\" that are being passed through to the shader.\n        //\n        SLANG_PARAMETER_CATEGORY_EXISTENTIAL_OBJECT_PARAM,\n\n        //\n        SLANG_PARAMETER_CATEGORY_COUNT,\n\n\n        // DEPRECATED:\n        SLANG_PARAMETER_CATEGORY_VERTEX_INPUT = SLANG_PARAMETER_CATEGORY_VARYING_INPUT,\n        SLANG_PARAMETER_CATEGORY_FRAGMENT_OUTPUT = SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT,\n    };\n\n    /** Types of API-managed bindings that a parameter might use.\n    \n    `SlangBindingType` represents the distinct types of binding ranges that might be\n    understood by an underlying graphics API or cross-API abstraction layer.\n    Several of the enumeration cases here correspond to cases of `VkDescriptorType`\n    defined by the Vulkan API. Note however that the values of this enumeration\n    are not the same as those of any particular API.\n\n    The `SlangBindingType` enumeration is distinct from `SlangParameterCategory`\n    because `SlangParameterCategory` differentiates the types of parameters for\n    the purposes of layout, where the layout rules of some targets will treat\n    parameters of different types as occupying the same binding space for layout\n    (e.g., in SPIR-V both a `Texture2D` and `SamplerState` use the same space of\n    `binding` indices, and are not allowed to overlap), while those same types\n    map to different types of bindingsin the API (e.g., both textures and samplers\n    use different `VkDescriptorType` values).\n\n    When you want to answer \"what register/binding did this parameter use?\" you\n    should use `SlangParameterCategory`.\n\n    When you wnat to answer \"what type of descriptor range should this parameter use?\"\n    you should use `SlangBindingType`.\n    */\n    typedef SlangUInt32 SlangBindingTypeIntegral;\n    enum SlangBindingType : SlangBindingTypeIntegral\n    {\n        SLANG_BINDING_TYPE_UNKNOWN = 0,\n\n        SLANG_BINDING_TYPE_SAMPLER,\n        SLANG_BINDING_TYPE_TEXTURE,\n        SLANG_BINDING_TYPE_CONSTANT_BUFFER,\n        SLANG_BINDING_TYPE_PARAMETER_BLOCK,\n        SLANG_BINDING_TYPE_TYPED_BUFFER,\n        SLANG_BINDING_TYPE_RAW_BUFFER,\n        SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER,\n        SLANG_BINDING_TYPE_INPUT_RENDER_TARGET,\n        SLANG_BINDING_TYPE_INLINE_UNIFORM_DATA,\n        SLANG_BINDING_TYPE_RAY_TRACTING_ACCELERATION_STRUCTURE,\n\n        SLANG_BINDING_TYPE_VARYING_INPUT,\n        SLANG_BINDING_TYPE_VARYING_OUTPUT,\n\n        SLANG_BINDING_TYPE_EXISTENTIAL_VALUE,\n        SLANG_BINDING_TYPE_PUSH_CONSTANT,\n\n        SLANG_BINDING_TYPE_MUTABLE_FLAG = 0x100,\n\n        SLANG_BINDING_TYPE_MUTABLE_TETURE = SLANG_BINDING_TYPE_TEXTURE | SLANG_BINDING_TYPE_MUTABLE_FLAG,\n        SLANG_BINDING_TYPE_MUTABLE_TYPED_BUFFER = SLANG_BINDING_TYPE_TYPED_BUFFER | SLANG_BINDING_TYPE_MUTABLE_FLAG,\n        SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER = SLANG_BINDING_TYPE_RAW_BUFFER | SLANG_BINDING_TYPE_MUTABLE_FLAG,\n\n        SLANG_BINDING_TYPE_BASE_MASK = 0x00FF,\n        SLANG_BINDING_TYPE_EXT_MASK  = 0xFF00,\n    };\n\n    typedef SlangUInt32 SlangLayoutRulesIntegral;\n    enum SlangLayoutRules : SlangLayoutRulesIntegral\n    {\n        SLANG_LAYOUT_RULES_DEFAULT,\n    };\n\n    typedef SlangUInt32 SlangModifierIDIntegral;\n    enum SlangModifierID : SlangModifierIDIntegral\n    {\n        SLANG_MODIFIER_SHARED,\n    };\n\n    // User Attribute\n    SLANG_API char const* spReflectionUserAttribute_GetName(SlangReflectionUserAttribute* attrib);\n    SLANG_API unsigned int spReflectionUserAttribute_GetArgumentCount(SlangReflectionUserAttribute* attrib);\n    SLANG_API SlangReflectionType* spReflectionUserAttribute_GetArgumentType(SlangReflectionUserAttribute* attrib, unsigned int index);\n    SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueInt(SlangReflectionUserAttribute* attrib, unsigned int index, int * rs);\n    SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueFloat(SlangReflectionUserAttribute* attrib, unsigned int index, float * rs);\n\n    /** Returns the string-typed value of a user attribute argument\n        The string returned is not null-terminated. The length of the string is returned via `outSize`.\n        If index of out of range, or if the specified argument is not a string, the function will return nullptr.\n    */\n    SLANG_API const char* spReflectionUserAttribute_GetArgumentValueString(SlangReflectionUserAttribute* attrib, unsigned int index, size_t * outSize);\n\n    // Type Reflection\n\n    SLANG_API SlangTypeKind spReflectionType_GetKind(SlangReflectionType* type);\n    SLANG_API unsigned int spReflectionType_GetUserAttributeCount(SlangReflectionType* type);\n    SLANG_API SlangReflectionUserAttribute* spReflectionType_GetUserAttribute(SlangReflectionType* type, unsigned int index);\n    SLANG_API SlangReflectionUserAttribute* spReflectionType_FindUserAttributeByName(SlangReflectionType* type, char const* name);\n\n    SLANG_API unsigned int spReflectionType_GetFieldCount(SlangReflectionType* type);\n    SLANG_API SlangReflectionVariable* spReflectionType_GetFieldByIndex(SlangReflectionType* type, unsigned index);\n\n        /** Returns the number of elements in the given type.\n\n        This operation is valid for vector and array types. For other types it returns zero.\n\n        When invoked on an unbounded-size array it will return `SLANG_UNBOUNDED_SIZE`,\n        which is defined to be `~size_t(0)`.\n\n        If the size of a type cannot be statically computed, perhaps because it depends on\n        a generic parameter that has not been bound to a specific value, this function returns zero.\n        */\n    SLANG_API size_t spReflectionType_GetElementCount(SlangReflectionType* type);\n\n    #define SLANG_UNBOUNDED_SIZE (~size_t(0))\n\n    SLANG_API SlangReflectionType* spReflectionType_GetElementType(SlangReflectionType* type);\n\n    SLANG_API unsigned int spReflectionType_GetRowCount(SlangReflectionType* type);\n    SLANG_API unsigned int spReflectionType_GetColumnCount(SlangReflectionType* type);\n    SLANG_API SlangScalarType spReflectionType_GetScalarType(SlangReflectionType* type);\n\n    SLANG_API SlangResourceShape spReflectionType_GetResourceShape(SlangReflectionType* type);\n    SLANG_API SlangResourceAccess spReflectionType_GetResourceAccess(SlangReflectionType* type);\n    SLANG_API SlangReflectionType* spReflectionType_GetResourceResultType(SlangReflectionType* type);\n\n    SLANG_API char const* spReflectionType_GetName(SlangReflectionType* type);\n\n    // Type Layout Reflection\n\n    SLANG_API SlangReflectionType* spReflectionTypeLayout_GetType(SlangReflectionTypeLayout* type);\n    SLANG_API SlangTypeKind spReflectionTypeLayout_getKind(SlangReflectionTypeLayout* type);\n    SLANG_API size_t spReflectionTypeLayout_GetSize(SlangReflectionTypeLayout* type, SlangParameterCategory category);\n    SLANG_API size_t spReflectionTypeLayout_GetStride(SlangReflectionTypeLayout* type, SlangParameterCategory category);\n    SLANG_API int32_t spReflectionTypeLayout_getAlignment(SlangReflectionTypeLayout* type, SlangParameterCategory category);\n\n    SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetFieldByIndex(SlangReflectionTypeLayout* type, unsigned index);\n\n    SLANG_API SlangInt spReflectionTypeLayout_findFieldIndexByName(SlangReflectionTypeLayout* typeLayout, const char* nameBegin, const char* nameEnd);\n\n    SLANG_API size_t spReflectionTypeLayout_GetElementStride(SlangReflectionTypeLayout* type, SlangParameterCategory category);\n    SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_GetElementTypeLayout(SlangReflectionTypeLayout* type);\n    SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetElementVarLayout(SlangReflectionTypeLayout* type);\n    SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getContainerVarLayout(SlangReflectionTypeLayout* type);\n\n    SLANG_API SlangParameterCategory spReflectionTypeLayout_GetParameterCategory(SlangReflectionTypeLayout* type);\n\n    SLANG_API unsigned spReflectionTypeLayout_GetCategoryCount(SlangReflectionTypeLayout* type);\n    SLANG_API SlangParameterCategory spReflectionTypeLayout_GetCategoryByIndex(SlangReflectionTypeLayout* type, unsigned index);\n\n    SLANG_API SlangMatrixLayoutMode spReflectionTypeLayout_GetMatrixLayoutMode(SlangReflectionTypeLayout* type);\n\n    SLANG_API int spReflectionTypeLayout_getGenericParamIndex(SlangReflectionTypeLayout* type);\n\n    SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getPendingDataTypeLayout(SlangReflectionTypeLayout* type);\n\n    SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout(SlangReflectionTypeLayout* type);\n    SLANG_API SlangInt spReflectionType_getSpecializedTypeArgCount(SlangReflectionType* type);\n    SLANG_API SlangReflectionType* spReflectionType_getSpecializedTypeArgType(SlangReflectionType* type, SlangInt index);\n\n    SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeCount(SlangReflectionTypeLayout* typeLayout);\n    SLANG_API SlangBindingType spReflectionTypeLayout_getBindingRangeType(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeBindingCount(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getBindingRangeLeafTypeLayout(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangReflectionVariable* spReflectionTypeLayout_getBindingRangeLeafVariable(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangInt spReflectionTypeLayout_getFieldBindingRangeOffset(SlangReflectionTypeLayout* typeLayout, SlangInt fieldIndex);\n\n    SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorSetIndex(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorRangeCount(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n\n    SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetCount(SlangReflectionTypeLayout* typeLayout);\n    SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex);\n    SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex);\n    SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex);\n    SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex);\n    SLANG_API SlangBindingType spReflectionTypeLayout_getDescriptorSetDescriptorRangeType(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex);\n    SLANG_API SlangParameterCategory spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex);\n\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex);\n    SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getSubObjectRangeOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex);\n\n#if 0\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeObjectCount(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n    SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getSubObjectRangeTypeLayout(SlangReflectionTypeLayout* typeLayout, SlangInt index);\n\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeCount(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex);\n    SLANG_API SlangBindingType spReflectionTypeLayout_getSubObjectRangeDescriptorRangeBindingType(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeBindingCount(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeIndexOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject);\n    SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject);\n#endif\n\n    // Variable Reflection\n\n    SLANG_API char const* spReflectionVariable_GetName(SlangReflectionVariable* var);\n    SLANG_API SlangReflectionType* spReflectionVariable_GetType(SlangReflectionVariable* var);\n    SLANG_API SlangReflectionModifier* spReflectionVariable_FindModifier(SlangReflectionVariable* var, SlangModifierID modifierID);\n    SLANG_API unsigned int spReflectionVariable_GetUserAttributeCount(SlangReflectionVariable* var);\n    SLANG_API SlangReflectionUserAttribute* spReflectionVariable_GetUserAttribute(SlangReflectionVariable* var, unsigned int index);\n    SLANG_API SlangReflectionUserAttribute* spReflectionVariable_FindUserAttributeByName(SlangReflectionVariable* var, SlangSession * session, char const* name);\n\n    // Variable Layout Reflection\n\n    SLANG_API SlangReflectionVariable* spReflectionVariableLayout_GetVariable(SlangReflectionVariableLayout* var);\n\n    SLANG_API SlangReflectionTypeLayout* spReflectionVariableLayout_GetTypeLayout(SlangReflectionVariableLayout* var);\n\n    SLANG_API size_t spReflectionVariableLayout_GetOffset(SlangReflectionVariableLayout* var, SlangParameterCategory category);\n    SLANG_API size_t spReflectionVariableLayout_GetSpace(SlangReflectionVariableLayout* var, SlangParameterCategory category);\n\n    SLANG_API char const* spReflectionVariableLayout_GetSemanticName(SlangReflectionVariableLayout* var);\n    SLANG_API size_t spReflectionVariableLayout_GetSemanticIndex(SlangReflectionVariableLayout* var);\n\n    /** Get the stage that a variable belongs to (if any).\n\n    A variable \"belongs\" to a specific stage when it is a varying input/output\n    parameter either defined as part of the parameter list for an entry\n    point *or* at the global scope of a stage-specific GLSL code file (e.g.,\n    an `in` parameter in a GLSL `.vs` file belongs to the vertex stage).\n    */\n    SLANG_API SlangStage spReflectionVariableLayout_getStage(\n        SlangReflectionVariableLayout* var);\n\n\n    SLANG_API SlangReflectionVariableLayout* spReflectionVariableLayout_getPendingDataLayout(SlangReflectionVariableLayout* var);\n\n    // Shader Parameter Reflection\n\n    typedef SlangReflectionVariableLayout SlangReflectionParameter;\n\n    SLANG_API unsigned spReflectionParameter_GetBindingIndex(SlangReflectionParameter* parameter);\n    SLANG_API unsigned spReflectionParameter_GetBindingSpace(SlangReflectionParameter* parameter);\n\n    SLANG_API SlangResult spIsParameterLocationUsed(\n        SlangCompileRequest* request,\n        SlangInt entryPointIndex,\n        SlangInt targetIndex,\n        SlangParameterCategory category, // is this a `t` register? `s` register?\n        SlangUInt spaceIndex,      // `space` for D3D12, `set` for Vulkan\n        SlangUInt registerIndex,   // `register` for D3D12, `binding` for Vulkan\n        bool& outUsed);\n\n    // Entry Point Reflection\n\n    SLANG_API char const* spReflectionEntryPoint_getName(\n        SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API char const* spReflectionEntryPoint_getNameOverride(\n        SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API unsigned spReflectionEntryPoint_getParameterCount(\n        SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getParameterByIndex(\n        SlangReflectionEntryPoint*  entryPoint,\n        unsigned                    index);\n\n    SLANG_API SlangStage spReflectionEntryPoint_getStage(SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API void spReflectionEntryPoint_getComputeThreadGroupSize(\n        SlangReflectionEntryPoint*  entryPoint,\n        SlangUInt                   axisCount,\n        SlangUInt*                  outSizeAlongAxis);\n\n    SLANG_API int spReflectionEntryPoint_usesAnySampleRateInput(\n        SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getVarLayout(\n        SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getResultVarLayout(\n        SlangReflectionEntryPoint* entryPoint);\n\n    SLANG_API int spReflectionEntryPoint_hasDefaultConstantBuffer(\n        SlangReflectionEntryPoint* entryPoint);\n\n    // SlangReflectionTypeParameter\n    SLANG_API char const* spReflectionTypeParameter_GetName(SlangReflectionTypeParameter* typeParam);\n    SLANG_API unsigned spReflectionTypeParameter_GetIndex(SlangReflectionTypeParameter* typeParam);\n    SLANG_API unsigned spReflectionTypeParameter_GetConstraintCount(SlangReflectionTypeParameter* typeParam);\n    SLANG_API SlangReflectionType* spReflectionTypeParameter_GetConstraintByIndex(SlangReflectionTypeParameter* typeParam, unsigned int index);\n\n    // Shader Reflection\n\n    SLANG_API unsigned spReflection_GetParameterCount(SlangReflection* reflection);\n    SLANG_API SlangReflectionParameter* spReflection_GetParameterByIndex(SlangReflection* reflection, unsigned index);\n\n    SLANG_API unsigned int spReflection_GetTypeParameterCount(SlangReflection* reflection);\n    SLANG_API SlangReflectionTypeParameter* spReflection_GetTypeParameterByIndex(SlangReflection* reflection, unsigned int index);\n    SLANG_API SlangReflectionTypeParameter* spReflection_FindTypeParameter(SlangReflection* reflection, char const* name);\n\n    SLANG_API SlangReflectionType* spReflection_FindTypeByName(SlangReflection* reflection, char const* name);\n    SLANG_API SlangReflectionTypeLayout* spReflection_GetTypeLayout(SlangReflection* reflection, SlangReflectionType* reflectionType, SlangLayoutRules rules);\n\n    SLANG_API SlangUInt spReflection_getEntryPointCount(SlangReflection* reflection);\n    SLANG_API SlangReflectionEntryPoint* spReflection_getEntryPointByIndex(SlangReflection* reflection, SlangUInt index);\n    SLANG_API SlangReflectionEntryPoint* spReflection_findEntryPointByName(SlangReflection* reflection, char const* name);\n\n    SLANG_API SlangUInt spReflection_getGlobalConstantBufferBinding(SlangReflection* reflection);\n    SLANG_API size_t spReflection_getGlobalConstantBufferSize(SlangReflection* reflection);\n\n    SLANG_API  SlangReflectionType* spReflection_specializeType(\n        SlangReflection*            reflection,\n        SlangReflectionType*        type,\n        SlangInt                    specializationArgCount,\n        SlangReflectionType* const* specializationArgs,\n        ISlangBlob**                outDiagnostics);\n\n        /// Get the number of hashed strings\n    SLANG_API SlangUInt spReflection_getHashedStringCount(\n        SlangReflection*  reflection);\n\n        /// Get a hashed string. The number of chars is written in outCount.\n        /// The count does *NOT* including terminating 0. The returned string will be 0 terminated. \n    SLANG_API const char* spReflection_getHashedString(\n        SlangReflection*  reflection,\n        SlangUInt index,\n        size_t* outCount);\n\n        /// Compute a string hash.\n        /// Count should *NOT* include terminating zero.\n    SLANG_API int spComputeStringHash(const char* chars, size_t count);\n\n        /// Get a type layout representing reflection information for the global-scope prameters.\n    SLANG_API SlangReflectionTypeLayout* spReflection_getGlobalParamsTypeLayout(\n        SlangReflection* reflection);\n\n        /// Get a variable layout representing reflection information for the global-scope prameters.\n    SLANG_API SlangReflectionVariableLayout* spReflection_getGlobalParamsVarLayout(\n        SlangReflection* reflection);\n\n#ifdef __cplusplus\n}\n\n/* Helper interfaces for C++ users */\nnamespace slang\n{\n    struct BufferReflection;\n    struct TypeLayoutReflection;\n    struct TypeReflection;\n    struct VariableLayoutReflection;\n    struct VariableReflection;\n    \n    struct UserAttribute\n    {\n        char const* getName()\n        {\n            return spReflectionUserAttribute_GetName((SlangReflectionUserAttribute*)this);\n        }\n        uint32_t getArgumentCount()\n        {\n            return (uint32_t)spReflectionUserAttribute_GetArgumentCount((SlangReflectionUserAttribute*)this);\n        }\n        TypeReflection* getArgumentType(uint32_t index)\n        {\n            return (TypeReflection*)spReflectionUserAttribute_GetArgumentType((SlangReflectionUserAttribute*)this, index);\n        }\n        SlangResult getArgumentValueInt(uint32_t index, int * value)\n        {\n            return spReflectionUserAttribute_GetArgumentValueInt((SlangReflectionUserAttribute*)this, index, value);\n        }\n        SlangResult getArgumentValueFloat(uint32_t index, float * value)\n        {\n            return spReflectionUserAttribute_GetArgumentValueFloat((SlangReflectionUserAttribute*)this, index, value);\n        }\n        const char* getArgumentValueString(uint32_t index, size_t * outSize)\n        {\n            return spReflectionUserAttribute_GetArgumentValueString((SlangReflectionUserAttribute*)this, index, outSize);\n        }\n    };\n\n    struct TypeReflection\n    {\n        enum class Kind\n        {\n            None    = SLANG_TYPE_KIND_NONE,\n            Struct  = SLANG_TYPE_KIND_STRUCT,\n            Array   = SLANG_TYPE_KIND_ARRAY,\n            Matrix  = SLANG_TYPE_KIND_MATRIX,\n            Vector  = SLANG_TYPE_KIND_VECTOR,\n            Scalar  = SLANG_TYPE_KIND_SCALAR,\n            ConstantBuffer = SLANG_TYPE_KIND_CONSTANT_BUFFER,\n            Resource = SLANG_TYPE_KIND_RESOURCE,\n            SamplerState = SLANG_TYPE_KIND_SAMPLER_STATE,\n            TextureBuffer = SLANG_TYPE_KIND_TEXTURE_BUFFER,\n            ShaderStorageBuffer = SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER,\n            ParameterBlock = SLANG_TYPE_KIND_PARAMETER_BLOCK,\n            GenericTypeParameter = SLANG_TYPE_KIND_GENERIC_TYPE_PARAMETER,\n            Interface = SLANG_TYPE_KIND_INTERFACE,\n            OutputStream = SLANG_TYPE_KIND_OUTPUT_STREAM,\n            Specialized = SLANG_TYPE_KIND_SPECIALIZED,\n            Feedback = SLANG_TYPE_KIND_FEEDBACK,\n        };\n\n        enum ScalarType : SlangScalarTypeIntegral\n        {\n            None    = SLANG_SCALAR_TYPE_NONE,\n            Void    = SLANG_SCALAR_TYPE_VOID,\n            Bool    = SLANG_SCALAR_TYPE_BOOL,\n            Int32   = SLANG_SCALAR_TYPE_INT32,\n            UInt32  = SLANG_SCALAR_TYPE_UINT32,\n            Int64   = SLANG_SCALAR_TYPE_INT64,\n            UInt64  = SLANG_SCALAR_TYPE_UINT64,\n            Float16 = SLANG_SCALAR_TYPE_FLOAT16,\n            Float32 = SLANG_SCALAR_TYPE_FLOAT32,\n            Float64 = SLANG_SCALAR_TYPE_FLOAT64,\n            Int8    = SLANG_SCALAR_TYPE_INT8,\n            UInt8   = SLANG_SCALAR_TYPE_UINT8,\n            Int16   = SLANG_SCALAR_TYPE_INT16,\n            UInt16  = SLANG_SCALAR_TYPE_UINT16,\n        };\n\n        Kind getKind()\n        {\n            return (Kind) spReflectionType_GetKind((SlangReflectionType*) this);\n        }\n\n        // only useful if `getKind() == Kind::Struct`\n        unsigned int getFieldCount()\n        {\n            return spReflectionType_GetFieldCount((SlangReflectionType*) this);\n        }\n\n        VariableReflection* getFieldByIndex(unsigned int index)\n        {\n            return (VariableReflection*) spReflectionType_GetFieldByIndex((SlangReflectionType*) this, index);\n        }\n\n        bool isArray() { return getKind() == TypeReflection::Kind::Array; }\n\n        TypeReflection* unwrapArray()\n        {\n            TypeReflection* type = this;\n            while( type->isArray() )\n            {\n                type = type->getElementType();\n            }\n            return type;\n        }\n\n        // only useful if `getKind() == Kind::Array`\n        size_t getElementCount()\n        {\n            return spReflectionType_GetElementCount((SlangReflectionType*) this);\n        }\n\n        size_t getTotalArrayElementCount()\n        {\n            if(!isArray()) return 0;\n            size_t result = 1;\n            TypeReflection* type = this;\n            for(;;)\n            {\n                if(!type->isArray())\n                    return result;\n\n                result *= type->getElementCount();\n                type = type->getElementType();\n            }\n        }\n\n        TypeReflection* getElementType()\n        {\n            return (TypeReflection*) spReflectionType_GetElementType((SlangReflectionType*) this);\n        }\n\n        unsigned getRowCount()\n        {\n            return spReflectionType_GetRowCount((SlangReflectionType*) this);\n        }\n\n        unsigned getColumnCount()\n        {\n            return spReflectionType_GetColumnCount((SlangReflectionType*) this);\n        }\n\n        ScalarType getScalarType()\n        {\n            return (ScalarType) spReflectionType_GetScalarType((SlangReflectionType*) this);\n        }\n\n        TypeReflection* getResourceResultType()\n        {\n            return (TypeReflection*) spReflectionType_GetResourceResultType((SlangReflectionType*) this);\n        }\n\n        SlangResourceShape getResourceShape()\n        {\n            return spReflectionType_GetResourceShape((SlangReflectionType*) this);\n        }\n\n        SlangResourceAccess getResourceAccess()\n        {\n            return spReflectionType_GetResourceAccess((SlangReflectionType*) this);\n        }\n\n        char const* getName()\n        {\n            return spReflectionType_GetName((SlangReflectionType*) this);\n        }\n\n        unsigned int getUserAttributeCount()\n        {\n            return spReflectionType_GetUserAttributeCount((SlangReflectionType*)this);\n        }\n        UserAttribute* getUserAttributeByIndex(unsigned int index)\n        {\n            return (UserAttribute*)spReflectionType_GetUserAttribute((SlangReflectionType*)this, index);\n        }\n        UserAttribute* findUserAttributeByName(char const* name)\n        {\n            return (UserAttribute*)spReflectionType_FindUserAttributeByName((SlangReflectionType*)this, name);\n        }\n    };\n\n    enum ParameterCategory : SlangParameterCategoryIntegral\n    {\n        // TODO: these aren't scoped...\n        None = SLANG_PARAMETER_CATEGORY_NONE,\n        Mixed = SLANG_PARAMETER_CATEGORY_MIXED,\n        ConstantBuffer = SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER,\n        ShaderResource = SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE,\n        UnorderedAccess = SLANG_PARAMETER_CATEGORY_UNORDERED_ACCESS,\n        VaryingInput = SLANG_PARAMETER_CATEGORY_VARYING_INPUT,\n        VaryingOutput = SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT,\n        SamplerState = SLANG_PARAMETER_CATEGORY_SAMPLER_STATE,\n        Uniform = SLANG_PARAMETER_CATEGORY_UNIFORM,\n        DescriptorTableSlot = SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT,\n        SpecializationConstant = SLANG_PARAMETER_CATEGORY_SPECIALIZATION_CONSTANT,\n        PushConstantBuffer = SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER,\n        RegisterSpace = SLANG_PARAMETER_CATEGORY_REGISTER_SPACE,\n        GenericResource = SLANG_PARAMETER_CATEGORY_GENERIC,\n\n        RayPayload = SLANG_PARAMETER_CATEGORY_RAY_PAYLOAD,\n        HitAttributes = SLANG_PARAMETER_CATEGORY_HIT_ATTRIBUTES,\n        CallablePayload = SLANG_PARAMETER_CATEGORY_CALLABLE_PAYLOAD,\n\n        ShaderRecord = SLANG_PARAMETER_CATEGORY_SHADER_RECORD,\n\n        ExistentialTypeParam = SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM,\n        ExistentialObjectParam = SLANG_PARAMETER_CATEGORY_EXISTENTIAL_OBJECT_PARAM,\n\n        // DEPRECATED:\n        VertexInput = SLANG_PARAMETER_CATEGORY_VERTEX_INPUT,\n        FragmentOutput = SLANG_PARAMETER_CATEGORY_FRAGMENT_OUTPUT,\n    };\n\n    enum class BindingType : SlangBindingTypeIntegral\n    {\n        Unknown                             = SLANG_BINDING_TYPE_UNKNOWN,\n\n        Sampler                             = SLANG_BINDING_TYPE_SAMPLER,\n        Texture                             = SLANG_BINDING_TYPE_TEXTURE,\n        ConstantBuffer                      = SLANG_BINDING_TYPE_CONSTANT_BUFFER,\n        ParameterBlock                      = SLANG_BINDING_TYPE_PARAMETER_BLOCK,\n        TypedBuffer                         = SLANG_BINDING_TYPE_TYPED_BUFFER,\n        RawBuffer                           = SLANG_BINDING_TYPE_RAW_BUFFER,\n        CombinedTextureSampler              = SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER,\n        InputRenderTarget                   = SLANG_BINDING_TYPE_INPUT_RENDER_TARGET,\n        InlineUniformData                   = SLANG_BINDING_TYPE_INLINE_UNIFORM_DATA,\n        RayTracingAccelerationStructure     = SLANG_BINDING_TYPE_RAY_TRACTING_ACCELERATION_STRUCTURE,\n        VaryingInput                        = SLANG_BINDING_TYPE_VARYING_INPUT,\n        VaryingOutput                       = SLANG_BINDING_TYPE_VARYING_OUTPUT,\n        ExistentialValue                    = SLANG_BINDING_TYPE_EXISTENTIAL_VALUE,\n        PushConstant                        = SLANG_BINDING_TYPE_PUSH_CONSTANT,\n\n        MutableFlag                         = SLANG_BINDING_TYPE_MUTABLE_FLAG,\n\n        MutableTexture                      = SLANG_BINDING_TYPE_MUTABLE_TETURE,\n        MutableTypedBuffer                  = SLANG_BINDING_TYPE_MUTABLE_TYPED_BUFFER,\n        MutableRawBuffer                    = SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER,\n\n        BaseMask                            = SLANG_BINDING_TYPE_BASE_MASK,\n        ExtMask                             = SLANG_BINDING_TYPE_EXT_MASK,\n    };\n\n    struct TypeLayoutReflection\n    {\n        TypeReflection* getType()\n        {\n            return (TypeReflection*) spReflectionTypeLayout_GetType((SlangReflectionTypeLayout*) this);\n        }\n\n        TypeReflection::Kind getKind()\n        {\n            return (TypeReflection::Kind) spReflectionTypeLayout_getKind((SlangReflectionTypeLayout*) this);\n        }\n\n        size_t getSize(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM)\n        {\n            return spReflectionTypeLayout_GetSize((SlangReflectionTypeLayout*) this, category);\n        }\n\n        size_t getStride(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM)\n        {\n            return spReflectionTypeLayout_GetStride((SlangReflectionTypeLayout*) this, category);\n        }\n\n        int32_t getAlignment(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM)\n        {\n            return spReflectionTypeLayout_getAlignment((SlangReflectionTypeLayout*) this, category);\n        }\n\n        unsigned int getFieldCount()\n        {\n            return getType()->getFieldCount();\n        }\n\n        VariableLayoutReflection* getFieldByIndex(unsigned int index)\n        {\n            return (VariableLayoutReflection*) spReflectionTypeLayout_GetFieldByIndex((SlangReflectionTypeLayout*) this, index);\n        }\n\n        SlangInt findFieldIndexByName(char const* nameBegin, char const* nameEnd = nullptr)\n        {\n            return spReflectionTypeLayout_findFieldIndexByName((SlangReflectionTypeLayout*) this, nameBegin, nameEnd);\n        }\n\n        bool isArray() { return getType()->isArray(); }\n\n        TypeLayoutReflection* unwrapArray()\n        {\n            TypeLayoutReflection* typeLayout = this;\n            while( typeLayout->isArray() )\n            {\n                typeLayout = typeLayout->getElementTypeLayout();\n            }\n            return typeLayout;\n        }\n\n        // only useful if `getKind() == Kind::Array`\n        size_t getElementCount()\n        {\n            return getType()->getElementCount();\n        }\n\n        size_t getTotalArrayElementCount()\n        {\n            return getType()->getTotalArrayElementCount();\n        }\n\n        size_t getElementStride(SlangParameterCategory category)\n        {\n            return spReflectionTypeLayout_GetElementStride((SlangReflectionTypeLayout*) this, category);\n        }\n\n        TypeLayoutReflection* getElementTypeLayout()\n        {\n            return (TypeLayoutReflection*) spReflectionTypeLayout_GetElementTypeLayout((SlangReflectionTypeLayout*) this);\n        }\n\n        VariableLayoutReflection* getElementVarLayout()\n        {\n            return (VariableLayoutReflection*)spReflectionTypeLayout_GetElementVarLayout((SlangReflectionTypeLayout*) this);\n        }\n\n        VariableLayoutReflection* getContainerVarLayout()\n        {\n            return (VariableLayoutReflection*)spReflectionTypeLayout_getContainerVarLayout((SlangReflectionTypeLayout*) this);\n        }\n\n        // How is this type supposed to be bound?\n        ParameterCategory getParameterCategory()\n        {\n            return (ParameterCategory) spReflectionTypeLayout_GetParameterCategory((SlangReflectionTypeLayout*) this);\n        }\n\n        unsigned int getCategoryCount()\n        {\n            return spReflectionTypeLayout_GetCategoryCount((SlangReflectionTypeLayout*) this);\n        }\n\n        ParameterCategory getCategoryByIndex(unsigned int index)\n        {\n            return (ParameterCategory) spReflectionTypeLayout_GetCategoryByIndex((SlangReflectionTypeLayout*) this, index);\n        }\n\n        unsigned getRowCount()\n        {\n            return getType()->getRowCount();\n        }\n\n        unsigned getColumnCount()\n        {\n            return getType()->getColumnCount();\n        }\n\n        TypeReflection::ScalarType getScalarType()\n        {\n            return getType()->getScalarType();\n        }\n\n        TypeReflection* getResourceResultType()\n        {\n            return getType()->getResourceResultType();\n        }\n\n        SlangResourceShape getResourceShape()\n        {\n            return getType()->getResourceShape();\n        }\n\n        SlangResourceAccess getResourceAccess()\n        {\n            return getType()->getResourceAccess();\n        }\n\n        char const* getName()\n        {\n            return getType()->getName();\n        }\n\n        SlangMatrixLayoutMode getMatrixLayoutMode()\n        {\n            return spReflectionTypeLayout_GetMatrixLayoutMode((SlangReflectionTypeLayout*) this);\n        }\n\n        int getGenericParamIndex()\n        {\n            return spReflectionTypeLayout_getGenericParamIndex(\n                (SlangReflectionTypeLayout*) this);\n        }\n\n        TypeLayoutReflection* getPendingDataTypeLayout()\n        {\n            return (TypeLayoutReflection*) spReflectionTypeLayout_getPendingDataTypeLayout(\n                (SlangReflectionTypeLayout*) this);\n        }\n\n        VariableLayoutReflection* getSpecializedTypePendingDataVarLayout()\n        {\n            return (VariableLayoutReflection*) spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout(\n                (SlangReflectionTypeLayout*) this);\n        }\n\n        SlangInt getBindingRangeCount()\n        {\n            return spReflectionTypeLayout_getBindingRangeCount(\n                (SlangReflectionTypeLayout*) this);\n        }\n\n        BindingType getBindingRangeType(SlangInt index)\n        {\n            return (BindingType) spReflectionTypeLayout_getBindingRangeType(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        SlangInt getBindingRangeBindingCount(SlangInt index)\n        {\n            return spReflectionTypeLayout_getBindingRangeBindingCount(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        /*\n        SlangInt getBindingRangeIndexOffset(SlangInt index)\n        {\n            return spReflectionTypeLayout_getBindingRangeIndexOffset(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        SlangInt getBindingRangeSpaceOffset(SlangInt index)\n        {\n            return spReflectionTypeLayout_getBindingRangeSpaceOffset(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n        */\n\n        SlangInt getFieldBindingRangeOffset(SlangInt fieldIndex)\n        {\n            return spReflectionTypeLayout_getFieldBindingRangeOffset(\n                (SlangReflectionTypeLayout*) this,\n                fieldIndex);\n        }\n\n        TypeLayoutReflection* getBindingRangeLeafTypeLayout(SlangInt index)\n        {\n            return (TypeLayoutReflection*) spReflectionTypeLayout_getBindingRangeLeafTypeLayout(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        VariableReflection* getBindingRangeLeafVariable(SlangInt index)\n        {\n            return (VariableReflection*)spReflectionTypeLayout_getBindingRangeLeafVariable(\n                (SlangReflectionTypeLayout*)this, index);\n        }\n\n        SlangInt getBindingRangeDescriptorSetIndex(SlangInt index)\n        {\n            return spReflectionTypeLayout_getBindingRangeDescriptorSetIndex(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        SlangInt getBindingRangeFirstDescriptorRangeIndex(SlangInt index)\n        {\n            return spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        SlangInt getBindingRangeDescriptorRangeCount(SlangInt index)\n        {\n            return spReflectionTypeLayout_getBindingRangeDescriptorRangeCount(\n                (SlangReflectionTypeLayout*) this,\n                index);\n        }\n\n        SlangInt getDescriptorSetCount()\n        {\n            return spReflectionTypeLayout_getDescriptorSetCount(\n                (SlangReflectionTypeLayout*) this);\n        }\n\n        SlangInt getDescriptorSetSpaceOffset(SlangInt setIndex)\n        {\n            return spReflectionTypeLayout_getDescriptorSetSpaceOffset(\n                (SlangReflectionTypeLayout*) this,\n                setIndex);\n        }\n\n        SlangInt getDescriptorSetDescriptorRangeCount(SlangInt setIndex)\n        {\n            return spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount(\n                (SlangReflectionTypeLayout*) this,\n                setIndex);\n        }\n\n        SlangInt getDescriptorSetDescriptorRangeIndexOffset(SlangInt setIndex, SlangInt rangeIndex)\n        {\n            return spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset(\n                (SlangReflectionTypeLayout*) this,\n                setIndex,\n                rangeIndex);\n        }\n\n        SlangInt getDescriptorSetDescriptorRangeDescriptorCount(SlangInt setIndex, SlangInt rangeIndex)\n        {\n            return spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount(\n                (SlangReflectionTypeLayout*) this,\n                setIndex,\n                rangeIndex);\n        }\n\n        BindingType getDescriptorSetDescriptorRangeType(SlangInt setIndex, SlangInt rangeIndex)\n        {\n            return (BindingType) spReflectionTypeLayout_getDescriptorSetDescriptorRangeType(\n                (SlangReflectionTypeLayout*) this,\n                setIndex,\n                rangeIndex);\n        }\n\n        ParameterCategory getDescriptorSetDescriptorRangeCategory(SlangInt setIndex, SlangInt rangeIndex)\n        {\n            return (ParameterCategory) spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory(\n                (SlangReflectionTypeLayout*) this,\n                setIndex,\n                rangeIndex);\n        }\n\n        SlangInt getSubObjectRangeCount()\n        {\n            return spReflectionTypeLayout_getSubObjectRangeCount(\n                (SlangReflectionTypeLayout*) this);\n        }\n\n        SlangInt getSubObjectRangeBindingRangeIndex(SlangInt subObjectRangeIndex)\n        {\n            return spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(\n                (SlangReflectionTypeLayout*) this,\n                subObjectRangeIndex);\n        }\n\n        SlangInt getSubObjectRangeSpaceOffset(SlangInt subObjectRangeIndex)\n        {\n            return spReflectionTypeLayout_getSubObjectRangeSpaceOffset(\n                (SlangReflectionTypeLayout*) this,\n                subObjectRangeIndex);\n        }\n\n        VariableLayoutReflection* getSubObjectRangeOffset(SlangInt subObjectRangeIndex)\n        {\n            return (VariableLayoutReflection*) spReflectionTypeLayout_getSubObjectRangeOffset(\n                (SlangReflectionTypeLayout*) this,\n                subObjectRangeIndex);\n        }\n    };\n\n    struct Modifier\n    {\n        enum ID : SlangModifierIDIntegral\n        {\n            Shared = SLANG_MODIFIER_SHARED,\n        };\n    };\n\n    struct VariableReflection\n    {\n        char const* getName()\n        {\n            return spReflectionVariable_GetName((SlangReflectionVariable*) this);\n        }\n\n        TypeReflection* getType()\n        {\n            return (TypeReflection*) spReflectionVariable_GetType((SlangReflectionVariable*) this);\n        }\n\n        Modifier* findModifier(Modifier::ID id)\n        {\n            return (Modifier*) spReflectionVariable_FindModifier((SlangReflectionVariable*) this, (SlangModifierID) id);\n        }\n\n        unsigned int getUserAttributeCount()\n        {\n            return spReflectionVariable_GetUserAttributeCount((SlangReflectionVariable*)this);\n        }\n        UserAttribute* getUserAttributeByIndex(unsigned int index)\n        {\n            return (UserAttribute*)spReflectionVariable_GetUserAttribute((SlangReflectionVariable*)this, index);\n        }\n        UserAttribute* findUserAttributeByName(SlangSession* session, char const* name)\n        {\n            return (UserAttribute*)spReflectionVariable_FindUserAttributeByName((SlangReflectionVariable*)this, session, name);\n        }\n    };\n\n    struct VariableLayoutReflection\n    {\n        VariableReflection* getVariable()\n        {\n            return (VariableReflection*) spReflectionVariableLayout_GetVariable((SlangReflectionVariableLayout*) this);\n        }\n\n        char const* getName()\n        {\n            return getVariable()->getName();\n        }\n\n        Modifier* findModifier(Modifier::ID id)\n        {\n            return getVariable()->findModifier(id);\n        }\n\n        TypeLayoutReflection* getTypeLayout()\n        {\n            return (TypeLayoutReflection*) spReflectionVariableLayout_GetTypeLayout((SlangReflectionVariableLayout*) this);\n        }\n\n        ParameterCategory getCategory()\n        {\n            return getTypeLayout()->getParameterCategory();\n        }\n\n        unsigned int getCategoryCount()\n        {\n            return getTypeLayout()->getCategoryCount();\n        }\n\n        ParameterCategory getCategoryByIndex(unsigned int index)\n        {\n            return getTypeLayout()->getCategoryByIndex(index);\n        }\n\n\n        size_t getOffset(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM)\n        {\n            return spReflectionVariableLayout_GetOffset((SlangReflectionVariableLayout*) this, category);\n        }\n\n        TypeReflection* getType()\n        {\n            return getVariable()->getType();\n        }\n\n        unsigned getBindingIndex()\n        {\n            return spReflectionParameter_GetBindingIndex((SlangReflectionVariableLayout*) this);\n        }\n\n        unsigned getBindingSpace()\n        {\n            return spReflectionParameter_GetBindingSpace((SlangReflectionVariableLayout*) this);\n        }\n\n        size_t getBindingSpace(SlangParameterCategory category)\n        {\n            return spReflectionVariableLayout_GetSpace((SlangReflectionVariableLayout*) this, category);\n        }\n\n        char const* getSemanticName()\n        {\n            return spReflectionVariableLayout_GetSemanticName((SlangReflectionVariableLayout*) this);\n        }\n\n        size_t getSemanticIndex()\n        {\n            return spReflectionVariableLayout_GetSemanticIndex((SlangReflectionVariableLayout*) this);\n        }\n\n        SlangStage getStage()\n        {\n            return spReflectionVariableLayout_getStage((SlangReflectionVariableLayout*) this);\n        }\n\n        VariableLayoutReflection* getPendingDataLayout()\n        {\n            return (VariableLayoutReflection*) spReflectionVariableLayout_getPendingDataLayout((SlangReflectionVariableLayout*) this);\n        }\n    };\n\n    struct EntryPointReflection\n    {\n        char const* getName()\n        {\n            return spReflectionEntryPoint_getName((SlangReflectionEntryPoint*) this);\n        }\n\n        char const* getNameOverride()\n        {\n            return spReflectionEntryPoint_getNameOverride((SlangReflectionEntryPoint*)this);\n        }\n\n        unsigned getParameterCount()\n        {\n            return spReflectionEntryPoint_getParameterCount((SlangReflectionEntryPoint*) this);\n        }\n\n        VariableLayoutReflection* getParameterByIndex(unsigned index)\n        {\n            return (VariableLayoutReflection*) spReflectionEntryPoint_getParameterByIndex((SlangReflectionEntryPoint*) this, index);\n        }\n\n        SlangStage getStage()\n        {\n            return spReflectionEntryPoint_getStage((SlangReflectionEntryPoint*) this);\n        }\n\n        void getComputeThreadGroupSize(\n            SlangUInt   axisCount,\n            SlangUInt*  outSizeAlongAxis)\n        {\n            return spReflectionEntryPoint_getComputeThreadGroupSize((SlangReflectionEntryPoint*) this, axisCount, outSizeAlongAxis);\n        }\n\n        bool usesAnySampleRateInput()\n        {\n            return 0 != spReflectionEntryPoint_usesAnySampleRateInput((SlangReflectionEntryPoint*) this);\n        }\n\n        VariableLayoutReflection* getVarLayout()\n        {\n            return (VariableLayoutReflection*) spReflectionEntryPoint_getVarLayout((SlangReflectionEntryPoint*) this);\n        }\n\n        TypeLayoutReflection* getTypeLayout()\n        {\n            return getVarLayout()->getTypeLayout();\n        }\n\n        VariableLayoutReflection* getResultVarLayout()\n        {\n            return (VariableLayoutReflection*) spReflectionEntryPoint_getResultVarLayout((SlangReflectionEntryPoint*) this);\n        }\n\n        bool hasDefaultConstantBuffer()\n        {\n            return spReflectionEntryPoint_hasDefaultConstantBuffer((SlangReflectionEntryPoint*) this) != 0;\n        }\n    };\n    typedef EntryPointReflection EntryPointLayout;\n\n    struct TypeParameterReflection\n    {\n        char const* getName()\n        {\n            return spReflectionTypeParameter_GetName((SlangReflectionTypeParameter*) this);\n        }\n        unsigned getIndex()\n        {\n            return spReflectionTypeParameter_GetIndex((SlangReflectionTypeParameter*) this);\n        }\n        unsigned getConstraintCount()\n        {\n            return spReflectionTypeParameter_GetConstraintCount((SlangReflectionTypeParameter*) this);\n        }\n        TypeReflection* getConstraintByIndex(int index)\n        {\n            return (TypeReflection*)spReflectionTypeParameter_GetConstraintByIndex((SlangReflectionTypeParameter*) this, index);\n        }\n    };\n\n    enum class LayoutRules : SlangLayoutRulesIntegral\n    {\n        Default = SLANG_LAYOUT_RULES_DEFAULT,\n    };\n\n    typedef struct ShaderReflection ProgramLayout;\n\n    struct ShaderReflection\n    {\n        unsigned getParameterCount()\n        {\n            return spReflection_GetParameterCount((SlangReflection*) this);\n        }\n\n        unsigned getTypeParameterCount()\n        {\n            return spReflection_GetTypeParameterCount((SlangReflection*) this);\n        }\n\n        TypeParameterReflection* getTypeParameterByIndex(unsigned index)\n        {\n            return (TypeParameterReflection*)spReflection_GetTypeParameterByIndex((SlangReflection*) this, index);\n        }\n\n        TypeParameterReflection* findTypeParameter(char const* name)\n        {\n            return (TypeParameterReflection*)spReflection_FindTypeParameter((SlangReflection*)this, name);\n        }\n\n        VariableLayoutReflection* getParameterByIndex(unsigned index)\n        {\n            return (VariableLayoutReflection*) spReflection_GetParameterByIndex((SlangReflection*) this, index);\n        }\n\n        static ProgramLayout* get(SlangCompileRequest* request)\n        {\n            return (ProgramLayout*) spGetReflection(request);\n        }\n\n        SlangUInt getEntryPointCount()\n        {\n            return spReflection_getEntryPointCount((SlangReflection*) this);\n        }\n\n        EntryPointReflection* getEntryPointByIndex(SlangUInt index)\n        {\n            return (EntryPointReflection*) spReflection_getEntryPointByIndex((SlangReflection*) this, index);\n        }\n\n        SlangUInt getGlobalConstantBufferBinding()\n        {\n            return spReflection_getGlobalConstantBufferBinding((SlangReflection*)this);\n        }\n\n        size_t getGlobalConstantBufferSize()\n        {\n            return spReflection_getGlobalConstantBufferSize((SlangReflection*)this);\n        }\n\n        TypeReflection* findTypeByName(const char* name)\n        {\n            return (TypeReflection*)spReflection_FindTypeByName(\n                (SlangReflection*) this,\n                name);\n        }\n\n        TypeLayoutReflection* getTypeLayout(\n            TypeReflection* type,\n            LayoutRules     rules = LayoutRules::Default)\n        {\n            return (TypeLayoutReflection*)spReflection_GetTypeLayout(\n                (SlangReflection*) this,\n                (SlangReflectionType*)type,\n                SlangLayoutRules(rules));\n        }\n\n        EntryPointReflection* findEntryPointByName(const char* name)\n        {\n            return (EntryPointReflection*)spReflection_findEntryPointByName(\n                (SlangReflection*) this,\n                name);\n        }\n\n        TypeReflection* specializeType(\n            TypeReflection*         type,\n            SlangInt                specializationArgCount,\n            TypeReflection* const*  specializationArgs,\n            ISlangBlob**            outDiagnostics)\n        {\n            return (TypeReflection*) spReflection_specializeType(\n                (SlangReflection*) this,\n                (SlangReflectionType*) type,\n                specializationArgCount,\n                (SlangReflectionType* const*) specializationArgs,\n                outDiagnostics);\n        }\n\n        SlangUInt getHashedStringCount() const { return spReflection_getHashedStringCount((SlangReflection*)this); }\n\n        const char* getHashedString(SlangUInt index, size_t* outCount) const\n        {\n            return spReflection_getHashedString((SlangReflection*)this, index, outCount);\n        }\n\n        TypeLayoutReflection* getGlobalParamsTypeLayout()\n        {\n            return (TypeLayoutReflection*) spReflection_getGlobalParamsTypeLayout((SlangReflection*) this);\n        }\n\n        VariableLayoutReflection* getGlobalParamsVarLayout()\n        {\n            return (VariableLayoutReflection*) spReflection_getGlobalParamsVarLayout((SlangReflection*) this);\n        }\n    };\n\n    typedef uint32_t CompileStdLibFlags;\n    struct CompileStdLibFlag\n    {\n        enum Enum : CompileStdLibFlags\n        {\n            WriteDocumentation = 0x1,\n        };\n    };\n\n    typedef ISlangBlob IBlob;\n\n    struct IComponentType;\n    struct ITypeConformance;\n    struct IGlobalSession;\n    struct IModule;\n    struct ISession;\n\n    struct SessionDesc;\n    struct SpecializationArg;\n    struct TargetDesc;\n\n        /** A global session for interaction with the Slang library.\n\n        An application may create and re-use a single global session across\n        multiple sessions, in order to amortize startups costs (in current\n        Slang this is mostly the cost of loading the Slang standard library).\n\n        The global session is currently *not* thread-safe and objects created from\n        a single global session should only be used from a single thread at\n        a time.\n        */\n    struct IGlobalSession : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0xc140b5fd, 0xc78, 0x452e, { 0xba, 0x7c, 0x1a, 0x1e, 0x70, 0xc7, 0xf7, 0x1c })\n\n            /** Create a new session for loading and compiling code.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL createSession(\n            SessionDesc const&  desc,\n            ISession**          outSession) = 0;\n\n            /** Look up the internal ID of a profile by its `name`.\n\n            Profile IDs are *not* guaranteed to be stable across versions\n            of the Slang library, so clients are expected to look up\n            profiles by name at runtime.\n            */\n        virtual SLANG_NO_THROW SlangProfileID SLANG_MCALL findProfile(\n            char const*     name) = 0;\n\n            /** Set the path that downstream compilers (aka back end compilers) will\n            be looked from.\n            @param passThrough Identifies the downstream compiler\n            @param path The path to find the downstream compiler (shared library/dll/executable)\n\n            For back ends that are dlls/shared libraries, it will mean the path will\n            be prefixed with the path when calls are made out to ISlangSharedLibraryLoader.\n            For executables - it will look for executables along the path */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPath(\n            SlangPassThrough passThrough,\n            char const* path) = 0;\n\n            /** DEPRECIATED: Use setLanguagePrelude\n\n            Set the 'prelude' for generated code for a 'downstream compiler'.\n            @param passThrough The downstream compiler for generated code that will have the prelude applied to it. \n            @param preludeText The text added pre-pended verbatim before the generated source\n\n            That for pass-through usage, prelude is not pre-pended, preludes are for code generation only. \n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPrelude(\n            SlangPassThrough passThrough,\n            const char* preludeText) = 0;\n\n            /** DEPRECIATED: Use getLanguagePrelude\n\n            Get the 'prelude' for generated code for a 'downstream compiler'.\n            @param passThrough The downstream compiler for generated code that will have the prelude applied to it. \n            @param outPrelude  On exit holds a blob that holds the string of the prelude.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL getDownstreamCompilerPrelude(\n            SlangPassThrough passThrough,\n            ISlangBlob** outPrelude) = 0;\n\n            /** Get the build version 'tag' string. The string is the same as produced via `git describe --tags`\n            for the project. If Slang is built separately from the automated build scripts\n            the contents will by default be 'unknown'. Any string can be set by changing the\n            contents of 'slang-tag-version.h' file and recompiling the project.\n\n            This method will return exactly the same result as the free function spGetBuildTagString.\n\n            @return The build tag string\n            */\n        virtual SLANG_NO_THROW const char* SLANG_MCALL getBuildTagString() = 0;\n\n            /* For a given source language set the default compiler.\n            If a default cannot be chosen (for example the target cannot be achieved by the default),\n            the default will not be used. \n\n            @param sourceLanguage the source language \n            @param defaultCompiler the default compiler for that language\n            @return \n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL setDefaultDownstreamCompiler(\n            SlangSourceLanguage sourceLanguage,\n            SlangPassThrough defaultCompiler) = 0;\n\n            /* For a source type get the default compiler \n\n            @param sourceLanguage the source language \n            @return The downstream compiler for that source language */\n        virtual SlangPassThrough SLANG_MCALL getDefaultDownstreamCompiler(\n            SlangSourceLanguage sourceLanguage) = 0;\n\n            /* Set the 'prelude' placed before generated code for a specific language type.\n            \n            @param sourceLanguage The language the prelude should be inserted on.\n            @param preludeText The text added pre-pended verbatim before the generated source\n\n            Note! That for pass-through usage, prelude is not pre-pended, preludes are for code generation only. \n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setLanguagePrelude(\n            SlangSourceLanguage sourceLanguage,\n            const char* preludeText) = 0;\n\n            /** Get the 'prelude' associated with a specific source language. \n            @param sourceLanguage The language the prelude should be inserted on.\n            @param outPrelude  On exit holds a blob that holds the string of the prelude.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL getLanguagePrelude(\n            SlangSourceLanguage sourceLanguage,\n            ISlangBlob** outPrelude) = 0;\n\n            /** Create a compile request.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest(\n            slang::ICompileRequest** outCompileRequest) = 0;\n\n            /** Add new builtin declarations to be used in subsequent compiles.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addBuiltins(\n            char const*     sourcePath,\n            char const*     sourceString) = 0;\n\n            /** Set the session shared library loader. If this changes the loader, it may cause shared libraries to be unloaded\n            @param loader The loader to set. Setting nullptr sets the default loader. \n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setSharedLibraryLoader(\n            ISlangSharedLibraryLoader* loader) = 0;\n\n            /** Gets the currently set shared library loader\n            @return Gets the currently set loader. If returns nullptr, it's the default loader\n            */\n        virtual SLANG_NO_THROW ISlangSharedLibraryLoader* SLANG_MCALL getSharedLibraryLoader() = 0;\n\n            /** Returns SLANG_OK if a the compilation target is supported for this session\n            \n            @param target The compilation target to test\n            @return SLANG_OK if the target is available\n            SLANG_E_NOT_IMPLEMENTED if not implemented in this build\n            SLANG_E_NOT_FOUND if other resources (such as shared libraries) required to make target work could not be found\n            SLANG_FAIL other kinds of failures */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL checkCompileTargetSupport(\n            SlangCompileTarget  target) = 0;\n\n            /** Returns SLANG_OK if a the pass through support is supported for this session\n            @param session Session\n            @param target The compilation target to test\n            @return SLANG_OK if the target is available\n            SLANG_E_NOT_IMPLEMENTED if not implemented in this build\n            SLANG_E_NOT_FOUND if other resources (such as shared libraries) required to make target work could not be found\n            SLANG_FAIL other kinds of failures */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL checkPassThroughSupport(\n            SlangPassThrough    passThrough) = 0;\n\n            /** Compile from (embedded source) the StdLib on the session.\n            Will return a failure if there is already a StdLib available\n            NOTE! API is experimental and not ready for production code\n            @param flags to control compilation\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL compileStdLib(CompileStdLibFlags flags) = 0;\n\n            /** Load the StdLib. Currently loads modules from the file system. \n            @param stdLib Start address of the serialized stdlib\n            @param stdLibSizeInBytes The size in bytes of the serialized stdlib\n\n            NOTE! API is experimental and not ready for production code\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadStdLib(const void* stdLib, size_t stdLibSizeInBytes) = 0;\n\n            /** Save the StdLib modules to the file system\n            @param archiveType The type of archive used to hold the stdlib\n            @param outBlob The serialized blob containing the standard library\n\n            NOTE! API is experimental and not ready for production code  */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveStdLib(SlangArchiveType archiveType, ISlangBlob** outBlob) = 0;\n\n            /** Look up the internal ID of a capability by its `name`.\n\n            Capability IDs are *not* guaranteed to be stable across versions\n            of the Slang library, so clients are expected to look up\n            capabilities by name at runtime.\n            */\n        virtual SLANG_NO_THROW SlangCapabilityID SLANG_MCALL findCapability(\n            char const*     name) = 0;\n\n            /** Set the downstream/pass through compiler to be used for a transition from the source type to the target type\n            @param source The source 'code gen target'\n            @param target The target 'code gen target'\n            @param compiler The compiler/pass through to use for the transition from source to target\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) = 0;\n\n            /** Get the downstream/pass through compiler for a transition specified by source and target\n            @param source The source 'code gen target'\n            @param target The target 'code gen target'\n            @return The compiler that is used for the transition. Returns SLANG_PASS_THROUGH_NONE it is not defined\n            */\n        virtual SLANG_NO_THROW SlangPassThrough SLANG_MCALL getDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target) = 0;\n\n            /** Get the time in seconds spent in the downstream compiler.\n            @return The time spent in the downstream compiler in the current global session.\n            */\n        virtual SLANG_NO_THROW double SLANG_MCALL getDownstreamCompilerElapsedTime() = 0;\n    };\n\n    #define SLANG_UUID_IGlobalSession IGlobalSession::getTypeGuid()\n\n    /*!\n    @brief A request for one or more compilation actions to be performed.\n    */\n    struct ICompileRequest : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE( 0x96d33993, 0x317c, 0x4db5, { 0xaf, 0xd8, 0x66, 0x6e, 0xe7, 0x72, 0x48, 0xe2 } )\n   \n            /** Set the filesystem hook to use for a compile request\n\n            The provided `fileSystem` will be used to load any files that\n            need to be loaded during processing of the compile `request`.\n            This includes:\n\n              - Source files loaded via `spAddTranslationUnitSourceFile`\n              - Files referenced via `#include`\n              - Files loaded to resolve `#import` operations\n                */\n        virtual SLANG_NO_THROW void SLANG_MCALL setFileSystem(\n            ISlangFileSystem*       fileSystem) = 0;\n\n            /*!\n            @brief Set flags to be used for compilation.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setCompileFlags(\n            SlangCompileFlags       flags) = 0;\n\n            /*!\n            @brief Returns the compilation flags previously set with `setCompileFlags`\n            */\n        virtual SLANG_NO_THROW SlangCompileFlags SLANG_MCALL getCompileFlags() = 0;\n\n            /*!\n            @brief Set whether to dump intermediate results (for debugging) or not.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediates(\n            int                     enable) = 0;\n\n        virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediatePrefix(\n            const char* prefix) = 0;\n\n            /*!\n            @brief Set whether (and how) `#line` directives should be output.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setLineDirectiveMode(\n            SlangLineDirectiveMode  mode) = 0;\n\n            /*!\n            @brief Sets the target for code generation.\n            @param target The code generation target. Possible values are:\n            - SLANG_GLSL. Generates GLSL code.\n            - SLANG_HLSL. Generates HLSL code.\n            - SLANG_SPIRV. Generates SPIR-V code.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setCodeGenTarget(\n            SlangCompileTarget target) = 0;\n\n            /*!\n            @brief Add a code-generation target to be used.\n            */\n        virtual SLANG_NO_THROW int SLANG_MCALL addCodeGenTarget(\n            SlangCompileTarget      target) = 0;\n\n        virtual SLANG_NO_THROW void SLANG_MCALL setTargetProfile(\n            int                     targetIndex,\n            SlangProfileID          profile) = 0;\n\n        virtual SLANG_NO_THROW void SLANG_MCALL setTargetFlags(\n            int                     targetIndex,\n            SlangTargetFlags        flags) = 0;\n\n\n            /*!\n            @brief Set the floating point mode (e.g., precise or fast) to use a target.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setTargetFloatingPointMode(\n            int                     targetIndex,\n            SlangFloatingPointMode  mode) = 0;\n\n            /* DEPRECATED: use `spSetMatrixLayoutMode` instead. */\n        virtual SLANG_NO_THROW void SLANG_MCALL setTargetMatrixLayoutMode(\n            int                     targetIndex,\n            SlangMatrixLayoutMode   mode) = 0;\n\n        virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode(\n            SlangMatrixLayoutMode   mode) = 0;\n\n            /*!\n            @brief Set the level of debug information to produce.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoLevel(\n            SlangDebugInfoLevel     level) = 0;\n\n            /*!\n            @brief Set the level of optimization to perform.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setOptimizationLevel(\n            SlangOptimizationLevel  level) = 0;\n\n\n    \n            /*!\n            @brief Set the container format to be used for binary output.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setOutputContainerFormat(\n            SlangContainerFormat    format) = 0;\n\n        virtual SLANG_NO_THROW void SLANG_MCALL setPassThrough(\n            SlangPassThrough        passThrough) = 0;\n\n    \n        virtual SLANG_NO_THROW void SLANG_MCALL setDiagnosticCallback(\n            SlangDiagnosticCallback callback,\n            void const*             userData) = 0;\n\n        virtual SLANG_NO_THROW void SLANG_MCALL setWriter(\n            SlangWriterChannel      channel, \n            ISlangWriter*           writer) = 0;\n\n        virtual SLANG_NO_THROW ISlangWriter* SLANG_MCALL getWriter(\n            SlangWriterChannel      channel) = 0;\n\n            /*!\n            @brief Add a path to use when searching for referenced files.\n            This will be used for both `#include` directives and also for explicit `__import` declarations.\n            @param ctx The compilation context.\n            @param searchDir The additional search directory.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addSearchPath(\n            const char*             searchDir) = 0;\n\n            /*!\n            @brief Add a macro definition to be used during preprocessing.\n            @param key The name of the macro to define.\n            @param value The value of the macro to define.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addPreprocessorDefine(\n            const char*             key,\n            const char*             value) = 0;\n\n            /*!\n            @brief Set options using arguments as if specified via command line.\n            @return Returns SlangResult. On success SLANG_SUCCEEDED(result) is true.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL processCommandLineArguments(\n            char const* const*      args,\n            int                     argCount) = 0;\n\n            /** Add a distinct translation unit to the compilation request\n\n            `name` is optional. \n            Returns the zero-based index of the translation unit created.\n            */\n        virtual SLANG_NO_THROW int SLANG_MCALL addTranslationUnit(\n            SlangSourceLanguage     language,\n            char const*             name) = 0;\n\n    \n            /** Set a default module name. Translation units will default to this module name if one is not\n            passed. If not set each translation unit will get a unique name. \n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDefaultModuleName(\n            const char* defaultModuleName) = 0;\n\n            /** Add a preprocessor definition that is scoped to a single translation unit.\n\n            @param translationUnitIndex The index of the translation unit to get the definition.\n            @param key The name of the macro to define.\n            @param value The value of the macro to define.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitPreprocessorDefine(\n            int                     translationUnitIndex,\n            const char*             key,\n            const char*             value) = 0;\n\n\n            /** Add a source file to the given translation unit.\n\n            If a user-defined file system has been specified via\n            `spSetFileSystem`, then it will be used to load the\n            file at `path`. Otherwise, Slang will use the OS\n            file system.\n\n            This function does *not* search for a file using\n            the registered search paths (`spAddSearchPath`),\n            and instead using the given `path` as-is.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceFile(\n            int                     translationUnitIndex,\n            char const*             path) = 0;\n\n            /** Add a source string to the given translation unit.\n\n            @param translationUnitIndex The index of the translation unit to add source to.\n            @param path The file-system path that should be assumed for the source code.\n            @param source A null-terminated UTF-8 encoded string of source code.\n\n            The implementation will make a copy of the source code data.\n            An application may free the buffer immediately after this call returns.\n\n            The `path` will be used in any diagnostic output, as well\n            as to determine the base path when resolving relative\n            `#include`s.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceString(\n            int                     translationUnitIndex,\n            char const*             path,\n            char const*             source) = 0;\n\n\n            /** Add a slang library - such that its contents can be referenced during linking.\n            This is equivalent to the -r command line option.\n\n            @param libData The library data\n            @param libDataSize The size of the library data\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL addLibraryReference(\n            const void* libData,\n            size_t libDataSize) = 0;\n\n            /** Add a source string to the given translation unit.\n\n            @param translationUnitIndex The index of the translation unit to add source to.\n            @param path The file-system path that should be assumed for the source code.\n            @param sourceBegin A pointer to a buffer of UTF-8 encoded source code.\n            @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin`\n\n            The implementation will make a copy of the source code data.\n            An application may free the buffer immediately after this call returns.\n\n            The `path` will be used in any diagnostic output, as well\n            as to determine the base path when resolving relative\n            `#include`s.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceStringSpan(\n            int                     translationUnitIndex,\n            char const*             path,\n            char const*             sourceBegin,\n            char const*             sourceEnd) = 0;\n\n            /** Add a blob of source code to the given translation unit.\n\n            @param translationUnitIndex The index of the translation unit to add source to.\n            @param path The file-system path that should be assumed for the source code.\n            @param sourceBlob A blob containing UTF-8 encoded source code.\n            @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin`\n\n            The compile request will retain a reference to the blob.\n\n            The `path` will be used in any diagnostic output, as well\n            as to determine the base path when resolving relative\n            `#include`s.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceBlob(\n            int                     translationUnitIndex,\n            char const*             path,\n            ISlangBlob*             sourceBlob) = 0;\n\n            /** Add an entry point in a particular translation unit\n            */\n        virtual SLANG_NO_THROW int SLANG_MCALL addEntryPoint(\n            int                     translationUnitIndex,\n            char const*             name,\n            SlangStage              stage) = 0;\n\n            /** Add an entry point in a particular translation unit,\n                with additional arguments that specify the concrete\n                type names for entry-point generic type parameters.\n            */\n        virtual SLANG_NO_THROW int SLANG_MCALL addEntryPointEx(\n            int                     translationUnitIndex,\n            char const*             name,\n            SlangStage              stage,\n            int                     genericArgCount,\n            char const**            genericArgs) = 0;\n\n            /** Specify the arguments to use for global generic parameters.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL setGlobalGenericArgs(\n            int                     genericArgCount,\n            char const**            genericArgs) = 0;\n\n            /** Specify the concrete type to be used for a global \"existential slot.\"\n\n            Every shader parameter (or leaf field of a `struct`-type shader parameter)\n            that has an interface or array-of-interface type introduces an existential\n            slot. The number of slots consumed by a shader parameter, and the starting\n            slot of each parameter can be queried via the reflection API using\n            `SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM`.\n\n            In order to generate specialized code, a concrete type needs to be specified\n            for each existential slot. This function specifies the name of the type\n            (or in general a type *expression*) to use for a specific slot at the\n            global scope.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForGlobalExistentialTypeParam(\n            int                     slotIndex,\n            char const*             typeName) = 0;\n\n            /** Specify the concrete type to be used for an entry-point \"existential slot.\"\n\n            Every shader parameter (or leaf field of a `struct`-type shader parameter)\n            that has an interface or array-of-interface type introduces an existential\n            slot. The number of slots consumed by a shader parameter, and the starting\n            slot of each parameter can be queried via the reflection API using\n            `SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM`.\n\n            In order to generate specialized code, a concrete type needs to be specified\n            for each existential slot. This function specifies the name of the type\n            (or in general a type *expression*) to use for a specific slot at the\n            entry-point scope.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForEntryPointExistentialTypeParam(\n            int                     entryPointIndex,\n            int                     slotIndex,\n            char const*             typeName) = 0;\n\n            /** Execute the compilation request.\n\n            @returns  SlangResult, SLANG_OK on success. Use SLANG_SUCCEEDED() and SLANG_FAILED() to test SlangResult.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile() = 0;\n\n\n            /** Get any diagnostic messages reported by the compiler.\n\n            @returns A null-terminated UTF-8 encoded string of diagnostic messages.\n\n            The returned pointer is only guaranteed to be valid\n            until `request` is destroyed. Applications that wish to\n            hold on to the diagnostic output for longer should use\n            `getDiagnosticOutputBlob`.\n            */\n        virtual SLANG_NO_THROW char const* SLANG_MCALL getDiagnosticOutput() = 0;\n\n            /** Get diagnostic messages reported by the compiler.\n\n            @param outBlob A pointer to receive a blob holding a nul-terminated UTF-8 encoded string of diagnostic messages.\n            @returns A `SlangResult` indicating success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getDiagnosticOutputBlob(\n            ISlangBlob**            outBlob) = 0;\n\n\n            /** Get the number of files that this compilation depended on.\n\n            This includes both the explicit source files, as well as any\n            additional files that were transitively referenced (e.g., via\n            a `#include` directive).\n            */\n        virtual SLANG_NO_THROW int SLANG_MCALL getDependencyFileCount() = 0;\n\n            /** Get the path to a file this compilation depended on.\n            */\n        virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath(\n            int                     index) = 0;\n\n            /** Get the number of translation units associated with the compilation request\n            */\n        virtual SLANG_NO_THROW int SLANG_MCALL getTranslationUnitCount() = 0;\n\n            /** Get the output source code associated with a specific entry point.\n\n            The lifetime of the output pointer is the same as `request`.\n            */\n        virtual SLANG_NO_THROW char const* SLANG_MCALL getEntryPointSource(\n            int                     entryPointIndex) = 0;\n\n            /** Get the output bytecode associated with a specific entry point.\n\n            The lifetime of the output pointer is the same as `request`.\n            */\n        virtual SLANG_NO_THROW void const* SLANG_MCALL getEntryPointCode(\n            int                     entryPointIndex,\n            size_t*                 outSize) = 0;\n\n            /** Get the output code associated with a specific entry point.\n\n            @param entryPointIndex The index of the entry point to get code for.\n            @param targetIndex The index of the target to get code for (default: zero).\n            @param outBlob A pointer that will receive the blob of code\n            @returns A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCodeBlob(\n            int                     entryPointIndex,\n            int                     targetIndex,\n            ISlangBlob**            outBlob) = 0;\n\n            /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface.\n\n            That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope.\n\n            NOTE! Requires a compilation target of SLANG_HOST_CALLABLE.\n    \n            @param entryPointIndex  The index of the entry point to get code for.\n            @param targetIndex      The index of the target to get code for (default: zero).\n            @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on.\n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable(\n            int                     entryPointIndex,\n            int                     targetIndex,\n            ISlangSharedLibrary**   outSharedLibrary) = 0;\n\n            /** Get the output code associated with a specific target.\n\n            @param targetIndex The index of the target to get code for (default: zero).\n            @param outBlob A pointer that will receive the blob of code\n            @returns A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCodeBlob(\n            int                     targetIndex,\n            ISlangBlob**            outBlob) = 0;\n\n            /** Get 'callable' functions for a target accessible through the ISlangSharedLibrary interface.\n\n            That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope.\n\n            NOTE! Requires a compilation target of SLANG_HOST_CALLABLE.\n    \n            @param targetIndex      The index of the target to get code for (default: zero).\n            @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on.\n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetHostCallable(\n            int                     targetIndex,\n            ISlangSharedLibrary**   outSharedLibrary) = 0;\n\n            /** Get the output bytecode associated with an entire compile request.\n\n            The lifetime of the output pointer is the same as `request` and the last spCompile.\n\n            @param outSize          The size of the containers contents in bytes. Will be zero if there is no code available.\n            @returns                Pointer to start of the contained data, or nullptr if there is no code available.\n            */\n        virtual SLANG_NO_THROW void const* SLANG_MCALL getCompileRequestCode(\n            size_t*                 outSize) = 0;\n\n            /** Return the container code as a blob. The container blob is created as part of a compilation (with spCompile),\n            and a container is produced with a suitable ContainerFormat. \n\n            @param outSize          The blob containing the container data. \n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getContainerCode(\n            ISlangBlob**            outBlob) = 0;\n\n            /** Load repro from memory specified.\n\n            Should only be performed on a newly created request.\n\n            NOTE! When using the fileSystem, files will be loaded via their `unique names` as if they are part of the flat file system. This\n            mechanism is described more fully in docs/repro.md.\n\n            @param fileSystem       An (optional) filesystem. Pass nullptr to just use contents of repro held in data.\n            @param data             The data to load from.\n            @param size             The size of the data to load from. \n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadRepro(\n            ISlangFileSystem* fileSystem,\n            const void* data,\n            size_t size) = 0;\n\n            /** Save repro state. Should *typically* be performed after spCompile, so that everything\n            that is needed for a compilation is available. \n\n            @param outBlob          Blob that will hold the serialized state\n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveRepro(\n            ISlangBlob** outBlob) = 0;\n\n            /** Enable repro capture.\n\n            Should be set after any ISlangFileSystem has been set, but before any compilation. It ensures that everything\n            that the ISlangFileSystem accesses will be correctly recorded.\n            Note that if a ISlangFileSystem/ISlangFileSystemExt isn't explicitly set (ie the default is used), then the\n            request will automatically be set up to record everything appropriate. \n\n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL enableReproCapture() = 0;\n\n            /** Get the (linked) program for a compile request.\n\n            The linked program will include all of the global-scope modules for the\n            translation units in the program, plus any modules that they `import`\n            (transitively), specialized to any global specialization arguments that\n            were provided via the API.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getProgram(\n            slang::IComponentType** outProgram) = 0;\n\n            /** Get the (partially linked) component type for an entry point.\n\n            The returned component type will include the entry point at the\n            given index, and will be specialized using any specialization arguments\n            that were provided for it via the API.\n\n            The returned component will *not* include the modules representing\n            the global scope and its dependencies/specialization, so a client\n            program will typically want to compose this component type with\n            the one returned by `spCompileRequest_getProgram` to get a complete\n            and usable component type from which kernel code can be requested.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPoint(\n            SlangInt                entryPointIndex,\n            slang::IComponentType** outEntryPoint) = 0;\n\n            /** Get the (un-linked) module for a translation unit.\n\n            The returned module will not be linked against any dependencies,\n            nor against any entry points (even entry points declared inside\n            the module). Similarly, the module will not be specialized\n            to the arguments that might have been provided via the API.\n\n            This function provides an atomic unit of loaded code that\n            is suitable for looking up types and entry points in the\n            given module, and for linking together to produce a composite\n            program that matches the needs of an application.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getModule(\n            SlangInt                translationUnitIndex,\n            slang::IModule**        outModule) = 0;\n\n            /** Get the `ISession` handle behind the `SlangCompileRequest`.\n            TODO(JS): Arguably this should just return the session pointer.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSession(\n            slang::ISession** outSession) = 0;\n\n            /** get reflection data from a compilation request */\n        virtual SLANG_NO_THROW SlangReflection* SLANG_MCALL getReflection() = 0;\n\n            /** Make output specially handled for command line output */\n        virtual SLANG_NO_THROW void SLANG_MCALL setCommandLineCompilerMode() = 0;\n\n            /** Add a defined capability that should be assumed available on the target */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL addTargetCapability(\n            SlangInt            targetIndex,\n            SlangCapabilityID   capability) = 0;\n\n            /** Get the (linked) program for a compile request, including all entry points.\n\n            The resulting program will include all of the global-scope modules for the\n            translation units in the program, plus any modules that they `import`\n            (transitively), specialized to any global specialization arguments that\n            were provided via the API, as well as all entry points specified for compilation,\n            specialized to their entry-point specialization arguments.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getProgramWithEntryPoints(\n            slang::IComponentType** outProgram) = 0;\n\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL isParameterLocationUsed(\n            SlangInt entryPointIndex,\n            SlangInt targetIndex,\n            SlangParameterCategory category,\n            SlangUInt spaceIndex,\n            SlangUInt registerIndex,\n            bool& outUsed) = 0;\n\n            /** Set the line directive mode for a target.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setTargetLineDirectiveMode(\n            SlangInt targetIndex,\n            SlangLineDirectiveMode mode) = 0;\n\n            /** Set whether to use scalar buffer layouts for GLSL/Vulkan targets.\n                If true, the generated GLSL/Vulkan code will use `scalar` layout for storage buffers.\n                If false, the resulting code will std430 for storage buffers.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceGLSLScalarBufferLayout(int targetIndex, bool forceScalarLayout) = 0;\n\n            /** Overrides the severity of a specific diagnostic message.\n\n            @param messageID            Numeric identifier of the message to override,\n                                        as defined in the 1st parameter of the DIAGNOSTIC macro.\n            @param overrideSeverity     New severity of the message. If the message is originally Error or Fatal,\n                                        the new severity cannot be lower than that.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL overrideDiagnosticSeverity(\n            SlangInt messageID,\n            SlangSeverity overrideSeverity) = 0;\n\n            /** Returns the currently active flags of the request's diagnostic sink. */\n        virtual SLANG_NO_THROW SlangDiagnosticFlags SLANG_MCALL getDiagnosticFlags() = 0;\n\n            /** Sets the flags of the request's diagnostic sink.\n                The previously specified flags are discarded. */\n        virtual SLANG_NO_THROW void SLANG_MCALL setDiagnosticFlags(SlangDiagnosticFlags flags) = 0;\n    };\n\n    #define SLANG_UUID_ICompileRequest ICompileRequest::getTypeGuid()\n\n        /** Description of a code generation target.\n        */\n    struct TargetDesc\n    {\n            /** The size of this structure, in bytes.\n            */\n        size_t structureSize = sizeof(TargetDesc);\n\n            /** The target format to generate code for (e.g., SPIR-V, DXIL, etc.)\n            */\n        SlangCompileTarget      format = SLANG_TARGET_UNKNOWN;\n\n            /** The compilation profile supported by the target (e.g., \"Shader Model 5.1\")\n            */\n        SlangProfileID          profile = SLANG_PROFILE_UNKNOWN;\n\n            /** Flags for the code generation target. Currently unused. */\n        SlangTargetFlags        flags = 0;\n\n            /** Default mode to use for floating-point operations on the target.\n            */\n        SlangFloatingPointMode  floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT;\n\n            /** Optimization level to use for the target.\n            */\n        SlangOptimizationLevel optimizationLevel = SLANG_OPTIMIZATION_LEVEL_DEFAULT;\n\n            /** The line directive mode for output source code.\n            */\n        SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT;\n\n            /** Whether to force `scalar` layout for glsl shader storage buffers.\n            */\n        bool forceGLSLScalarBufferLayout = false;\n    };\n\n    typedef uint32_t SessionFlags;\n    enum\n    {\n        kSessionFlags_None = 0,\n\n        /** Use application-specific policy for semantics of the `shared` keyword.\n        \n        This is a legacy/compatibility flag to help an existing Slang client\n        migrate to new language features, and should *not* be used by other\n        clients. This feature may be removed in a future release without a\n        deprecation warning, and this bit may be re-used for another feature.\n        You have been warned.\n        */\n        kSessionFlag_FalcorCustomSharedKeywordSemantics = 1 << 0,\n    };\n\n    struct PreprocessorMacroDesc\n    {\n        const char* name;\n        const char* value;\n    };\n\n    struct SessionDesc\n    {\n            /** The size of this structure, in bytes.\n             */\n        size_t structureSize = sizeof(SessionDesc);\n\n            /** Code generation targets to include in the session.\n            */\n        TargetDesc const*   targets = nullptr;\n        SlangInt            targetCount = 0;\n\n            /** Flags to configure the session.\n            */\n        SessionFlags flags = kSessionFlags_None;\n\n            /** Default layout to assume for variables with matrix types.\n            */\n        SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR;\n\n            /** Paths to use when searching for `#include`d or `import`ed files.\n            */\n        char const* const*  searchPaths = nullptr;\n        SlangInt            searchPathCount = 0;\n\n        PreprocessorMacroDesc const*    preprocessorMacros = nullptr;\n        SlangInt                        preprocessorMacroCount = 0;\n\n        ISlangFileSystem* fileSystem = nullptr;\n    };\n\n    enum class ContainerType\n    {\n        None, UnsizedArray, StructuredBuffer, ConstantBuffer, ParameterBlock\n    };\n\n    // A struct storing a single hash represented as a four element uint32_t array.\n    // This is intended to be used with the current MD5 hashing implementation.\n    struct Digest\n    {\n        uint32_t values[4] = { 0 };\n\n        bool operator==(const Digest& rhs)\n        {\n            return values[0] == rhs.values[0]\n                && values[1] == rhs.values[1]\n                && values[2] == rhs.values[2]\n                && values[3] == rhs.values[3];\n        }\n\n        uint32_t getHashCode()\n        {\n            return values[0];\n        }\n    };\n\n        /** A session provides a scope for code that is loaded.\n\n        A session can be used to load modules of Slang source code,\n        and to request target-specific compiled binaries and layout\n        information.\n\n        In order to be able to load code, the session owns a set\n        of active \"search paths\" for resolving `#include` directives\n        and `import` declrations, as well as a set of global\n        preprocessor definitions that will be used for all code\n        that gets `import`ed in the session.\n\n        If multiple user shaders are loaded in the same session,\n        and import the same module (e.g., two source files do `import X`)\n        then there will only be one copy of `X` loaded within the session.\n\n        In order to be able to generate target code, the session\n        owns a list of available compilation targets, which specify\n        code generation options.\n\n        Code loaded and compiled within a session is owned by the session\n        and will remain resident in memory until the session is released.\n        Applications wishing to control the memory usage for compiled\n        and loaded code should use multiple sessions.\n        */\n    struct ISession : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE( 0x67618701, 0xd116, 0x468f, { 0xab, 0x3b, 0x47, 0x4b, 0xed, 0xce, 0xe, 0x3d } )\n\n            /** Get the global session thas was used to create this session.\n            */\n        virtual SLANG_NO_THROW IGlobalSession* SLANG_MCALL getGlobalSession() = 0;\n\n            /** Load a module as it would be by code using `import`.\n            */\n        virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModule(\n            const char* moduleName,\n            IBlob**     outDiagnostics = nullptr) = 0;\n\n            /** Load a module from Slang source code.\n            */\n        virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromSource(\n            const char* moduleName,\n            const char* path,\n            slang::IBlob* source,\n            slang::IBlob** outDiagnostics = nullptr) = 0;\n\n            /** Combine multiple component types to create a composite component type.\n\n            The `componentTypes` array must contain `componentTypeCount` pointers\n            to component types that were loaded or created using the same session.\n\n            The shader parameters and specialization parameters of the composite will\n            be the union of those in `componentTypes`. The relative order of child\n            component types is significant, and will affect the order in which\n            parameters are reflected and laid out.\n\n            The entry-point functions of the composite will be the union of those in\n            `componentTypes`, and will follow the ordering of `componentTypes`.\n\n            The requirements of the composite component type will be a subset of\n            those in `componentTypes`. If an entry in `componentTypes` has a requirement\n            that can be satisfied by another entry, then the composition will\n            satisfy the requirement and it will not appear as a requirement of\n            the composite. If multiple entries in `componentTypes` have a requirement\n            for the same type, then only the first such requirement will be retained\n            on the composite. The relative ordering of requirements on the composite\n            will otherwise match that of `componentTypes`.\n\n            If any diagnostics are generated during creation of the composite, they\n            will be written to `outDiagnostics`. If an error is encountered, the\n            function will return null.\n\n            It is an error to create a composite component type that recursively\n            aggregates the a single module more than once.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompositeComponentType(\n            IComponentType* const*  componentTypes,\n            SlangInt                componentTypeCount,\n            IComponentType**        outCompositeComponentType,\n            ISlangBlob**            outDiagnostics = nullptr) = 0;\n\n            /** Specialize a type based on type arguments.\n            */\n        virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL specializeType(\n            TypeReflection*             type,\n            SpecializationArg const*    specializationArgs,\n            SlangInt                    specializationArgCount,\n            ISlangBlob**                outDiagnostics = nullptr) = 0;\n\n\n            /** Get the layout `type` on the chosen `target`.\n            */\n        virtual SLANG_NO_THROW TypeLayoutReflection* SLANG_MCALL getTypeLayout(\n            TypeReflection* type,\n            SlangInt        targetIndex = 0,\n            LayoutRules     rules = LayoutRules::Default,\n            ISlangBlob**    outDiagnostics = nullptr) = 0;\n\n            /** Get a container type from `elementType`. For example, given type `T`, returns\n                a type that represents `StructuredBuffer<T>`.\n\n                @param `elementType`: the element type to wrap around.\n                @param `containerType`: the type of the container to wrap `elementType` in.\n                @param `outDiagnostics`: a blob to receive diagnostic messages.\n            */\n        virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL getContainerType(\n            TypeReflection* elementType,\n            ContainerType containerType,\n            ISlangBlob** outDiagnostics = nullptr) = 0;\n\n            /** Return a `TypeReflection` that represents the `__Dynamic` type.\n                This type can be used as a specialization argument to indicate using\n                dynamic dispatch.\n            */\n        virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL getDynamicType() = 0;\n\n            /** Get the mangled name for a type RTTI object.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeRTTIMangledName(\n            TypeReflection* type,\n            ISlangBlob** outNameBlob) = 0;\n\n            /** Get the mangled name for a type witness.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessMangledName(\n            TypeReflection* type,\n            TypeReflection* interfaceType,\n            ISlangBlob** outNameBlob) = 0;\n\n            /** Get the sequential ID used to identify a type witness in a dynamic object.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessSequentialID(\n            slang::TypeReflection* type,\n            slang::TypeReflection* interfaceType,\n            uint32_t*              outId) = 0;\n\n            /** Create a request to load/compile front-end code.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest(\n            SlangCompileRequest**   outCompileRequest) = 0;\n\n        \n            /** Creates a `IComponentType` that represents a type's conformance to an interface.\n                The retrieved `ITypeConformance` objects can be included in a composite `IComponentType`\n                to explicitly specify which implementation types should be included in the final compiled\n                code. For example, if an module defines `IMaterial` interface and `AMaterial`,\n                `BMaterial`, `CMaterial` types that implements the interface, the user can exclude\n                `CMaterial` implementation from the resulting shader code by explcitly adding\n                `AMaterial:IMaterial` and `BMaterial:IMaterial` conformances to a composite\n                `IComponentType` and get entry point code from it. The resulting code will not have\n                anything related to `CMaterial` in the dynamic dispatch logic. If the user does not\n                explicitly include any `TypeConformances` to an interface type, all implementations to\n                that interface will be included by default. By linking a `ITypeConformance`, the user is\n                also given the opportunity to specify the dispatch ID of the implementation type. If\n                `conformanceIdOverride` is -1, there will be no override behavior and Slang will\n                automatically assign IDs to implementation types. The automatically assigned IDs can be\n                queried via `ISession::getTypeConformanceWitnessSequentialID`.\n\n                Returns SLANG_OK if succeeds, or SLANG_FAIL if `type` does not conform to `interfaceType`.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL createTypeConformanceComponentType(\n            slang::TypeReflection* type,\n            slang::TypeReflection* interfaceType,\n            ITypeConformance** outConformance,\n            SlangInt conformanceIdOverride,\n            ISlangBlob** outDiagnostics) = 0;\n    };\n\n    #define SLANG_UUID_ISession ISession::getTypeGuid()\n\n        /** A component type is a unit of shader code layout, reflection, and linking.\n\n        A component type is a unit of shader code that can be included into\n        a linked and compiled shader program. Each component type may have:\n\n        * Zero or more uniform shader parameters, representing textures,\n          buffers, etc. that the code in the component depends on.\n\n        * Zero or more *specialization* parameters, which are type or\n          value parameters that can be used to synthesize specialized\n          versions of the component type.\n\n        * Zero or more entry points, which are the individually invocable\n          kernels that can have final code generated.\n\n        * Zero or more *requirements*, which are other component\n          types on which the component type depends.\n\n        One example of a component type is a module of Slang code:\n\n        * The global-scope shader parameters declared in the module are\n          the parameters when considered as a component type.\n\n        * Any global-scope generic or interface type parameters introduce\n          specialization parameters for the module.\n\n        * A module does not by default include any entry points when\n          considered as a component type (although the code of the\n          module might *declare* some entry points).\n\n        * Any other modules that are `import`ed in the source code\n          become requirements of the module, when considered as a\n          component type.\n\n        An entry point is another example of a component type:\n\n        * The `uniform` parameters of the entry point function are\n          its shader parameters when considered as a component type.\n\n        * Any generic or interface-type parameters of the entry point\n          introduce specialization parameters.\n\n        * An entry point component type exposes a single entry point (itself).\n\n        * An entry point has one requirement for the module in which\n          it was defined.\n\n        Component types can be manipulated in a few ways:\n\n        * Multiple component types can be combined into a composite, which\n          combines all of their code, parameters, etc.\n\n        * A component type can be specialized, by \"plugging in\" types and\n          values for its specialization parameters.\n\n        * A component type can be laid out for a particular target, giving\n          offsets/bindings to the shader parameters it contains.\n\n        * Generated kernel code can be requested for entry points.\n\n        */\n    struct IComponentType : public ISlangUnknown\n    {\n        SLANG_COM_INTERFACE(0x5bc42be8, 0x5c50, 0x4929, { 0x9e, 0x5e, 0xd1, 0x5e, 0x7c, 0x24, 0x1, 0x5f })\n\n            /** Get the runtime session that this component type belongs to.\n            */\n        virtual SLANG_NO_THROW ISession* SLANG_MCALL getSession() = 0;\n\n            /** Get the layout for this program for the chosen `targetIndex`.\n\n            The resulting layout will establish offsets/bindings for all\n            of the global and entry-point shader parameters in the\n            component type.\n\n            If this component type has specialization parameters (that is,\n            it is not fully specialized), then the resulting layout may\n            be incomplete, and plugging in arguments for generic specialization\n            parameters may result in a component type that doesn't have\n            a compatible layout. If the component type only uses\n            interface-type specialization parameters, then the layout\n            for a specialization should be compatible with an unspecialized\n            layout (all parameters in the unspecialized layout will have\n            the same offset/binding in the specialized layout).\n\n            If this component type is combined into a composite, then\n            the absolute offsets/bindings of parameters may not stay the same.\n            If the shader parameters in a component type don't make\n            use of explicit binding annotations (e.g., `register(...)`),\n            then the *relative* offset of shader parameters will stay\n            the same when it is used in a composition.\n            */\n        virtual SLANG_NO_THROW ProgramLayout* SLANG_MCALL getLayout(\n            SlangInt    targetIndex = 0,\n            IBlob**     outDiagnostics = nullptr) = 0;\n\n            /** Get the number of (unspecialized) specialization parameters for the component type.\n            */\n        virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() = 0;\n\n            /** Get the compiled code for the entry point at `entryPointIndex` for the chosen `targetIndex`\n\n            Entry point code can only be computed for a component type that\n            has no specialization parameters (it must be fully specialized)\n            and that has no requirements (it must be fully linked).\n\n            If code has not already been generated for the given entry point and target,\n            then a compilation error may be detected, in which case `outDiagnostics`\n            (if non-null) will be filled in with a blob of messages diagnosing the error.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode(\n            SlangInt    entryPointIndex,\n            SlangInt    targetIndex,\n            IBlob**     outCode,\n            IBlob**     outDiagnostics = nullptr) = 0;\n\n            /** Compute the hash code of all dependencies for this component type. This generally means file path\n                dependencies but can also include the component's name or sub-components. The dependency-based\n                hash effectively represents all the files that may be included/imported by a component type along with\n                any non-code-specific that helps define a component. This can be useful to simply check for a component\n                type without needing to inspect the code. For example, a shader cache might key its entries using the\n                dependency-based hash in order to determine at a glance if a particular shader is present, with no\n                regard for the shader's contents.\n\n                This function should only have a meaningful implementation in ComponentType. All other types derived from\n                ComponentType that also inherit from IComponentType should do nothing.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL computeDependencyBasedHash(\n            SlangInt entryPointIndex,\n            SlangInt targetIndex,\n            Digest* outHash) = 0;\n\n            /** Compute the hash code of this component type's contents as indicated by the file dependencies.\n                This hash is ideal when we need to confirm whether shader code changes have occurred. For example,\n                a shader cache needs to be able to check when a cache entry contains out-of-date code, which can be\n                easily detected by comparing the contents-based hashes since they will directly reflect any change\n                to the shader's code.\n\n                This function should only have a meaningful implementation in ComponentType. All other types derived\n                from ComponentType that also inherit from IComponentType should do nothing. However, the only component\n                type that should ever be hashing its contents is Module as it represents all the code in a given\n                translation unit.\n            */\n        virtual SLANG_NO_THROW void SLANG_MCALL computeContentsBasedHash(Digest* outHash) = 0;\n\n            /** Specialize the component by binding its specialization parameters to concrete arguments.\n\n            The `specializationArgs` array must have `specializationArgCount` entries, and\n            this must match the number of specialization parameters on this component type.\n\n            If any diagnostics (error or warnings) are produced, they will be written to `outDiagnostics`.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize(\n            SpecializationArg const*    specializationArgs,\n            SlangInt                    specializationArgCount,\n            IComponentType**            outSpecializedComponentType,\n            ISlangBlob**                outDiagnostics = nullptr) = 0;\n\n            /** Link this component type against all of its unsatisifed dependencies.\n            \n            A component type may have unsatisfied dependencies. For example, a module\n            depends on any other modules it `import`s, and an entry point depends\n            on the module that defined it.\n\n            A user can manually satisfy dependencies by creating a composite\n            component type, and when doing so they retain full control over\n            the relative ordering of shader parameters in the resulting layout.\n\n            It is an error to try to generate/access compiled kernel code for\n            a component type with unresolved dependencies, so if dependencies\n            remain after whatever manual composition steps an application\n            cares to peform, the `link()` function can be used to automatically\n            compose in any remaining dependencies. The order of parameters\n            (and hence the global layout) that results will be deterministic,\n            but is not currently documented.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL link(\n            IComponentType**            outLinkedComponentType,\n            ISlangBlob**                outDiagnostics = nullptr) = 0;\n\n            /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface.\n\n            The functions remain in scope as long as the ISlangSharedLibrary interface is in scope.\n\n            NOTE! Requires a compilation target of SLANG_HOST_CALLABLE.\n    \n            @param entryPointIndex  The index of the entry point to get code for.\n            @param targetIndex      The index of the target to get code for (default: zero).\n            @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on.\n            @returns                A `SlangResult` to indicate success or failure.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable(\n            int                     entryPointIndex,\n            int                     targetIndex,\n            ISlangSharedLibrary**   outSharedLibrary,\n            slang::IBlob**          outDiagnostics = 0) = 0;\n\n            /** Get a new ComponentType object that represents a renamed entry point.\n\n            The current object must be a single EntryPoint, or a CompositeComponentType or\n            SpecializedComponentType that contains one EntryPoint component.\n            */\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint(\n            const char* newName, IComponentType** outEntryPoint) = 0;\n    };\n    #define SLANG_UUID_IComponentType IComponentType::getTypeGuid()\n\n    struct IEntryPoint : public IComponentType\n    {\n        SLANG_COM_INTERFACE(0x8f241361, 0xf5bd, 0x4ca0, { 0xa3, 0xac, 0x2, 0xf7, 0xfa, 0x24, 0x2, 0xb8 })\n    };\n\n    #define SLANG_UUID_IEntryPoint IEntryPoint::getTypeGuid()\n\n    struct ITypeConformance : public IComponentType\n    {\n        SLANG_COM_INTERFACE(0x73eb3147, 0xe544, 0x41b5, { 0xb8, 0xf0, 0xa2, 0x44, 0xdf, 0x21, 0x94, 0xb })\n    };\n    #define SLANG_UUID_ITypeConformance ITypeConformance::getTypeGuid()\n\n        /** A module is the granularity of shader code compilation and loading.\n\n        In most cases a module corresponds to a single compile \"translation unit.\"\n        This will often be a single `.slang` or `.hlsl` file and everything it\n        `#include`s.\n\n        Notably, a module `M` does *not* include the things it `import`s, as these\n        as distinct modules that `M` depends on. There is a directed graph of\n        module dependencies, and all modules in the graph must belong to the\n        same session (`ISession`).\n\n        A module establishes a namespace for looking up types, functions, etc.\n        */\n    struct IModule : public IComponentType\n    {\n        SLANG_COM_INTERFACE(0xc720e64, 0x8722, 0x4d31, { 0x89, 0x90, 0x63, 0x8a, 0x98, 0xb1, 0xc2, 0x79 })\n\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL findEntryPointByName(\n            char const*     name,\n            IEntryPoint**   outEntryPoint) = 0;\n\n        /// Get number of entry points defined in the module. An entry point defined in a module\n        /// is by default not included in the linkage, so calls to `IComponentType::getEntryPointCount`\n        /// on an `IModule` instance will always return 0. However `IModule::getDefinedEntryPointCount`\n        /// will return the number of defined entry points.\n        virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDefinedEntryPointCount() = 0;\n        /// Get the name of an entry point defined in the module.\n        virtual SLANG_NO_THROW SlangResult SLANG_MCALL\n            getDefinedEntryPoint(SlangInt32 index, IEntryPoint** outEntryPoint) = 0;\n    };\n    \n    #define SLANG_UUID_IModule IModule::getTypeGuid()\n\n        /** Argument used for specialization to types/values.\n        */\n    struct SpecializationArg\n    {\n        enum class Kind : int32_t\n        {\n            Unknown,    /**< An invalid specialization argument. */\n            Type,       /**< Specialize to a type. */\n        };\n\n        /** The kind of specialization argument. */\n        Kind kind;\n        union\n        {\n            /** A type specialization argument, used for `Kind::Type`. */\n            TypeReflection* type;\n        };\n\n        static SpecializationArg fromType(TypeReflection* inType)\n        {\n            SpecializationArg rs;\n            rs.kind = Kind::Type;\n            rs.type = inType;\n            return rs;\n        }\n    };\n}\n\n// Passed into functions to create globalSession to identify the API version client code is\n// using. \n#define SLANG_API_VERSION 0\n\n/* Create a global session, with built in StdLib.\n\n@param apiVersion Pass in SLANG_API_VERSION\n@param outGlobalSession (out)The created global session. \n*/\nSLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSession(\n    SlangInt                apiVersion,\n    slang::IGlobalSession** outGlobalSession);\n\n/* Create a global session, but do not set up the stdlib. The stdlib can\nthen be loaded via loadStdLib or compileStdLib\n\n@param apiVersion Pass in SLANG_API_VERSION\n@param outGlobalSession (out)The created global session that doesn't have a StdLib setup.\n\nNOTE! API is experimental and not ready for production code \n*/\nSLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSessionWithoutStdLib(\n    SlangInt                apiVersion,\n    slang::IGlobalSession** outGlobalSession);\n\n/* Returns a blob that contains the serialized stdlib.\nReturns nullptr if there isn't an embedded stdlib.\n*/\nSLANG_API ISlangBlob* slang_getEmbeddedStdLib();\n\nnamespace slang\n{\n    inline SlangResult createGlobalSession(\n        slang::IGlobalSession** outGlobalSession)\n    {\n        return slang_createGlobalSession(SLANG_API_VERSION, outGlobalSession);\n    }\n}\n\n/** @see slang::ICompileRequest::getProgram\n*/\nSLANG_EXTERN_C SLANG_API SlangResult spCompileRequest_getProgram(\n    SlangCompileRequest*    request,\n    slang::IComponentType** outProgram);\n\n/** @see slang::ICompileRequest::getProgramWithEntryPoints\n*/\nSLANG_EXTERN_C SLANG_API SlangResult spCompileRequest_getProgramWithEntryPoints(\n    SlangCompileRequest*    request,\n    slang::IComponentType** outProgram);\n\n/** @see slang::ICompileRequest::getEntryPoint\n*/\nSLANG_EXTERN_C SLANG_API SlangResult spCompileRequest_getEntryPoint(\n    SlangCompileRequest*    request,\n    SlangInt                entryPointIndex,\n    slang::IComponentType** outEntryPoint);\n\n/** @see slang::ICompileRequest::getModule\n*/\nSLANG_EXTERN_C SLANG_API SlangResult spCompileRequest_getModule(\n    SlangCompileRequest*    request,\n    SlangInt                translationUnitIndex,\n    slang::IModule**        outModule);\n\n/** @see slang::ICompileRequest::getSession\n*/\nSLANG_EXTERN_C SLANG_API SlangResult spCompileRequest_getSession(\n    SlangCompileRequest* request,\n    slang::ISession** outSession);\n#endif\n\n/* DEPRECATED DEFINITIONS\n\nEverything below this point represents deprecated APIs/definition that are only\nbeing kept around for source/binary compatibility with old client code. New\ncode should not use any of these declarations, and the Slang API will drop these\ndeclarations over time.\n*/\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define SLANG_ERROR_INSUFFICIENT_BUFFER SLANG_E_BUFFER_TOO_SMALL\n#define SLANG_ERROR_INVALID_PARAMETER SLANG_E_INVALID_ARG\n\nSLANG_API char const* spGetTranslationUnitSource(\n    SlangCompileRequest*    request,\n    int                     translationUnitIndex);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "Source/External/xmake.lua",
    "content": "add_requires(\"cereal\")\nadd_requires(\"glfw\", {configs = {shared = true}})\nadd_requires(\"spdlog\")\nadd_requires(\"stb\")\nadd_requires(\"glm\")\nadd_requires(\"glslang sdk-1.3.250.1\")\nadd_requires(\"spirv-cross\")\nadd_requires(\"spirv-reflect sdk-1.3.250.1\")\nadd_requires(\"directxshadercompiler\")\nadd_requires(\"assimp\", {configs = {shared = true}})\nadd_requires(\"imgui docking\")\nadd_requires(\"nativefiledialog\")\nadd_requires(\"meshoptimizer\")\nadd_requires(\"mustache\")\nadd_requires(\"slang\")\nadd_requires(\"volk\", {configs = {header_only = true}})\nadd_requires(\"vulkan-headers\")\nadd_requires(\"vulkan-memory-allocator v3.0.0\")\n\n-- option(\"CUDA_ENABLE\")\n--     on_check(function (option)\n--         import(\"detect.sdks.find_cuda\")\n--         local cuda = find_cuda()\n--         if cuda then\n--             option:enable(true)\n--             option:add(\"defines\", \"CUDA_ENABLE\")\n--         else\n--             option:enable(false)\n--         end\n--     end)\n-- option_end()\n\n-- if has_config(\"CUDA_ENABLE\") then\n--     add_requires(\"cuda\")\n-- end\n\ntarget(\"ImGui-Tools\")\n    set_kind(\"static\")\n\n    add_files(\"imgui_tools/**.cpp\")\n    add_headerfiles(\"imgui_tools/**.h\")\n    add_includedirs(\"imgui_tools/\", {public  = true})\n    add_packages(\"glfw\", \"imgui\")\n\n    set_group(\"External\")\ntarget_end()\n\npackage(\"mustache\")\n    on_load(function (package)\n        package:set(\"installdir\", path.join(os.scriptdir(), \"mustache\"))\n    end)\n\n    on_fetch(function (package)\n        local result = {}\n        result.includedirs = package:installdir()\n        return result\n    end)\npackage_end()\n\npackage(\"slang\")\n    on_load(function (package)\n        package:set(\"installdir\", path.join(os.scriptdir(), \"slang\"))\n    end)\n\n    on_fetch(function (package)\n        package:addenv(\"PATH\", package:installdir(\"bin/windows-x64/release\"))\n\n        local result = {}\n        result.links = \"slang\"\n        result.includedirs = package:installdir()\n        result.linkdirs = package:installdir(\"bin/windows-x64/release\")\n        return result\n    end)\npackage_end()\n\n"
  },
  {
    "path": "Source/Plugin/Editor/AnimationEditor.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/Resource/Animation.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\nusing namespace Ilum;\n\nclass AnimationEditor : public Widget\n{\n  public:\n\tstruct UniformBlock\n\t{\n\t\tglm::mat4 transform;\n\t};\n\n\tstruct BoneVertex\n\t{\n\t\talignas(16) glm::vec3 position;\n\t\tuint32_t bone_id;\n\t};\n\n  public:\n\tAnimationEditor(Editor *editor) :\n\t    Widget(\"Animation Editor\", editor)\n\t{\n\t\tm_uniform_buffer = p_editor->GetRHIContext()->CreateBuffer<UniformBlock>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\t\tm_pipeline_state = p_editor->GetRHIContext()->CreatePipelineState();\n\t\tm_render_target  = p_editor->GetRHIContext()->CreateRenderTarget();\n\n\t\tVertexInputState vertex_input_state = {};\n\t\tvertex_input_state.input_bindings   = {\n            VertexInputState::InputBinding{0, sizeof(BoneVertex), RHIVertexInputRate::Vertex}};\n\t\tvertex_input_state.input_attributes = {\n\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 0, 0, RHIFormat::R32_UINT, offsetof(BoneVertex, bone_id)},\n\t\t};\n\n\t\tBlendState blend_state = {};\n\t\tblend_state.attachment_states.resize(1);\n\n\t\tInputAssemblyState input_assembly_state = {};\n\t\tinput_assembly_state.topology           = RHIPrimitiveTopology::Triangle;\n\n\t\tDepthStencilState depth_stencil_state  = {};\n\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\tdepth_stencil_state.depth_write_enable = true;\n\n\t\tm_pipeline_state->SetVertexInputState(vertex_input_state);\n\t\tm_pipeline_state->SetBlendState(blend_state);\n\t\tm_pipeline_state->SetDepthStencilState(depth_stencil_state);\n\t\tm_pipeline_state->SetInputAssemblyState(input_assembly_state);\n\t}\n\n\tvirtual ~AnimationEditor() override = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tauto *resource = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Animation>(m_animation_name);\n\n\t\tImGui::Columns(2);\n\n\t\t// Inspector\n\t\t{\n\t\t\tImGui::BeginChild(\"Animation Editor Inspector\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\t\tImGui::Text(\"Animation Editor Inspector\");\n\n\t\t\tif (ImGui::TreeNode(\"Animation\"))\n\t\t\t{\n\t\t\t\tif (ImGui::Button(m_animation_name.c_str(), ImVec2(150.f, 20.f)))\n\t\t\t\t{\n\t\t\t\t\tm_animation_name = \"\";\n\t\t\t\t\tm_root.children.clear();\n\t\t\t\t\tm_root.name = \"\";\n\t\t\t\t}\n\n\t\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t\t{\n\t\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Animation\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tm_animation_name = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\t\tresource         = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Animation>(m_animation_name);\n\t\t\t\t\t\tif (resource)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_root = resource->GetHierarchyNode();\n\n\t\t\t\t\t\t\tglm::vec3 min_bound = glm::vec3(std::numeric_limits<float>::max());\n\t\t\t\t\t\t\tglm::vec3 max_bound = glm::vec3(-std::numeric_limits<float>::max());\n\n\t\t\t\t\t\t\tCalculateBound(resource, m_root, min_bound, max_bound);\n\n\t\t\t\t\t\t\t// Update skinned buffer\n\t\t\t\t\t\t\tUpdateBuffer(m_time);\n\n\t\t\t\t\t\t\t// Update vertex buffer\n\t\t\t\t\t\t\tstd::vector<BoneVertex> bone_vertices;\n\t\t\t\t\t\t\tUpdateVertexBuffer(bone_vertices, m_root, resource);\n\n\t\t\t\t\t\t\tm_vertex_buffer = p_editor->GetRHIContext()->CreateBuffer<BoneVertex>(bone_vertices.size(), RHIBufferUsage::Vertex | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t\t\t\t\tm_vertex_buffer->CopyToDevice(bone_vertices.data(), bone_vertices.size() * sizeof(BoneVertex));\n\n\t\t\t\t\t\t\tm_view.center  = 0.5f * (min_bound + max_bound);\n\t\t\t\t\t\t\tm_view.radius  = glm::length(max_bound - min_bound);\n\t\t\t\t\t\t\tm_scale_factor = m_view.radius;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tImGui::EndDragDropTarget();\n\t\t\t\t}\n\n\t\t\t\tImGui::SameLine();\n\n\t\t\t\tif (ImGui::Button(m_start ? \"Stop\" : \"Start\", ImVec2(150.f, 20.f)))\n\t\t\t\t{\n\t\t\t\t\tm_start = !m_start;\n\t\t\t\t}\n\n\t\t\t\tif (m_start)\n\t\t\t\t{\n\t\t\t\t\tm_time += ImGui::GetIO().DeltaTime;\n\t\t\t\t\tif (m_time > (resource ? resource->GetMaxTimeStamp() : 1000.f))\n\t\t\t\t\t{\n\t\t\t\t\t\tm_time -= resource ? resource->GetMaxTimeStamp() : 1000.f;\n\t\t\t\t\t}\n\t\t\t\t\tUpdateBuffer(m_time);\n\t\t\t\t}\n\n\t\t\t\tif (ImGui::SliderFloat(\"Time\", &m_time, 0.f, resource ? resource->GetMaxTimeStamp() : 1000.f))\n\t\t\t\t{\n\t\t\t\t\tUpdateBuffer(m_time);\n\t\t\t\t}\n\n\t\t\t\t// Draw hierarchy\n\t\t\t\tif (!m_animation_name.empty())\n\t\t\t\t{\n\t\t\t\t\tDrawHierarchy(resource, m_root);\n\t\t\t\t}\n\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\n\t\t\tif (ImGui::TreeNode(\"Skinned Meshes\"))\n\t\t\t{\n\t\t\t\tfor (auto &skinned_mesh : m_skinned_meshes)\n\t\t\t\t{\n\t\t\t\t\tImGui::PushID(skinned_mesh.c_str());\n\n\t\t\t\t\tif (ImGui::Button(skinned_mesh.c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8f, 30.f)))\n\t\t\t\t\t{\n\t\t\t\t\t\tskinned_mesh = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t\t\t{\n\t\t\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"SkinnedMesh\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tskinned_mesh = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tImGui::PopID();\n\t\t\t\t}\n\n\t\t\t\tif (ImGui::Button(\"+\"))\n\t\t\t\t{\n\t\t\t\t\tm_skinned_meshes.emplace_back(\"\");\n\t\t\t\t}\n\n\t\t\t\tImGui::SameLine();\n\n\t\t\t\tif (ImGui::Button(\"-\"))\n\t\t\t\t{\n\t\t\t\t\tm_skinned_meshes.pop_back();\n\t\t\t\t}\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\n\t\t\tImGui::EndChild();\n\t\t}\n\n\t\tImGui::NextColumn();\n\n\t\tUpdateCamera(ImGui::GetColumnWidth(1), ImGui::GetContentRegionAvail().y);\n\n\t\t// Model Viewer\n\t\tif (resource)\n\t\t{\n\t\t\tRender(static_cast<uint32_t>(ImGui::GetColumnWidth(1)), static_cast<uint32_t>(ImGui::GetContentRegionAvail().y));\n\t\t\tif (m_render_texture)\n\t\t\t{\n\t\t\t\tImGui::Image(m_render_texture.get(), ImVec2{ImGui::GetColumnWidth(1), ImGui::GetContentRegionAvail().y});\n\t\t\t}\n\t\t}\n\n\t\tImGui::End();\n\t}\n\n\tvoid UpdateVertexBuffer(std::vector<BoneVertex> &vertices, const HierarchyNode &node, Resource<ResourceType::Animation> *resource, Bone *parent = nullptr, glm::mat4 parent_transform = glm::mat4(1.f))\n\t{\n\t\tauto *bone = resource->GetBone(node.name);\n\n\t\tif (bone)\n\t\t{\n\t\t\tuint32_t current_id = bone->GetBoneID();\n\t\t\tif (parent)\n\t\t\t{\n\t\t\t\tBoneVertex p0 = {}, p1 = {};\n\t\t\t\tp0.bone_id  = parent->GetBoneID();\n\t\t\t\tp1.bone_id  = current_id;\n\t\t\t\tp0.position = glm::vec3(parent_transform * glm::vec4(0.f, 0.f, 0.f, 1.f));\n\t\t\t\tp1.position = glm::vec3(parent_transform * node.transform * glm::vec4(0.f, 0.f, 0.f, 1.f));\n\n\t\t\t\tvertices.push_back(p0);\n\t\t\t\tvertices.push_back(p1);\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &child : node.children)\n\t\t{\n\t\t\tUpdateVertexBuffer(vertices, child, resource, bone, parent_transform * node.transform);\n\t\t}\n\t}\n\n\tvoid DrawHierarchy(Resource<ResourceType::Animation> *resource, const HierarchyNode &node)\n\t{\n\t\tBone *bone = resource->GetBone(node.name);\n\n\t\tbool open = false;\n\t\tif (bone)\n\t\t{\n\t\t\topen = ImGui::TreeNodeEx(node.name.c_str(), node.children.empty() ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_None);\n\t\t}\n\n\t\tif (!bone || open)\n\t\t{\n\t\t\tfor (auto &child : node.children)\n\t\t\t{\n\t\t\t\tDrawHierarchy(resource, child);\n\t\t\t}\n\t\t}\n\n\t\tif (open)\n\t\t{\n\t\t\tImGui::TreePop();\n\t\t}\n\t}\n\n\tvoid CalculateBound(Resource<ResourceType::Animation> *resource, const HierarchyNode &node, glm::vec3 &min_bound, glm::vec3 &max_bound, glm::mat4 parent = glm::mat4(1.f))\n\t{\n\t\tBone *bone = resource->GetBone(node.name);\n\n\t\tglm::mat4 global_transformation = parent * node.transform;\n\n\t\tif (bone)\n\t\t{\n\t\t\tglobal_transformation = parent * bone->GetLocalTransform(0.f);\n\n\t\t\tglm::vec3 position = glm::vec3(global_transformation * bone->GetBoneOffset() * glm::vec4(0.f, 0.f, 0.f, 1.f));\n\n\t\t\tmin_bound = glm::min(min_bound, position);\n\t\t\tmax_bound = glm::max(max_bound, position);\n\t\t}\n\n\t\tfor (auto &child : node.children)\n\t\t{\n\t\t\tCalculateBound(resource, child, min_bound, max_bound, global_transformation);\n\t\t}\n\t}\n\n\tvoid CalculateBoneTransform(float time, Resource<ResourceType::Animation> *resource, const HierarchyNode &node, glm::mat4 *&skinned_matrices, glm::mat4 parent = glm::mat4(1.f))\n\t{\n\t\tBone *bone = resource->GetBone(node.name);\n\n\t\tglm::mat4 global_transformation = parent * node.transform;\n\n\t\tif (bone)\n\t\t{\n\t\t\tglobal_transformation = parent * bone->GetLocalTransform(time);\n\t\t\tif (skinned_matrices)\n\t\t\t{\n\t\t\t\tuint32_t  bone_id = bone->GetBoneID();\n\t\t\t\tglm::mat4 offset  = bone->GetBoneOffset();\n\n\t\t\t\tskinned_matrices[bone_id] = global_transformation * offset;\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &child : node.children)\n\t\t{\n\t\t\tCalculateBoneTransform(time, resource, child, skinned_matrices, global_transformation);\n\t\t}\n\t}\n\n\tvoid UpdateBuffer(float time)\n\t{\n\t\tauto *resource    = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Animation>(m_animation_name);\n\t\tauto *rhi_context = p_editor->GetRHIContext();\n\t\tif (resource)\n\t\t{\n\t\t\tif (!m_skinned_buffer || m_skinned_buffer->GetDesc().size != resource->GetBoneCount() * sizeof(glm::mat4))\n\t\t\t{\n\t\t\t\tm_skinned_buffer = rhi_context->CreateBuffer<glm::mat4>((size_t) resource->GetMaxBoneIndex() + 1U, RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\n\t\t\tglm::mat4 *skinned_matrices = static_cast<glm::mat4 *>(m_skinned_buffer->Map());\n\n\t\t\tCalculateBoneTransform(time, resource, m_root, skinned_matrices);\n\n\t\t\tm_skinned_buffer->Unmap();\n\t\t}\n\t}\n\n\tvoid UpdateCamera(float width, float height)\n\t{\n\t\tfloat delta_time = ImGui::GetIO().DeltaTime;\n\n\t\tif (ImGui::IsWindowHovered())\n\t\t{\n\t\t\tif (ImGui::IsMouseDragging(ImGuiMouseButton_Right))\n\t\t\t{\n\t\t\t\tImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);\n\t\t\t\tImGui::ResetMouseDragDelta(ImGuiMouseButton_Right);\n\t\t\t\tm_view.phi -= delta.y * delta_time * 5.f;\n\t\t\t\tm_view.theta -= delta.x * delta_time * 5.f;\n\t\t\t}\n\t\t\tm_view.radius += m_scale_factor * ImGui::GetIO().MouseWheel * delta_time;\n\t\t}\n\n\t\tglm::vec3 position = m_view.center + m_view.radius * glm::vec3(glm::sin(glm::radians(m_view.phi)) * glm::sin(glm::radians(m_view.theta)), glm::cos(glm::radians(m_view.phi)), glm::sin(glm::radians(m_view.phi)) * glm::cos(glm::radians(m_view.theta)));\n\n\t\tUniformBlock block = {};\n\n\t\tglm::vec3 forward = glm::normalize(m_view.center - position);\n\t\tglm::vec3 right   = glm::normalize(glm::cross(forward, glm::vec3{0.f, 1.f, 0.f}));\n\t\tglm::vec3 up      = glm::normalize(glm::cross(right, forward));\n\t\tblock.transform   = glm::perspective(glm::radians(45.f), width / height, 0.01f, 1000.f) * glm::lookAt(position, m_view.center, up);\n\n\t\tm_uniform_buffer->CopyToDevice(&block, sizeof(block));\n\t}\n\n\tvoid Render(uint32_t width, uint32_t height)\n\t{\n\t\tauto *rhi_context = p_editor->GetRHIContext();\n\t\tauto *resource    = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Animation>(m_animation_name);\n\n\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\tcmd_buffer->Begin();\n\n\t\tif (!m_render_texture)\n\t\t{\n\t\t\tm_render_texture = rhi_context->CreateTexture2D(1000, 1000, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false);\n\t\t\tm_depth_texture  = rhi_context->CreateTexture2D(1000, 1000, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget, false);\n\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t    {TextureStateTransition{m_render_texture.get(), RHIResourceState::Undefined, RHIResourceState::RenderTarget, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t\t     TextureStateTransition{m_depth_texture.get(), RHIResourceState::Undefined, RHIResourceState::DepthWrite, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t\t\t    {});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_render_texture.get(), RHIResourceState::ShaderResource, RHIResourceState::RenderTarget, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}}, {});\n\t\t}\n\n\t\t{\n\t\t\tVertexInputState vertex_input_state = {};\n\t\t\tvertex_input_state.input_bindings   = {\n                VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex), RHIVertexInputRate::Vertex}};\n\t\t\tvertex_input_state.input_attributes = {\n\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, position)},\n\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 1, 0, RHIFormat::R32G32B32A32_SINT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, bones[0])},\n\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 2, 0, RHIFormat::R32G32B32A32_SINT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, bones[4])},\n\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Weights, 3, 0, RHIFormat::R32G32B32A32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, weights[0])},\n\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Weights, 4, 0, RHIFormat::R32G32B32A32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, weights[4])},\n\t\t\t};\n\n\t\t\tInputAssemblyState input_assembly_state = {};\n\t\t\tinput_assembly_state.topology           = RHIPrimitiveTopology::Triangle;\n\n\t\t\tRasterizationState rasterization_state = {};\n\t\t\trasterization_state.polygon_mode       = RHIPolygonMode::Solid;\n\t\t\trasterization_state.line_width         = 1.f;\n\n\t\t\tm_pipeline_state->SetVertexInputState(vertex_input_state);\n\t\t\tm_pipeline_state->SetInputAssemblyState(input_assembly_state);\n\t\t\tm_pipeline_state->SetRasterizationState(rasterization_state);\n\n\t\t\tauto *vertex_shader   = p_editor->GetRenderer()->RequireShader(\"./Source/Shaders/Editor/AnimationEditor.hlsl\", \"VSmain\", RHIShaderStage::Vertex);\n\t\t\tauto *fragment_shader = p_editor->GetRenderer()->RequireShader(\"./Source/Shaders/Editor/AnimationEditor.hlsl\", \"PSmain\", RHIShaderStage::Fragment);\n\n\t\t\tm_pipeline_state->ClearShader();\n\t\t\tm_pipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\t\tm_pipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader);\n\n\t\t\tShaderMeta meta = p_editor->GetRenderer()->RequireShaderMeta(vertex_shader);\n\t\t\tmeta += p_editor->GetRenderer()->RequireShaderMeta(fragment_shader);\n\n\t\t\tm_render_target->Clear();\n\t\t\tm_render_target->Set(0, m_render_texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, ColorAttachment{RHILoadAction::Clear, RHIStoreAction::Store});\n\t\t\tm_render_target->Set(m_depth_texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, DepthStencilAttachment{});\n\n\t\t\tauto *descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\tdescriptor->BindBuffer(\"UniformBuffer\", m_uniform_buffer.get())\n\t\t\t    .BindBuffer(\"BoneMatrices\", m_skinned_buffer.get());\n\n\t\t\tcmd_buffer->BeginRenderPass(m_render_target.get());\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(m_pipeline_state.get());\n\t\t\tcmd_buffer->SetViewport((float) m_render_target->GetWidth(), (float) m_render_target->GetHeight());\n\t\t\tcmd_buffer->SetScissor(m_render_target->GetWidth(), m_render_target->GetHeight());\n\n\t\t\tfor (auto &skinned_mesh_name : m_skinned_meshes)\n\t\t\t{\n\t\t\t\tauto *skinned_mesh = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::SkinnedMesh>(skinned_mesh_name);\n\t\t\t\tif (skinned_mesh)\n\t\t\t\t{\n\t\t\t\t\tcmd_buffer->BindVertexBuffer(0, skinned_mesh->GetVertexBuffer());\n\t\t\t\t\tcmd_buffer->BindIndexBuffer(skinned_mesh->GetIndexBuffer());\n\t\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(skinned_mesh->GetIndexCount()));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t}\n\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_render_texture.get(), RHIResourceState::RenderTarget, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}}, {});\n\t\tcmd_buffer->End();\n\t\trhi_context->Submit({cmd_buffer});\n\t}\n\n  private:\n\tstd::string m_animation_name = \"\";\n\n\tstd::vector<std::string> m_skinned_meshes;\n\n\tHierarchyNode m_root;\n\n\tstd::unique_ptr<RHIPipelineState> m_pipeline_state = nullptr;\n\tstd::unique_ptr<RHIRenderTarget>  m_render_target  = nullptr;\n\n\tstd::unique_ptr<RHITexture> m_render_texture = nullptr;\n\tstd::unique_ptr<RHITexture> m_depth_texture  = nullptr;\n\n\tbool m_wireframe = false;\n\n\tbool m_start = false;\n\n\tstd::unique_ptr<RHIBuffer> m_uniform_buffer = nullptr;\n\tstd::unique_ptr<RHIBuffer> m_skinned_buffer = nullptr;\n\tstd::unique_ptr<RHIBuffer> m_vertex_buffer  = nullptr;\n\n\tfloat m_scale_factor = 1.f;\n\n\tfloat m_time = 0.f;\n\n\tstruct\n\t{\n\t\tglm::vec3 center = glm::vec3(0.f);\n\t\tfloat     radius = 0.f;\n\t\tfloat     theta  = 0.f;\n\t\tfloat     phi    = 90.f;\n\t} m_view;\n};\n\nextern \"C\"\n{\n\tEXPORT_API AnimationEditor *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new AnimationEditor(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/Console.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/Editor/Hierarchy.cpp",
    "content": "#include <Scene/Components/AllComponents.hpp>\n#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Scene/Node.hpp>\n#include <Scene/Scene.hpp>\n\n#include <imgui.h>\n\nusing namespace Ilum;\n\nclass Hierarchy : public Widget\n{\n  public:\n\tHierarchy(Editor *editor) :\n\t    Widget(\"Hierarchy\", editor)\n\t{\n\t}\n\n\tvirtual ~Hierarchy() override = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tif (ImGui::BeginDragDropTarget())\n\t\t{\n\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Node\"))\n\t\t\t{\n\t\t\t\tif (pay_load->DataSize == sizeof(Node *))\n\t\t\t\t{\n\t\t\t\t\t(*static_cast<Node **>(pay_load->Data))->SetParent(nullptr);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tauto roots = p_editor->GetRenderer()->GetScene()->GetRoots();\n\n\t\tfor (auto *root : roots)\n\t\t{\n\t\t\tDrawNode(root);\n\t\t}\n\n\t\tif (ImGui::IsMouseDown(ImGuiMouseButton_Left) && ImGui::IsWindowHovered())\n\t\t{\n\t\t\tp_editor->SelectNode();\n\t\t}\n\n\t\tImGui::End();\n\t}\n\n\tvoid DrawNode(Node *node)\n\t{\n\t\tbool has_child = !node->GetChildren().empty();\n\n\t\tbool update = false;\n\n\t\t// Setting up\n\t\tImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(5, 5));\n\t\tImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_FramePadding | (p_editor->GetSelectedNode() == node ? ImGuiTreeNodeFlags_Selected : 0) | (has_child ? 0 : ImGuiTreeNodeFlags_Leaf);\n\n\t\tImGui::PushID(static_cast<int32_t>((uint64_t) node));\n\t\tbool open = ImGui::TreeNodeEx(std::to_string((uint64_t) node).c_str(), flags, \"%s\", node->GetName().empty() ? \" \" : node->GetName().c_str());\n\n\t\tImGui::PopStyleVar();\n\n\t\t// Delete node\n\t\tbool node_deleted = false;\n\t\tif (ImGui::BeginPopupContextItem(std::to_string((uint64_t) node).c_str()))\n\t\t{\n\t\t\tif (ImGui::MenuItem(\"Delete Entity\"))\n\t\t\t{\n\t\t\t\tnode_deleted = true;\n\t\t\t\tupdate       = true;\n\t\t\t}\n\t\t\tImGui::EndPopup();\n\t\t}\n\t\tImGui::PopID();\n\n\t\t// Select entity\n\t\tif (ImGui::IsItemClicked())\n\t\t{\n\t\t\tp_editor->SelectNode(node);\n\t\t}\n\n\t\t// Drag and drop\n\t\tif (ImGui::BeginDragDropSource())\n\t\t{\n\t\t\tImGui::SetDragDropPayload(\"Node\", &node, sizeof(Node *));\n\t\t\tImGui::EndDragDropSource();\n\t\t}\n\n\t\tif (ImGui::BeginDragDropTarget())\n\t\t{\n\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Node\"))\n\t\t\t{\n\t\t\t\tif (pay_load->DataSize == sizeof(Node *))\n\t\t\t\t{\n\t\t\t\t\tNode *new_son = *static_cast<Node **>(pay_load->Data);\n\t\t\t\t\tif (node->GetParent() != new_son)\n\t\t\t\t\t{\n\t\t\t\t\t\tnew_son->SetParent(node);\n\t\t\t\t\t\tnew_son->GetComponent<Cmpt::Transform>()->SetDirty();\n\t\t\t\t\t\tupdate = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tImGui::EndDragDropTarget();\n\t\t}\n\n\t\t// Recursively open children nodes\n\t\tif (open)\n\t\t{\n\t\t\tfor (auto *child : node->GetChildren())\n\t\t\t{\n\t\t\t\tDrawNode(child);\n\t\t\t}\n\t\t\tImGui::TreePop();\n\t\t}\n\n\t\t// Delete callback\n\t\tif (node_deleted)\n\t\t{\n\t\t\tauto *scene = p_editor->GetRenderer()->GetScene();\n\n\t\t\tif ((node->HasComponent<Cmpt::OrthographicCamera>() &&node->GetComponent<Cmpt::OrthographicCamera>()==p_editor->GetMainCamera())||\n\t\t\t    (node->HasComponent<Cmpt::PerspectiveCamera>() && node->GetComponent<Cmpt::PerspectiveCamera>() == p_editor->GetMainCamera()))\n\t\t\t{\n\t\t\t\tp_editor->SetMainCamera();\n\t\t\t}\n\n\t\t\tif (p_editor->GetSelectedNode() == node)\n\t\t\t{\n\t\t\t\tp_editor->SelectNode();\n\t\t\t}\n\n\t\t\tscene->EraseNode(node);\n\t\t}\n\t}\n};\n\nextern \"C\"\n{\n\t__declspec(dllexport) Hierarchy *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new Hierarchy(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/Inspector.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <RHI/RHIContext.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\nusing namespace Ilum;\n\nclass Inspector : public Widget\n{\n  public:\n\tInspector(Editor *editor) :\n\t    Widget(\"Inspector\", editor)\n\t{\n\t}\n\n\tvirtual ~Inspector() override = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tauto *select = p_editor->GetSelectedNode();\n\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\t// Draw node components\n\t\tif (select)\n\t\t{\n\t\t\tDrawNodeInspector(select);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDrawRendererInspector();\n\t\t}\n\n\t\tImGui::End();\n\t}\n\n\tvoid DrawNodeInspector(Node *node)\n\t{\n\t\t{\n\t\t\t// Name\n\t\t\tchar buf[64] = {0};\n\t\t\tstd::memcpy(buf, node->GetName().data(), sizeof(buf));\n\t\t\tImGui::PushItemWidth(150.f);\n\t\t\tif (ImGui::InputText(\"Tag\", buf, sizeof(buf)))\n\t\t\t{\n\t\t\t\tnode->SetName(buf);\n\t\t\t}\n\t\t\tImGui::PopItemWidth();\n\t\t}\n\n\t\tfor (auto &[type, cmpt] : node->GetComponents())\n\t\t{\n\t\t\tconst ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding;\n\n\t\t\tImVec2 content_region_available = ImGui::GetContentRegionAvail();\n\n\t\t\tImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{4, 4});\n\t\t\tfloat line_height = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f;\n\t\t\tbool  open        = ImGui::TreeNodeEx((void *) type.hash_code(), tree_node_flags, cmpt->GetName());\n\t\t\tImGui::PopStyleVar();\n\n\t\t\tbool update = false;\n\n\t\t\tif (open)\n\t\t\t{\n\t\t\t\tcmpt->OnImGui();\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid DrawRendererInspector()\n\t{\n\t\tconst ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding;\n\n\t\tauto *rhi_context  = p_editor->GetRHIContext();\n\t\tauto *renderer     = p_editor->GetRenderer();\n\t\tauto *render_graph = renderer->GetRenderGraph();\n\n\t\tif (ImGui::TreeNodeEx(\"Hardware Info\", tree_node_flags, \"Hardware Info\"))\n\t\t{\n\t\t\tImGui::Text(\"GPU: %s\", rhi_context->GetDeviceName().c_str());\n\t\t\tImGui::Text(\"Backend: %s\", rhi_context->GetBackend().c_str());\n\t\t\tImGui::Text(\"CUDA: %s\", rhi_context->HasCUDA() ? \"Enable\" : \"Disable\");\n\t\t\tImGui::TreePop();\n\t\t}\n\n\t\tif (render_graph && ImGui::TreeNodeEx(\"Profiler\", tree_node_flags, \"Profiler\"))\n\t\t{\n\t\t\t{\n\t\t\t\tstatic float t = 0;\n\t\t\t\tt += ImGui::GetIO().DeltaTime;\n\t\t\t\tif (t > 0.1f)\n\t\t\t\t{\n\t\t\t\t\tt = 0;\n\t\t\t\t\tif (ImGui::GetIO().Framerate != 0.0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (m_frame_times.size() < 50)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_frame_times.push_back(1000.0f / ImGui::GetIO().Framerate);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstd::rotate(m_frame_times.begin(), m_frame_times.begin() + 1, m_frame_times.end());\n\t\t\t\t\t\t\tm_frame_times.back() = 1000.0f / ImGui::GetIO().Framerate;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfloat min_frame_time = 0.f, max_frame_time = 0.f;\n\t\t\t\tfloat max_cpu_time = 0.f, max_gpu_time = 0.f;\n\n\t\t\t\tif (!m_frame_times.empty())\n\t\t\t\t{\n\t\t\t\t\tmin_frame_time = *std::min_element(m_frame_times.begin(), m_frame_times.end());\n\t\t\t\t\tmax_frame_time = *std::max_element(m_frame_times.begin(), m_frame_times.end());\n\t\t\t\t}\n\n\t\t\t\tstd::vector<float>        cpu_times;\n\t\t\t\tstd::vector<float>        gpu_times;\n\t\t\t\tstd::vector<const char *> pass_names;\n\n\t\t\t\tif (ImGui::BeginTable(\"CPU&GPU Time\", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders))\n\t\t\t\t{\n\t\t\t\t\tImGui::TableSetupColumn(\"Pass\");\n\t\t\t\t\tImGui::TableSetupColumn(\"CPU (ms)\");\n\t\t\t\t\tImGui::TableSetupColumn(\"GPU (ms)\");\n\t\t\t\t\tImGui::TableSetupColumn(\"Thread\");\n\t\t\t\t\tImGui::TableHeadersRow();\n\n\t\t\t\t\tuint32_t idx = 0;\n\t\t\t\t\tfor (const auto &pass : render_graph->GetRenderPasses())\n\t\t\t\t\t{\n\t\t\t\t\t\tconst auto &profiler_state = pass.profiler->GetProfileState();\n\n\t\t\t\t\t\tcpu_times.push_back(profiler_state.cpu_time);\n\t\t\t\t\t\tgpu_times.push_back(profiler_state.gpu_time);\n\t\t\t\t\t\tpass_names.push_back(pass.name.c_str());\n\n\t\t\t\t\t\tImGui::TableNextRow();\n\n\t\t\t\t\t\tImGui::TableSetColumnIndex(0);\n\t\t\t\t\t\tImGui::Text(\"%s\", (std::to_string(idx++) + \" - \" + pass.name).c_str());\n\t\t\t\t\t\tImGui::TableSetColumnIndex(1);\n\t\t\t\t\t\tImGui::Text(\"%f\", cpu_times.back());\n\t\t\t\t\t\tImGui::TableSetColumnIndex(2);\n\t\t\t\t\t\tImGui::Text(\"%f\", gpu_times.back());\n\t\t\t\t\t\tImGui::TableSetColumnIndex(3);\n\t\t\t\t\t\tImGui::Text(\"%zu\", profiler_state.thread_id);\n\t\t\t\t\t}\n\t\t\t\t\tImGui::EndTable();\n\t\t\t\t}\n\n\t\t\t\tif (!cpu_times.empty())\n\t\t\t\t{\n\t\t\t\t\tmax_cpu_time = *std::max_element(cpu_times.begin(), cpu_times.end());\n\t\t\t\t\tmax_gpu_time = *std::max_element(gpu_times.begin(), gpu_times.end());\n\t\t\t\t}\n\n\t\t\t\tImGui::PlotLines((\"Frame Time (\" + std::to_string(static_cast<uint32_t>(ImGui::GetIO().Framerate)) + \"fps)\").c_str(), m_frame_times.data(), static_cast<int>(m_frame_times.size()), 0, nullptr, min_frame_time * 0.8f, max_frame_time * 1.2f, ImVec2{0, 80});\n\t\t\t\tImGui::PlotHistogram(\"CPU Time\", cpu_times.data(), static_cast<int>(cpu_times.size()), 0, nullptr, 0.f, max_cpu_time * 1.2f, ImVec2(0, 80.0f));\n\t\t\t\tImGui::PlotHistogram(\"GPU Time\", gpu_times.data(), static_cast<int>(gpu_times.size()), 0, nullptr, 0.f, max_gpu_time * 1.2f, ImVec2(0, 80.0f));\n\t\t\t}\n\n\t\t\tImGui::TreePop();\n\t\t}\n\n\t\tif (render_graph && ImGui::TreeNodeEx(\"Render Info\", tree_node_flags, \"Render Info\"))\n\t\t{\n\t\t\tfor (const auto &pass : render_graph->GetRenderPasses())\n\t\t\t{\n\t\t\t\tImGui::PushID(&pass.config);\n\t\t\t\tif (!pass.config.Empty() && ImGui::TreeNodeEx(&pass, tree_node_flags, pass.name.c_str()))\n\t\t\t\t{\n\t\t\t\t\tPluginManager::GetInstance().Call<bool>(fmt::format(\"shared/RenderPass/RenderPass.{}.{}.dll\", pass.category, pass.name), \"OnImGui\", &pass.config, ImGui::GetCurrentContext());\n\t\t\t\t\tImGui::TreePop();\n\t\t\t\t}\n\t\t\t\tImGui::PopID();\n\t\t\t}\n\t\t\tImGui::TreePop();\n\t\t}\n\t}\n\n  private:\n\tstd::vector<float> m_frame_times;\n};\n\nextern \"C\"\n{\n\tEXPORT_API Inspector *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\tIlum::Cmpt::SetImGuiContext(context);\n\t\treturn new Inspector(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/MainMenu.cpp",
    "content": "#include <Scene/Components/AllComponents.hpp>\n#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Scene/Node.hpp>\n#include <Scene/Scene.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\n#include <nfd.h>\n\nusing namespace Ilum;\n\nclass MainMenu : public Widget\n{\n  public:\n\tMainMenu(Editor *editor) :\n\t    Widget(\"Main Menu\", editor)\n\t{\n\t}\n\n\tvirtual ~MainMenu() override = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tif (ImGui::BeginMainMenuBar())\n\t\t{\n\t\t\tif (ImGui::BeginMenu(\"Component\"))\n\t\t\t{\n\t\t\t\tif (ImGui::BeginMenu(\"Add Light\"))\n\t\t\t\t{\n\t\t\t\t\tif (ImGui::MenuItem(\"Spot Light\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Spot Light\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::SpotLight>(node));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ImGui::MenuItem(\"Point Light\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Point Light\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::PointLight>(node));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ImGui::MenuItem(\"Directional Light\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Directional Light\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::DirectionalLight>(node));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ImGui::MenuItem(\"Rectangle Light\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Rectangle Light\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::RectLight>(node));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ImGui::MenuItem(\"Environment Light\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Environment Light\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::EnvironmentLight>(node));\n\t\t\t\t\t}\n\n\t\t\t\t\tImGui::EndMenu();\n\t\t\t\t}\n\n\t\t\t\tif (ImGui::BeginMenu(\"Add Camera\"))\n\t\t\t\t{\n\t\t\t\t\tif (ImGui::MenuItem(\"Perspective Camera\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Perspective Camera\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tauto *camera = node->AddComponent(std::make_unique<Cmpt::PerspectiveCamera>(node));\n\n\t\t\t\t\t\tif (!p_editor->GetMainCamera())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tp_editor->SetMainCamera(camera);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ImGui::MenuItem(\"Orthographic Camera\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(\"Orthographic Camera\");\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\t\t\tnode->AddComponent(std::make_unique<Cmpt::OrthographicCamera>(node));\n\t\t\t\t\t}\n\n\t\t\t\t\tImGui::EndMenu();\n\t\t\t\t}\n\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\n\t\t\tImGui::EndMainMenuBar();\n\t\t}\n\t}\n};\n\nextern \"C\"\n{\n\tEXPORT_API MainMenu *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\tIlum::Cmpt::SetImGuiContext(context);\n\t\treturn new MainMenu(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/MaterialGraphEditor.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Material/MaterialData.hpp>\n#include <Material/MaterialGraph.hpp>\n#include <RenderGraph/RenderGraphBlackboard.hpp>\n#include <Renderer/RenderData.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/Resource/Material.hpp>\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n#include <imnodes/imnodes.h>\n\n#include <nfd.h>\n\nusing namespace Ilum;\n\nclass MaterialGraphEditor : public Widget\n{\n  public:\n\tMaterialGraphEditor(Editor *editor) :\n\t    Widget(\"Material Editor\", editor)\n\t{\n\t\tImNodes::CreateContext();\n\t\tm_context = ImNodes::EditorContextCreate();\n\n\t\tstd::vector<Resource<ResourceType::Mesh>::Vertex> vertices;\n\n\t\tstd::vector<uint32_t> indices;\n\n\t\tDESERIALIZE(\"Asset/BuildIn/MaterialBall.asset\", vertices, indices);\n\n\t\tauto *rhi_context = editor->GetRenderer()->GetRHIContext();\n\t\tauto *renderer    = editor->GetRenderer();\n\n\t\tm_view.buffer = rhi_context->CreateBuffer(sizeof(m_view.uniform_block), RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\t\tm_view.Reset();\n\t\tm_view.Update();\n\n\t\t{\n\t\t\tm_view.uniform_block.model = glm::mat4_cast(glm::qua<float>(glm::radians(glm::vec3(135.f, 0.f, 180.f))));\n\t\t}\n\n\t\tm_material_ball.vertex_buffer = rhi_context->CreateBuffer<Resource<ResourceType::Mesh>::Vertex>(vertices.size(), RHIBufferUsage::Vertex | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\tm_material_ball.index_buffer  = rhi_context->CreateBuffer<uint32_t>(indices.size(), RHIBufferUsage::Index | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\n\t\tm_material_ball.indices_count = static_cast<uint32_t>(indices.size());\n\t\tm_material_ball.vertex_buffer->CopyToDevice(vertices.data(), vertices.size() * sizeof(Resource<ResourceType::Mesh>::Vertex));\n\t\tm_material_ball.index_buffer->CopyToDevice(indices.data(), indices.size() * sizeof(uint32_t));\n\n\t\tm_preview.pipeline = rhi_context->CreatePipelineState();\n\n\t\tBlendState blend_state;\n\t\tblend_state.attachment_states.resize(1);\n\t\tm_preview.pipeline->SetBlendState(blend_state);\n\n\t\tRasterizationState rasterization_state;\n\t\trasterization_state.cull_mode  = RHICullMode::None;\n\t\trasterization_state.front_face = RHIFrontFace::Clockwise;\n\t\tm_preview.pipeline->SetRasterizationState(rasterization_state);\n\n\t\tDepthStencilState depth_stencil_state  = {};\n\t\tdepth_stencil_state.depth_write_enable = true;\n\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\tm_preview.pipeline->SetDepthStencilState(depth_stencil_state);\n\n\t\tVertexInputState vertex_input_state = {};\n\t\tvertex_input_state.input_bindings   = {\n            VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::Mesh>::Vertex), RHIVertexInputRate::Vertex}};\n\t\tvertex_input_state.input_attributes = {\n\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, position)},\n\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Normal, 1, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, normal)},\n\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Tangent, 2, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, tangent)},\n\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 3, 0, RHIFormat::R32G32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, texcoord0)},\n\t\t};\n\t\tm_preview.pipeline->SetVertexInputState(vertex_input_state);\n\n\t\tm_preview.render_target_texture = rhi_context->CreateTexture2D(500, 500, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false);\n\t\tm_preview.depth_stencil_texture = rhi_context->CreateTexture2D(500, 500, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false);\n\t\tm_preview.render_target         = rhi_context->CreateRenderTarget();\n\t\tm_preview.render_target->Set(0, m_preview.render_target_texture.get(), RHITextureDimension::Texture2D, ColorAttachment{});\n\t\tm_preview.render_target->Set(m_preview.depth_stencil_texture.get(), RHITextureDimension::Texture2D, DepthStencilAttachment{});\n\n\t\t{\n\t\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\t\tcmd_buffer->Begin();\n\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_preview.render_target_texture.get(), RHIResourceState::Undefined, RHIResourceState::ShaderResource, TextureRange{}}}, {});\n\t\t\tcmd_buffer->End();\n\t\t\trhi_context->Execute({cmd_buffer});\n\t\t}\n\t}\n\n\tvirtual ~MaterialGraphEditor() override\n\t{\n\t\tImNodes::DestroyContext();\n\t\tImNodes::EditorContextFree(m_context);\n\t}\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tauto *resource_manager = p_editor->GetRenderer()->GetResourceManager();\n\n\t\tauto *resource = resource_manager->Get<ResourceType::Material>(m_material_name);\n\n\t\tImGui::Columns(2);\n\n\t\t// Inspector\n\t\t{\n\t\t\tImGui::BeginChild(\"Material Editor Inspector\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\t\tImGui::Text(\"Material Editor Inspector\");\n\n\t\t\tif (resource)\n\t\t\t{\n\t\t\t\tRender(resource);\n\t\t\t\tfloat width = glm::min(ImGui::GetColumnWidth(), 300.f);\n\t\t\t\tImGui::Image(m_preview.render_target_texture.get(), ImVec2(width, width));\n\t\t\t\tUpdateCamera();\n\t\t\t}\n\n\t\t\tSetMaterial(resource, resource_manager);\n\n\t\t\tif (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())\n\t\t\t{\n\t\t\t\tImGui::SetScrollHereY(1.0f);\n\t\t\t}\n\n\t\t\tImGui::EndChild();\n\t\t}\n\n\t\tImGui::NextColumn();\n\n\t\tImGui::BeginChild(\"Material Graph Editor\", ImVec2(0, 0), false, ImGuiWindowFlags_MenuBar);\n\n\t\tMenuBar();\n\n\t\tHandleSelection();\n\n\t\tImNodes::BeginNodeEditor();\n\n\t\tif (resource)\n\t\t{\n\t\t\tfor (auto &new_node : m_new_nodes)\n\t\t\t{\n\t\t\t\tImNodes::SetNodeScreenSpacePos(new_node, ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y));\n\t\t\t}\n\t\t\tm_new_nodes.clear();\n\n\t\t\tPopupWindow(resource);\n\t\t\tDrawNodes(resource);\n\t\t\tDrawEdges(resource);\n\t\t}\n\n\t\tImNodes::MiniMap(0.1f);\n\t\tImNodes::EndNodeEditor();\n\n\t\tDragDropResource();\n\n\t\tif (resource)\n\t\t{\n\t\t\tAddEdge(resource);\n\t\t}\n\n\t\tImGui::EndChild();\n\n\t\tImGui::End();\n\t}\n\n\tvoid SetMaterial(Resource<ResourceType::Material> *resource, ResourceManager *manager)\n\t{\n\t\tImGui::PushItemWidth(100.f);\n\t\tchar buf[128] = {0};\n\t\tstd::memcpy(buf, m_material_name.data(), sizeof(buf));\n\t\tif (ImGui::InputText(\"##NewMaterial\", buf, sizeof(buf)))\n\t\t{\n\t\t\tm_material_name = buf;\n\t\t}\n\t\tImGui::PopItemWidth();\n\n\t\tImGui::SameLine();\n\n\t\tif (!m_material_name.empty() && !resource)\n\t\t{\n\t\t\tif (ImGui::Button(\"New Material\"))\n\t\t\t{\n\t\t\t\tMaterialGraphDesc desc;\n\t\t\t\tdesc.SetName(m_material_name);\n\t\t\t\tmanager->Add<ResourceType::Material>(p_editor->GetRHIContext(), m_material_name, std::move(desc));\n\t\t\t\tresource = manager->Get<ResourceType::Material>(m_material_name);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tImGui::Text(\"Material Name\");\n\t\t}\n\t}\n\n\tvoid DragDropResource()\n\t{\n\t\tif (ImGui::BeginDragDropTarget())\n\t\t{\n\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Material\"))\n\t\t\t{\n\t\t\t\tm_material_name = static_cast<const char *>(pay_load->Data);\n\t\t\t\tauto *resource  = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Material>(m_material_name);\n\t\t\t\tif (resource)\n\t\t\t\t{\n\t\t\t\t\tImNodes::LoadCurrentEditorStateFromIniString(resource->GetLayout().data(), resource->GetLayout().length());\n\t\t\t\t\tauto &desc = resource->GetDesc();\n\t\t\t\t\tfor (auto &[node_handle, node] : desc.GetNodes())\n\t\t\t\t\t{\n\t\t\t\t\t\tm_current_handle = glm::max(m_current_handle, node_handle + 1);\n\t\t\t\t\t\tfor (auto &[pin_handle, pin] : node.GetPins())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_current_handle = glm::max(m_current_handle, pin_handle + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tm_view.uniform_block.material_id = static_cast<uint32_t>(p_editor->GetRenderer()->GetResourceManager()->Index<ResourceType::Material>(m_material_name));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid MenuBar()\n\t{\n\t\tauto *resource = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Material>(m_material_name);\n\n\t\tif (!resource)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (ImGui::BeginMenuBar())\n\t\t{\n\t\t\tif (ImGui::BeginMenu(\"Node\"))\n\t\t\t{\n\t\t\t\tfor (const auto &file : std::filesystem::directory_iterator(\"shared/Material/\"))\n\t\t\t\t{\n\t\t\t\t\tstd::string filename = file.path().filename().string();\n\t\t\t\t\t{\n\t\t\t\t\t\tsize_t pos1 = filename.find_first_of('.');\n\t\t\t\t\t\tsize_t pos2 = filename.find_first_of('.', pos1 + 1);\n\t\t\t\t\t\tsize_t pos3 = filename.find_first_of('.', pos2 + 1);\n\n\t\t\t\t\t\tstd::string category  = filename.substr(pos1 + 1, pos2 - pos1 - 1);\n\t\t\t\t\t\tstd::string node_name = filename.substr(pos2 + 1, pos3 - pos2 - 1);\n\n\t\t\t\t\t\tif (ImGui::BeginMenu(category.c_str()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (ImGui::MenuItem(node_name.c_str()))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tMaterialNodeDesc desc;\n\t\t\t\t\t\t\t\tPluginManager::GetInstance().Call(file.path().string(), \"Create\", &desc, &m_current_handle);\n\t\t\t\t\t\t\t\tresource->GetDesc().AddNode(m_current_handle++, std::move(desc));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tImGui::EndMenu();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\n\t\t\tif (ImGui::MenuItem(\"Clear\"))\n\t\t\t{\n\t\t\t\tresource->GetDesc().Clear();\n\t\t\t}\n\n\t\t\tif (ImGui::MenuItem(\"Compile\"))\n\t\t\t{\n\t\t\t\tDummyTexture *dummy_texture = p_editor->GetRenderer()->GetRenderGraphBlackboard().Get<DummyTexture>();\n\t\t\t\tGPUScene     *gpu_scene     = p_editor->GetRenderer()->GetRenderGraphBlackboard().Get<GPUScene>();\n\n\t\t\t\tresource->Compile(\n\t\t\t\t    p_editor->GetRenderer()->GetRHIContext(),\n\t\t\t\t    p_editor->GetRenderer()->GetResourceManager(),\n\t\t\t\t    dummy_texture->black_opaque.get(),\n\t\t\t\t    ImNodes::SaveCurrentEditorStateToIniString());\n\t\t\t}\n\n\t\t\tImGui::EndMenuBar();\n\t\t}\n\t}\n\n\tvoid PopupWindow(Resource<ResourceType::Material> *resource)\n\t{\n\t\tif (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight))\n\t\t{\n\t\t\tif (ImGui::MenuItem(\"Remove\"))\n\t\t\t{\n\t\t\t\tif (!m_select_links.empty() || !m_select_nodes.empty())\n\t\t\t\t{\n\t\t\t\t\tfor (auto &link : m_select_links)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto &[dst, src] : resource->GetDesc().GetEdges())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (link == static_cast<int32_t>(Hash(src, dst)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tresource->GetDesc().EraseLink(static_cast<size_t>(src), static_cast<size_t>(dst));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto &node : m_select_nodes)\n\t\t\t\t\t{\n\t\t\t\t\t\tresource->GetDesc().EraseNode(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tImGui::EndPopup();\n\t\t}\n\t}\n\n\tvoid EditMaterialNodePin(const MaterialNodePin &pin)\n\t{\n\t\tswitch (pin.type)\n\t\t{\n\t\t\tcase MaterialNodePin::Type::Float:\n\t\t\t\tImGui::DragFloat(\"\", pin.variant.Convert<float>(), 0.001f, 0.f, 0.f, \"%.2f\");\n\t\t\t\tbreak;\n\t\t\tcase MaterialNodePin::Type::Float3:\n\t\t\t\tImGui::DragFloat3(\"\", glm::value_ptr(*pin.variant.Convert<glm::vec3>()), 0.001f, 0.f, 0.f, \"%.2f\");\n\t\t\t\tbreak;\n\t\t\tcase MaterialNodePin::Type::RGB:\n\t\t\t\tImGui::ColorEdit3(\"\", glm::value_ptr(*pin.variant.Convert<glm::vec3>()), ImGuiColorEditFlags_NoInputs);\n\t\t\t\tbreak;\n\t\t\tcase MaterialNodePin::Type::Bool:\n\t\t\t\tImGui::Checkbox(\"\", pin.variant.Convert<bool>());\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvoid DrawNodes(Resource<ResourceType::Material> *resource)\n\t{\n\t\tfor (auto &[node_handle, node_desc] : resource->GetDesc().GetNodes())\n\t\t{\n\t\t\tconst float node_width = glm::max(ImGui::CalcTextSize(node_desc.GetName().c_str()).x, 120.f);\n\t\t\tImGui::PushItemWidth(node_width);\n\n\t\t\tImNodes::BeginNode(static_cast<int32_t>(node_handle));\n\t\t\tImNodes::BeginNodeTitleBar();\n\t\t\tImGui::Text(node_desc.GetName().c_str());\n\t\t\tImNodes::EndNodeTitleBar();\n\t\t\tPluginManager::GetInstance().Call(fmt::format(\"shared/Material/Material.{}.{}.dll\", node_desc.GetCategory(), node_desc.GetName()), \"OnImGui\", &node_desc, p_editor, ImGui::GetCurrentContext());\n\t\t\tfor (auto &[pin_handle, pin] : node_desc.GetPins())\n\t\t\t{\n\t\t\t\tif (!pin.enable)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (pin.attribute == MaterialNodePin::Attribute::Input)\n\t\t\t\t{\n\t\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Pin, m_pin_color[pin.type]);\n\t\t\t\t\tImNodes::BeginInputAttribute(static_cast<int32_t>(pin_handle));\n\t\t\t\t\tImGui::TextUnformatted(pin.name.c_str());\n\t\t\t\t\tif (!resource->GetDesc().HasLink(pin_handle) && !pin.variant.Empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tImGui::SameLine();\n\t\t\t\t\t\tImGui::PushItemWidth(node_width - ImGui::CalcTextSize(pin.name.c_str()).x);\n\t\t\t\t\t\tEditMaterialNodePin(pin);\n\t\t\t\t\t\tImGui::PopItemWidth();\n\t\t\t\t\t}\n\t\t\t\t\tImNodes::EndInputAttribute();\n\t\t\t\t\tImNodes::PopColorStyle();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Pin, m_pin_color[pin.type]);\n\t\t\t\t\tImNodes::BeginOutputAttribute(static_cast<int32_t>(pin_handle));\n\t\t\t\t\tconst float label_width = ImGui::CalcTextSize(pin.name.c_str()).x;\n\t\t\t\t\tImGui::Indent(node_width - label_width);\n\t\t\t\t\tif (!pin.variant.Empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tImGui::PushItemWidth(node_width - ImGui::CalcTextSize(pin.name.c_str()).x);\n\t\t\t\t\t\tEditMaterialNodePin(pin);\n\t\t\t\t\t\tImGui::PopItemWidth();\n\t\t\t\t\t\tImGui::SameLine();\n\t\t\t\t\t}\n\t\t\t\t\tImGui::TextUnformatted(pin.name.c_str());\n\t\t\t\t\tImNodes::EndOutputAttribute();\n\t\t\t\t\tImNodes::PopColorStyle();\n\t\t\t\t}\n\t\t\t}\n\t\t\tImNodes::EndNode();\n\t\t\tImGui::PopItemWidth();\n\t\t}\n\t}\n\n\tvoid HandleSelection()\n\t{\n\t\tm_select_links.clear();\n\t\tm_select_nodes.clear();\n\n\t\tif (ImNodes::NumSelectedLinks() > 0)\n\t\t{\n\t\t\tm_select_links.resize(ImNodes::NumSelectedLinks());\n\t\t\tImNodes::GetSelectedLinks(m_select_links.data());\n\t\t}\n\n\t\tif (ImNodes::NumSelectedNodes() > 0)\n\t\t{\n\t\t\tm_select_nodes.resize(ImNodes::NumSelectedNodes());\n\t\t\tImNodes::GetSelectedNodes(m_select_nodes.data());\n\t\t}\n\t}\n\n\tvoid DrawEdges(Resource<ResourceType::Material> *resource)\n\t{\n\t\tfor (auto &[dst, src] : resource->GetDesc().GetEdges())\n\t\t{\n\t\t\tconst auto &src_node = resource->GetDesc().GetNode(src);\n\t\t\tconst auto &dst_node = resource->GetDesc().GetNode(dst);\n\n\t\t\tauto type = src_node.GetPin(src).type;\n\n\t\t\tImNodes::PushColorStyle(ImNodesCol_Link, m_pin_color[type]);\n\t\t\tImNodes::Link(static_cast<int32_t>(Hash(src, dst)), static_cast<int32_t>(src), static_cast<int32_t>(dst));\n\t\t\tImNodes::PopColorStyle();\n\t\t}\n\t}\n\n\tvoid AddEdge(Resource<ResourceType::Material> *resource)\n\t{\n\t\tint32_t src = 0, dst = 0;\n\t\tif (ImNodes::IsLinkCreated(&src, &dst))\n\t\t{\n\t\t\tresource->GetDesc().Link(src, dst);\n\t\t}\n\t}\n\n\tvoid UpdateCamera()\n\t{\n\t\tfloat delta_time = ImGui::GetIO().DeltaTime;\n\n\t\tif (ImGui::IsItemHovered())\n\t\t{\n\t\t\tif (ImGui::IsMouseDragging(ImGuiMouseButton_Right))\n\t\t\t{\n\t\t\t\tImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);\n\t\t\t\tImGui::ResetMouseDragDelta(ImGuiMouseButton_Right);\n\t\t\t\tm_view.phi -= delta.y * delta_time * 50.f;\n\t\t\t\tm_view.theta -= delta.x * delta_time * 50.f;\n\t\t\t}\n\t\t\tm_view.radius += ImGui::GetIO().MouseWheel * delta_time * 10.f;\n\t\t}\n\n\t\tm_view.Update();\n\t}\n\n\tvoid Render(Resource<ResourceType::Material> *resource)\n\t{\n\t\tauto *renderer    = p_editor->GetRenderer();\n\t\tauto *rhi_context = p_editor->GetRHIContext();\n\t\tauto *gpu_scene   = renderer->GetRenderGraphBlackboard().Get<GPUScene>();\n\n\t\tauto &material_data = resource->GetMaterialData();\n\n\t\tShaderMeta meta;\n\n\t\t{\n\t\t\tauto *vertex_shader = renderer->RequireShader(\"Source/Shaders/Editor/MaterialEditor.hlsl\", \"VSmain\", RHIShaderStage::Vertex, {\"USE_MATERIAL\", material_data.signature}, {material_data.shader});\n\t\t\tauto *frag_shader   = renderer->RequireShader(\"Source/Shaders/Editor/MaterialEditor.hlsl\", \"PSmain\", RHIShaderStage::Fragment, {\"USE_MATERIAL\", material_data.signature}, {material_data.shader});\n\n\t\t\tm_preview.pipeline->ClearShader();\n\t\t\tm_preview.pipeline->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\t\tm_preview.pipeline->SetShader(RHIShaderStage::Fragment, frag_shader);\n\n\t\t\tmeta = renderer->RequireShaderMeta(vertex_shader);\n\t\t\tmeta += renderer->RequireShaderMeta(frag_shader);\n\t\t}\n\n\t\tauto *descriptor = rhi_context->CreateDescriptor(meta);\n\t\tdescriptor->BindBuffer(\"UniformBuffer\", m_view.buffer.get())\n\t\t    .BindTexture(\"Textures\", gpu_scene->texture.texture_2d, RHITextureDimension::Texture2D)\n\t\t    .BindSampler(\"Samplers\", gpu_scene->samplers)\n\t\t    .BindBuffer(\"MaterialOffsets\", gpu_scene->material.material_offset.get())\n\t\t    .BindBuffer(\"MaterialBuffer\", gpu_scene->material.material_buffer.get());\n\n\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\tcmd_buffer->Begin();\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_preview.render_target_texture.get(), RHIResourceState::ShaderResource, RHIResourceState::RenderTarget, TextureRange{}}}, {});\n\t\tcmd_buffer->BeginRenderPass(m_preview.render_target.get());\n\t\tcmd_buffer->SetViewport(static_cast<float>(m_preview.render_target->GetWidth()), static_cast<float>(m_preview.render_target->GetHeight()));\n\t\tcmd_buffer->SetScissor(m_preview.render_target->GetWidth(), m_preview.render_target->GetHeight());\n\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\tcmd_buffer->BindPipelineState(m_preview.pipeline.get());\n\t\tcmd_buffer->BindVertexBuffer(0, m_material_ball.vertex_buffer.get());\n\t\tcmd_buffer->BindIndexBuffer(m_material_ball.index_buffer.get());\n\t\tcmd_buffer->DrawIndexed(m_material_ball.indices_count);\n\t\tcmd_buffer->EndRenderPass();\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_preview.render_target_texture.get(), RHIResourceState::RenderTarget, RHIResourceState::ShaderResource, TextureRange{}}}, {});\n\t\tcmd_buffer->End();\n\n\t\trhi_context->Submit({cmd_buffer});\n\t}\n\n  private:\n\tImNodesEditorContext *m_context = nullptr;\n\n\tstd::string m_material_name = \"\";\n\n\tsize_t m_current_handle = 0;\n\n\tstd::vector<int32_t> m_select_nodes;\n\tstd::vector<int32_t> m_select_links;\n\tstd::vector<int32_t> m_new_nodes;\n\n\tstruct\n\t{\n\t\tglm::vec3 center = glm::vec3(0.f);\n\n\t\tfloat radius = 4.f;\n\t\tfloat theta  = 0.f;\n\t\tfloat phi    = 60.f;\n\n\t\tvoid Reset()\n\t\t{\n\t\t\tcenter = glm::vec3(0.f);\n\t\t\tradius = 4.f;\n\t\t\ttheta  = 0.f;\n\t\t\tphi    = 60.f;\n\n\t\t\tUpdate();\n\t\t}\n\n\t\tvoid Update()\n\t\t{\n\t\t\tglm::vec3 position  = center + radius * glm::vec3(glm::sin(glm::radians(phi)) * glm::sin(glm::radians(theta)), glm::cos(glm::radians(phi)), glm::sin(glm::radians(phi)) * glm::cos(glm::radians(theta)));\n\t\t\tglm::vec3 direction = glm::normalize(center - position);\n\t\t\tglm::vec3 right     = glm::normalize(glm::cross(direction, glm::vec3{0.f, 1.f, 0.f}));\n\t\t\tglm::vec3 up        = glm::normalize(glm::cross(right, direction));\n\t\t\tglm::mat4 transform = glm::perspective(glm::radians(45.f), 1.f, 0.01f, 1000.f) * glm::lookAt(position, center, up);\n\n\t\t\tuniform_block.transform  = transform;\n\t\t\tuniform_block.camera_pos = position;\n\t\t\tbuffer->CopyToDevice(&uniform_block, sizeof(uniform_block));\n\t\t}\n\n\t\tstruct\n\t\t{\n\t\t\tglm::mat4 transform;\n\t\t\tglm::mat4 model;\n\t\t\tglm::vec3 camera_pos;\n\t\t\tuint32_t  material_id;\n\t\t} uniform_block;\n\n\t\tstd::unique_ptr<RHIBuffer> buffer = nullptr;\n\t} m_view;\n\n\tstruct\n\t{\n\t\tstd::unique_ptr<RHIBuffer> vertex_buffer = nullptr;\n\t\tstd::unique_ptr<RHIBuffer> index_buffer  = nullptr;\n\n\t\tuint32_t indices_count = 0;\n\t} m_material_ball;\n\n\tstruct\n\t{\n\t\tstd::unique_ptr<RHIPipelineState> pipeline              = nullptr;\n\t\tstd::unique_ptr<RHITexture>       render_target_texture = nullptr;\n\t\tstd::unique_ptr<RHITexture>       depth_stencil_texture = nullptr;\n\t\tstd::unique_ptr<RHIRenderTarget>  render_target         = nullptr;\n\t} m_preview;\n\n\tstd::map<MaterialNodePin::Type, uint32_t> m_pin_color = {\n\t    {MaterialNodePin::Type::BSDF, IM_COL32(0, 128, 0, 255)},\n\t    {MaterialNodePin::Type::Media, IM_COL32(0, 0, 128, 255)},\n\t    {MaterialNodePin::Type::Float, IM_COL32(0, 128, 128, 255)},\n\t    {MaterialNodePin::Type::Float3, IM_COL32(128, 128, 0, 255)},\n\t    {MaterialNodePin::Type::RGB, IM_COL32(128, 128, 0, 255)},\n\t};\n};\n\nextern \"C\"\n{\n\tEXPORT_API MaterialGraphEditor *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new MaterialGraphEditor(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/MeshEditor.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Geometry/Mesh/Mesh.hpp>\n#include <Geometry/MeshProcess.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/Importer.hpp>\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\n#include <glm/glm.hpp>\n#include <glm/gtc/type_ptr.hpp>\n\nusing namespace Ilum;\n\nclass MeshEditor : public Widget\n{\n  private:\n\tstruct UniformBlock\n\t{\n\t\tglm::mat4 transform;\n\t\talignas(16) glm::vec3 color;\n\t\talignas(16) glm::vec3 direction;\n\t};\n\n\tenum class ShadingMode\n\t{\n\t\tNone,\n\t\tShading,\n\t\tNormal,\n\t\tUV,\n\t\tTexture\n\t};\n\n  public:\n\tMeshEditor(Editor *editor) :\n\t    Widget(\"Mesh Editor\", editor)\n\t{\n\t\tm_pipeline_state = p_editor->GetRHIContext()->CreatePipelineState();\n\t\tm_render_target  = p_editor->GetRHIContext()->CreateRenderTarget();\n\t\tm_uniform_buffer = p_editor->GetRHIContext()->CreateBuffer<UniformBlock>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\n\t\tVertexInputState vertex_input_state = {};\n\t\tvertex_input_state.input_bindings   = {\n            VertexInputState::InputBinding{0, sizeof(VertexData), RHIVertexInputRate::Vertex}};\n\n\t\tBlendState blend_state = {};\n\t\tblend_state.attachment_states.resize(1);\n\n\t\tDepthStencilState depth_stencil_state  = {};\n\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\tdepth_stencil_state.depth_write_enable = true;\n\n\t\tm_pipeline_state->SetVertexInputState(vertex_input_state);\n\t\tm_pipeline_state->SetBlendState(blend_state);\n\t\tm_pipeline_state->SetDepthStencilState(depth_stencil_state);\n\t}\n\n\tvirtual ~MeshEditor() override = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tImGui::Columns(2);\n\n\t\t// Inspector\n\t\t{\n\t\t\tImGui::BeginChild(\"Mesh Editor Inspector\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\t\tImGui::Text(\"Mesh Editor Inspector\");\n\n\t\t\tif (ImGui::TreeNode(\"Mesh\"))\n\t\t\t{\n\t\t\t\tImGui::Text(\"Vertices Count: %ld\", m_mesh.vertices.size());\n\t\t\t\tImGui::Text(\"Triangle Count: %ld\", m_mesh.indices.size() / 3);\n\n\t\t\t\tif (ImGui::Button(\"Clear\", ImVec2(150.f, 20.f)))\n\t\t\t\t{\n\t\t\t\t\tm_mesh.vertices.clear();\n\t\t\t\t\tm_mesh.indices.clear();\n\t\t\t\t}\n\n\t\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t\t{\n\t\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Mesh\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tstd::string mesh_name = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\t\tauto       *resource  = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Mesh>(mesh_name);\n\n\t\t\t\t\t\tm_mesh.indices.resize(resource->GetIndexCount());\n\t\t\t\t\t\tm_mesh.vertices.resize(resource->GetVertexCount());\n\n\t\t\t\t\t\tstd::vector<Resource<ResourceType::Mesh>::Vertex> vertices(resource->GetVertexCount());\n\n\t\t\t\t\t\tresource->GetVertexBuffer()->CopyToHost(vertices.data(), vertices.size() * sizeof(Resource<ResourceType::Mesh>::Vertex));\n\t\t\t\t\t\tresource->GetIndexBuffer()->CopyToHost(m_mesh.indices.data(), m_mesh.indices.size() * sizeof(uint32_t));\n\n\t\t\t\t\t\tglm::vec3 min_bound = glm::vec3(std::numeric_limits<float>::max());\n\t\t\t\t\t\tglm::vec3 max_bound = glm::vec3(-std::numeric_limits<float>::max());\n\n\t\t\t\t\t\tfor (uint32_t i = 0; i < m_mesh.vertices.size(); i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tVertexData data = {};\n\t\t\t\t\t\t\tdata.position   = vertices[i].position;\n\t\t\t\t\t\t\tdata.normal     = vertices[i].normal;\n\t\t\t\t\t\t\tdata.uv         = vertices[i].texcoord0;\n\n\t\t\t\t\t\t\tmin_bound = glm::min(min_bound, data.position);\n\t\t\t\t\t\t\tmax_bound = glm::max(max_bound, data.position);\n\n\t\t\t\t\t\t\tm_mesh.vertices[i] = data;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tm_view.center  = (max_bound + min_bound) * 0.5f;\n\t\t\t\t\t\tm_view.radius  = glm::length(max_bound - min_bound);\n\t\t\t\t\t\tm_scale_factor = m_view.radius;\n\n\t\t\t\t\t\tUpdateBuffer();\n\t\t\t\t\t}\n\t\t\t\t\tImGui::EndDragDropTarget();\n\t\t\t\t}\n\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\n\t\t\tif (ImGui::TreeNode(\"Rendering\"))\n\t\t\t{\n\t\t\t\tImGui::Checkbox(\"Wireframe\", &m_wireframe);\n\n\t\t\t\tconst char *shading_mode[] = {\"None\", \"Shading\", \"Normal\", \"UV\", \"Texture\"};\n\t\t\t\tImGui::PushItemWidth(90);\n\t\t\t\tImGui::Combo(\"Mode\", reinterpret_cast<int32_t *>(&m_shading_mode), shading_mode, 5);\n\t\t\t\tImGui::PopItemWidth();\n\t\t\t\tif (m_shading_mode == ShadingMode::Shading)\n\t\t\t\t{\n\t\t\t\t\tImGui::ColorEdit3(\"Color\", glm::value_ptr(m_color));\n\t\t\t\t}\n\t\t\t\tImGui::ColorEdit3(\"Background Color\", glm::value_ptr(m_bg_color));\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\n\t\t\tif (ImGui::TreeNode(\"Process\"))\n\t\t\t{\n\t\t\t\tfor (const auto &file : std::filesystem::directory_iterator(\"shared/Geometry/\"))\n\t\t\t\t{\n\t\t\t\t\tstd::string filename = file.path().filename().string();\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ImGui::TreeNode(\"Subdivision\"))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsize_t begin = std::string(\"Geometry.Subdivision.\").length();\n\t\t\t\t\t\t\tsize_t end   = filename.find_first_of('.', begin);\n\n\t\t\t\t\t\t\tif (ImGui::Button(filename.substr(begin, end - begin).c_str()))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tm_mesh = Subdivision::GetInstance(filename)->Execute(m_mesh);\n\t\t\t\t\t\t\t\tUpdateBuffer();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tImGui::TreePop();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\n\t\t\tif (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())\n\t\t\t{\n\t\t\t\tImGui::SetScrollHereY(1.0f);\n\t\t\t}\n\n\t\t\tImGui::EndChild();\n\t\t}\n\n\t\tImGui::NextColumn();\n\n\t\tUpdateCamera(ImGui::GetColumnWidth(1), ImGui::GetContentRegionAvail().y);\n\n\t\t// Model Viewer\n\t\tif (m_vertex_buffer && m_index_buffer)\n\t\t{\n\t\t\tRender(static_cast<uint32_t>(ImGui::GetColumnWidth(1)), static_cast<uint32_t>(ImGui::GetContentRegionAvail().y));\n\t\t\tif (m_render_texture)\n\t\t\t{\n\t\t\t\tImGui::Image(m_render_texture.get(), ImVec2{ImGui::GetColumnWidth(1), ImGui::GetContentRegionAvail().y});\n\t\t\t}\n\t\t}\n\n\t\tImGui::End();\n\t}\n\n\tvoid UpdateBuffer()\n\t{\n\t\tif (!m_mesh.vertices.empty() && !m_mesh.indices.empty())\n\t\t{\n\t\t\tif (!m_vertex_buffer || m_mesh.vertices.size() * sizeof(VertexData) > m_vertex_buffer->GetDesc().size)\n\t\t\t{\n\t\t\t\tm_vertex_buffer = p_editor->GetRHIContext()->CreateBuffer<VertexData>(m_mesh.vertices.size(), RHIBufferUsage::Vertex | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t}\n\t\t\tif (!m_index_buffer || m_mesh.indices.size() * sizeof(uint32_t) > m_index_buffer->GetDesc().size)\n\t\t\t{\n\t\t\t\tm_index_buffer = p_editor->GetRHIContext()->CreateBuffer<uint32_t>(m_mesh.indices.size(), RHIBufferUsage::Index | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t}\n\t\t\tm_vertex_buffer->CopyToDevice(m_mesh.vertices.data(), m_mesh.vertices.size() * sizeof(VertexData));\n\t\t\tm_index_buffer->CopyToDevice(m_mesh.indices.data(), m_mesh.indices.size() * sizeof(uint32_t));\n\t\t}\n\t}\n\n\tvoid Render(uint32_t width, uint32_t height)\n\t{\n\t\tauto *rhi_context = p_editor->GetRHIContext();\n\n\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\tcmd_buffer->Begin();\n\n\t\tif (!m_uv_texture)\n\t\t{\n\t\t\tm_uv_texture = rhi_context->CreateTexture2D(500, 500, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer, false);\n\t\t\tstd::vector<uint8_t> data(500 * 500 * 4);\n\t\t\tfor (size_t i = 0; i < 500; i++)\n\t\t\t{\n\t\t\t\tfor (size_t j = 0; j < 500; j++)\n\t\t\t\t{\n\t\t\t\t\tif (((i / 50) % 2 == 0 && (j / 50) % 2 == 1) ||\n\t\t\t\t\t    ((i / 50) % 2 == 1 && (j / 50) % 2 == 0))\n\t\t\t\t\t{\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j]     = 0;\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j + 1] = 125;\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j + 2] = 0;\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j + 3] = 255;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j]     = 255;\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j + 1] = 255;\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j + 2] = 255;\n\t\t\t\t\t\tdata[500U * 4U * i + 4U * j + 3] = 255;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto *copy_cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\t\t\tcopy_cmd_buffer->Begin();\n\t\t\t\tcopy_cmd_buffer->ResourceStateTransition({TextureStateTransition{m_uv_texture.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}}, {});\n\t\t\t\tauto staging_buffer = rhi_context->CreateBuffer(data.size(), RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t\tstaging_buffer->CopyToDevice(data.data(), data.size());\n\t\t\t\tcopy_cmd_buffer->CopyBufferToTexture(staging_buffer.get(), m_uv_texture.get(), 0, 0, 1);\n\t\t\t\tcopy_cmd_buffer->End();\n\t\t\t\trhi_context->Execute(copy_cmd_buffer);\n\t\t\t}\n\n\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_uv_texture.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}}, {});\n\t\t}\n\n\t\tif (!m_render_texture)\n\t\t{\n\t\t\tm_render_texture = rhi_context->CreateTexture2D(1000, 1000, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false);\n\t\t\tm_depth_texture  = rhi_context->CreateTexture2D(1000, 1000, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget, false);\n\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t    {TextureStateTransition{m_render_texture.get(), RHIResourceState::Undefined, RHIResourceState::RenderTarget, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t\t     TextureStateTransition{m_depth_texture.get(), RHIResourceState::Undefined, RHIResourceState::DepthWrite, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t\t\t    {});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_render_texture.get(), RHIResourceState::ShaderResource, RHIResourceState::RenderTarget, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}}, {});\n\t\t}\n\n\t\t// Shading\n\t\tif (m_shading_mode != ShadingMode::None)\n\t\t{\n\t\t\tconst char *shading_macros[] = {\"NONE\", \"SHADING\", \"DRAW_NORMAL\", \"DRAW_UV\", \"DRAW_TEXTURE\"};\n\n\t\t\tauto *vertex_shader   = p_editor->GetRenderer()->RequireShader(\"./Source/Shaders/Editor/MeshEditor.hlsl\", \"VSmain\", RHIShaderStage::Vertex, {shading_macros[(size_t) m_shading_mode]});\n\t\t\tauto *fragment_shader = p_editor->GetRenderer()->RequireShader(\"./Source/Shaders/Editor/MeshEditor.hlsl\", \"PSmain\", RHIShaderStage::Fragment, {shading_macros[(size_t) m_shading_mode]});\n\n\t\t\tm_pipeline_state->ClearShader();\n\t\t\tm_pipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\t\tm_pipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader);\n\n\t\t\tShaderMeta meta = p_editor->GetRenderer()->RequireShaderMeta(vertex_shader);\n\t\t\tmeta += p_editor->GetRenderer()->RequireShaderMeta(fragment_shader);\n\n\t\t\tRasterizationState rasterization_state = {};\n\t\t\trasterization_state.polygon_mode       = RHIPolygonMode::Solid;\n\t\t\trasterization_state.cull_mode          = RHICullMode::None;\n\t\t\tm_pipeline_state->SetRasterizationState(rasterization_state);\n\n\t\t\tVertexInputState vertex_input_state = m_pipeline_state->GetVertexInputState();\n\t\t\tif (m_shading_mode == ShadingMode::Shading ||\n\t\t\t    m_shading_mode == ShadingMode::Normal)\n\t\t\t{\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(VertexData, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Normal, 1, 0, RHIFormat::R32G32B32_FLOAT, offsetof(VertexData, normal)},\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if (m_shading_mode == ShadingMode::UV)\n\t\t\t{\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(VertexData, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 1, 0, RHIFormat::R32G32_FLOAT, offsetof(VertexData, uv)},\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if (m_shading_mode == ShadingMode::Texture)\n\t\t\t{\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(VertexData, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Normal, 1, 0, RHIFormat::R32G32B32_FLOAT, offsetof(VertexData, normal)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 2, 0, RHIFormat::R32G32_FLOAT, offsetof(VertexData, uv)},\n\t\t\t\t};\n\t\t\t}\n\t\t\tm_pipeline_state->SetVertexInputState(vertex_input_state);\n\n\t\t\tm_render_target->Clear();\n\t\t\tm_render_target->Set(0, m_render_texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, ColorAttachment{RHILoadAction::Clear, RHIStoreAction::Store, {m_bg_color.x, m_bg_color.y, m_bg_color.z, 1.f}});\n\t\t\tm_render_target->Set(m_depth_texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, DepthStencilAttachment{});\n\n\t\t\tauto *descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\tdescriptor->BindTexture(\"UVTexture\", m_uv_texture.get(), RHITextureDimension::Texture2D)\n\t\t\t    .BindSampler(\"UVSampler\", rhi_context->CreateSampler(SamplerDesc::LinearWarp()))\n\t\t\t    .BindBuffer(\"UniformBuffer\", m_uniform_buffer.get());\n\n\t\t\tcmd_buffer->BeginRenderPass(m_render_target.get());\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(m_pipeline_state.get());\n\t\t\tcmd_buffer->BindVertexBuffer(0, m_vertex_buffer.get());\n\t\t\tcmd_buffer->BindIndexBuffer(m_index_buffer.get());\n\t\t\tcmd_buffer->SetViewport((float) m_render_target->GetWidth(), (float) m_render_target->GetHeight());\n\t\t\tcmd_buffer->SetScissor(m_render_target->GetWidth(), m_render_target->GetHeight());\n\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(m_mesh.indices.size()));\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t}\n\n\t\tif (m_wireframe)\n\t\t{\n\t\t\tauto *vertex_shader   = p_editor->GetRenderer()->RequireShader(\"./Source/Shaders/Editor/MeshEditor.hlsl\", \"VSmain\", RHIShaderStage::Vertex, {\"WIREFRAME\"});\n\t\t\tauto *fragment_shader = p_editor->GetRenderer()->RequireShader(\"./Source/Shaders/Editor/MeshEditor.hlsl\", \"PSmain\", RHIShaderStage::Fragment, {\"WIREFRAME\"});\n\n\t\t\tm_pipeline_state->ClearShader();\n\t\t\tm_pipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\t\tm_pipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader);\n\n\t\t\tShaderMeta meta = p_editor->GetRenderer()->RequireShaderMeta(vertex_shader);\n\t\t\tmeta += p_editor->GetRenderer()->RequireShaderMeta(fragment_shader);\n\n\t\t\tRasterizationState rasterization_state = {};\n\t\t\trasterization_state.polygon_mode       = RHIPolygonMode::Wireframe;\n\t\t\trasterization_state.cull_mode          = RHICullMode::None;\n\t\t\tm_pipeline_state->SetRasterizationState(rasterization_state);\n\n\t\t\tVertexInputState vertex_input_state = m_pipeline_state->GetVertexInputState();\n\t\t\tvertex_input_state.input_attributes = {\n\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(VertexData, position)},\n\t\t\t};\n\t\t\tm_pipeline_state->SetVertexInputState(vertex_input_state);\n\n\t\t\tm_render_target->Clear();\n\t\t\tm_render_target->Set(0, m_render_texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, ColorAttachment{m_shading_mode != ShadingMode::None ? RHILoadAction::Load : RHILoadAction::Clear, RHIStoreAction::Store, {0.2f, 0.3f, 0.3f, 1.f}});\n\t\t\tm_render_target->Set(m_depth_texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, DepthStencilAttachment{m_shading_mode != ShadingMode::None ? RHILoadAction::Load : RHILoadAction::Clear});\n\n\t\t\tauto *descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\tdescriptor->BindTexture(\"UVTexture\", m_uv_texture.get(), RHITextureDimension::Texture2D)\n\t\t\t    .BindSampler(\"UVSampler\", rhi_context->CreateSampler(SamplerDesc::LinearWarp()))\n\t\t\t    .BindBuffer(\"UniformBuffer\", m_uniform_buffer.get());\n\n\t\t\tcmd_buffer->BeginRenderPass(m_render_target.get());\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(m_pipeline_state.get());\n\t\t\tcmd_buffer->BindVertexBuffer(0, m_vertex_buffer.get());\n\t\t\tcmd_buffer->BindIndexBuffer(m_index_buffer.get());\n\t\t\tcmd_buffer->SetViewport((float) m_render_target->GetWidth(), (float) m_render_target->GetHeight());\n\t\t\tcmd_buffer->SetScissor(m_render_target->GetWidth(), m_render_target->GetHeight());\n\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(m_mesh.indices.size()));\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t}\n\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_render_texture.get(), RHIResourceState::RenderTarget, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}}, {});\n\t\tcmd_buffer->End();\n\t\trhi_context->Submit({cmd_buffer});\n\t}\n\n\tvoid UpdateCamera(float width, float height)\n\t{\n\t\tfloat delta_time = ImGui::GetIO().DeltaTime;\n\n\t\tif (ImGui::IsWindowHovered())\n\t\t{\n\t\t\tif (ImGui::IsMouseDragging(ImGuiMouseButton_Right))\n\t\t\t{\n\t\t\t\tImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);\n\t\t\t\tImGui::ResetMouseDragDelta(ImGuiMouseButton_Right);\n\t\t\t\tm_view.phi -= delta.y * delta_time * 50.f;\n\t\t\t\tm_view.theta -= delta.x * delta_time * 50.f;\n\t\t\t}\n\t\t\tm_view.radius += m_scale_factor * ImGui::GetIO().MouseWheel * delta_time * 10.f;\n\t\t}\n\n\t\tglm::vec3 position = m_view.center + m_view.radius * glm::vec3(glm::sin(glm::radians(m_view.phi)) * glm::sin(glm::radians(m_view.theta)), glm::cos(glm::radians(m_view.phi)), glm::sin(glm::radians(m_view.phi)) * glm::cos(glm::radians(m_view.theta)));\n\n\t\tUniformBlock block = {};\n\n\t\tblock.color     = m_color;\n\t\tblock.direction = glm::normalize(m_view.center - position);\n\t\tglm::vec3 right = glm::normalize(glm::cross(block.direction, glm::vec3{0.f, 1.f, 0.f}));\n\t\tglm::vec3 up    = glm::normalize(glm::cross(right, block.direction));\n\t\tblock.transform = glm::perspective(glm::radians(45.f), width / height, 0.01f, 1000.f) * glm::lookAt(position, m_view.center, up);\n\n\t\tm_uniform_buffer->CopyToDevice(&block, sizeof(block));\n\t}\n\n  private:\n\tTriMesh m_mesh;\n\n\tstd::string m_mesh_name;\n\n\tstruct\n\t{\n\t\tglm::vec3 center = glm::vec3(0.f);\n\t\tfloat     radius = 0.f;\n\t\tfloat     theta  = 0.f;\n\t\tfloat     phi    = 90.f;\n\t} m_view;\n\n\tstd::unique_ptr<RHIPipelineState> m_pipeline_state = nullptr;\n\tstd::unique_ptr<RHIRenderTarget>  m_render_target  = nullptr;\n\n\tstd::unique_ptr<RHIBuffer> m_vertex_buffer = nullptr;\n\tstd::unique_ptr<RHIBuffer> m_index_buffer  = nullptr;\n\n\tstd::unique_ptr<RHIBuffer> m_uniform_buffer = nullptr;\n\n\tstd::unique_ptr<RHITexture> m_uv_texture     = nullptr;\n\tstd::unique_ptr<RHITexture> m_render_texture = nullptr;\n\tstd::unique_ptr<RHITexture> m_depth_texture  = nullptr;\n\n\tglm::vec3 m_color    = glm::vec3(1.f);\n\tglm::vec3 m_bg_color = glm::vec3(0.2f, 0.3f, 0.3f);\n\n\tfloat m_scale_factor = 1.f;\n\n\tbool m_wireframe = false;\n\n\tShadingMode m_shading_mode = ShadingMode::Shading;\n};\n\nextern \"C\"\n{\n\tEXPORT_API MeshEditor *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new MeshEditor(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/RenderGraphEditor.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBlackboard.hpp>\n#include <RenderGraph/RenderGraphBuilder.hpp>\n#include <RenderGraph/RenderPass.hpp>\n#include <Renderer/RenderData.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/Resource/RenderPipeline.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n#include <imnodes/imnodes.h>\n\n#include <nfd.h>\n\nusing namespace Ilum;\n\nclass RenderGraphEditor : public Widget\n{\n  public:\n\tRenderGraphEditor(Editor *editor) :\n\t    Widget(\"Render Graph Editor\", editor)\n\t{\n\t\tImNodes::CreateContext();\n\t\tm_context = ImNodes::EditorContextCreate();\n\t}\n\n\tvirtual ~RenderGraphEditor() override\n\t{\n\t\tImNodes::DestroyContext();\n\t\tImNodes::EditorContextFree(m_context);\n\t}\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str(), nullptr))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tauto *resource_manager = p_editor->GetRenderer()->GetResourceManager();\n\t\tauto *resource         = resource_manager->Get<ResourceType::RenderPipeline>(m_pipeline_name);\n\n\t\tImGui::Columns(2);\n\n\t\t{\n\t\t\tImGui::BeginChild(\"Render Pipeline Editor Inspector\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\t\tImGui::Text(\"Render Pipeline Editor Inspector\");\n\n\t\t\tSetRenderPipeline(resource, resource_manager);\n\n\t\t\tif (resource)\n\t\t\t{\n\t\t\t\tfor (auto &node : m_select_nodes)\n\t\t\t\t{\n\t\t\t\t\tif (resource->GetDesc().HasPass(node))\n\t\t\t\t\t{\n\t\t\t\t\t\tauto &pass = resource->GetDesc().GetPass(static_cast<size_t>(node));\n\t\t\t\t\t\tif (!pass.GetConfig().Empty())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tImGui::Separator();\n\t\t\t\t\t\t\tPluginManager::GetInstance().Call<bool>(fmt::format(\"shared/RenderPass/RenderPass.{}.{}.dll\", pass.GetCategory(), pass.GetName()), \"OnImGui\", &pass.GetConfig(), ImGui::GetCurrentContext());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())\n\t\t\t{\n\t\t\t\tImGui::SetScrollHereY(1.0f);\n\t\t\t}\n\n\t\t\tImGui::EndChild();\n\t\t}\n\n\t\tImGui::NextColumn();\n\n\t\t{\n\t\t\tImGui::BeginChild(\"Render Graph Editor\", ImVec2(0, 0), false, ImGuiWindowFlags_MenuBar);\n\n\t\t\tif (resource)\n\t\t\t{\n\t\t\t\tMainMenuBar(resource);\n\t\t\t}\n\n\t\t\tHandleSelection();\n\n\t\t\tImNodes::BeginNodeEditor();\n\n\t\t\tif (resource)\n\t\t\t{\n\t\t\t\tfor (auto &new_node : m_new_nodes)\n\t\t\t\t{\n\t\t\t\t\tImNodes::SetNodeScreenSpacePos(new_node, ImGui::GetMousePos());\n\t\t\t\t}\n\t\t\t\tm_new_nodes.clear();\n\n\t\t\t\tPopupWindow(resource);\n\t\t\t\tDrawNodes(resource);\n\t\t\t\tDrawEdges(resource);\n\t\t\t}\n\n\t\t\tImNodes::MiniMap(0.1f);\n\t\t\tImNodes::EndNodeEditor();\n\n\t\t\tDragDropResource();\n\n\t\t\tif (resource)\n\t\t\t{\n\t\t\t\tAddEdge(resource);\n\t\t\t}\n\n\t\t\tImGui::EndChild();\n\t\t}\n\n\t\tImGui::End();\n\t}\n\n  private:\n\tvoid HandleSelection()\n\t{\n\t\tm_select_links.clear();\n\t\tm_select_nodes.clear();\n\n\t\tif (ImNodes::NumSelectedLinks() > 0)\n\t\t{\n\t\t\tm_select_links.resize(ImNodes::NumSelectedLinks());\n\t\t\tImNodes::GetSelectedLinks(m_select_links.data());\n\t\t}\n\n\t\tif (ImNodes::NumSelectedNodes() > 0)\n\t\t{\n\t\t\tm_select_nodes.resize(ImNodes::NumSelectedNodes());\n\t\t\tImNodes::GetSelectedNodes(m_select_nodes.data());\n\t\t}\n\t}\n\n\tvoid AddEdge(Resource<ResourceType::RenderPipeline> *resource)\n\t{\n\t\tint32_t src = 0, dst = 0;\n\t\tif (ImNodes::IsLinkCreated(&src, &dst))\n\t\t{\n\t\t\tresource->GetDesc().Link(static_cast<size_t>(glm::abs(src)), static_cast<size_t>(glm::abs(dst)));\n\t\t}\n\t}\n\n\tvoid PopupWindow(Resource<ResourceType::RenderPipeline> *resource)\n\t{\n\t\tif (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight))\n\t\t{\n\t\t\tif (!m_select_links.empty() || !m_select_nodes.empty())\n\t\t\t{\n\t\t\t\tif (ImGui::MenuItem(\"Remove\"))\n\t\t\t\t{\n\t\t\t\t\tfor (auto &link : m_select_links)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (auto &[dst, src] : resource->GetDesc().GetEdges())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (link == static_cast<int32_t>(Hash(src, dst)))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tresource->GetDesc().EraseLink(static_cast<size_t>(src), static_cast<size_t>(dst));\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto &node : m_select_nodes)\n\t\t\t\t\t{\n\t\t\t\t\t\tresource->GetDesc().ErasePass(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tm_select_nodes.clear();\n\t\t\t\tm_select_links.clear();\n\t\t\t}\n\n\t\t\tImGui::EndPopup();\n\t\t}\n\t}\n\n\tvoid MainMenuBar(Resource<ResourceType::RenderPipeline> *resource)\n\t{\n\t\tif (ImGui::BeginMenuBar())\n\t\t{\n\t\t\tif (ImGui::BeginMenu(\"Pass\"))\n\t\t\t{\n\t\t\t\tfor (const auto &file : std::filesystem::directory_iterator(\"shared/RenderPass/\"))\n\t\t\t\t{\n\t\t\t\t\tstd::string filename = file.path().filename().string();\n\t\t\t\t\t{\n\t\t\t\t\t\tsize_t pos1 = filename.find_first_of('.');\n\t\t\t\t\t\tsize_t pos2 = filename.find_first_of('.', pos1 + 1);\n\t\t\t\t\t\tsize_t pos3 = filename.find_first_of('.', pos2 + 1);\n\n\t\t\t\t\t\tstd::string category  = filename.substr(pos1 + 1, pos2 - pos1 - 1);\n\t\t\t\t\t\tstd::string node_name = filename.substr(pos2 + 1, pos3 - pos2 - 1);\n\n\t\t\t\t\t\tif (ImGui::BeginMenu(category.c_str()))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (ImGui::MenuItem(node_name.c_str()))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tRenderPassDesc desc;\n\t\t\t\t\t\t\t\tPluginManager::GetInstance().Call(file.path().string(), \"Create\", &desc, &m_current_handle);\n\t\t\t\t\t\t\t\tm_new_nodes.push_back(static_cast<int32_t>(m_current_handle));\n\t\t\t\t\t\t\t\tresource->GetDesc().AddPass(m_current_handle++, std::move(desc));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tImGui::EndMenu();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\n\t\t\tif (ImGui::MenuItem(\"Compile\"))\n\t\t\t{\n\t\t\t\tauto *rhi_context = p_editor->GetRHIContext();\n\t\t\t\tauto *renderer    = p_editor->GetRenderer();\n\t\t\t\tauto render_graph = resource->Compile(rhi_context, renderer, renderer->GetViewport(), ImNodes::SaveCurrentEditorStateToIniString());\n\n\t\t\t\tif (render_graph)\n\t\t\t\t{\n\t\t\t\t\trenderer->SetRenderGraph(std::move(render_graph));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tLOG_INFO(\"Render Graph Compile Failed!\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!resource->GetDesc().GetPasses().empty())\n\t\t\t{\n\t\t\t\tif (ImGui::MenuItem(\"Clear\"))\n\t\t\t\t{\n\t\t\t\t\tresource->GetDesc().Clear();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::EndMenuBar();\n\t\t}\n\t}\n\n\tvoid DrawNodes(Resource<ResourceType::RenderPipeline> *resource)\n\t{\n\t\tfor (auto &[node_handle, node_desc] : resource->GetDesc().GetPasses())\n\t\t{\n\t\t\tconst float node_width = glm::max(ImGui::CalcTextSize(node_desc.GetName().c_str()).x, 150.f);\n\n\t\t\tImNodes::BeginNode(static_cast<int32_t>(node_handle));\n\t\t\tImNodes::BeginNodeTitleBar();\n\t\t\tImGui::Text(node_desc.GetName().c_str());\n\t\t\tImNodes::EndNodeTitleBar();\n\n\t\t\t// Draw exec pin\n\t\t\t{\n\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Pin, IM_COL32(255, 255, 255, 255));\n\t\t\t\tImNodes::PushColorStyle(ImNodesCol_PinHovered, IM_COL32(255, 255, 255, 255));\n\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Link, IM_COL32(255, 255, 255, 255));\n\n\t\t\t\t// In attribute\n\t\t\t\tImNodes::BeginInputAttribute(static_cast<int32_t>(node_handle));\n\t\t\t\tImGui::TextUnformatted(\"In\");\n\t\t\t\tImNodes::EndInputAttribute();\n\n\t\t\t\tImGui::SameLine();\n\n\t\t\t\t// Out attribute\n\t\t\t\tImNodes::BeginOutputAttribute(-static_cast<int32_t>(node_handle));\n\t\t\t\tconst float label_width = ImGui::CalcTextSize(\"OutIn \").x;\n\t\t\t\tImGui::Indent(node_width - label_width);\n\t\t\t\tImGui::TextUnformatted(\"Out\");\n\t\t\t\tImNodes::EndOutputAttribute();\n\n\t\t\t\tImNodes::PopColorStyle();\n\t\t\t\tImNodes::PopColorStyle();\n\t\t\t\tImNodes::PopColorStyle();\n\t\t\t}\n\n\t\t\tfor (auto &[pin_handle, pin] : node_desc.GetPins())\n\t\t\t{\n\t\t\t\tif (pin.attribute == RenderPassPin::Attribute::Input)\n\t\t\t\t{\n\t\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Pin, m_color[pin.type]);\n\t\t\t\t\tImNodes::BeginInputAttribute(static_cast<int32_t>(pin_handle));\n\t\t\t\t\tImGui::TextUnformatted(pin.name.c_str());\n\t\t\t\t\tif (!resource->GetDesc().HasLink(pin_handle))\n\t\t\t\t\t{\n\t\t\t\t\t\tImGui::SameLine();\n\t\t\t\t\t\tImGui::PushItemWidth(node_width - ImGui::CalcTextSize(pin.name.c_str()).x);\n\t\t\t\t\t\tImGui::PopItemWidth();\n\t\t\t\t\t}\n\t\t\t\t\tImNodes::EndInputAttribute();\n\t\t\t\t\tImNodes::PopColorStyle();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Pin, m_color[pin.type]);\n\t\t\t\t\tImNodes::BeginOutputAttribute(static_cast<int32_t>(pin_handle));\n\t\t\t\t\tconst float label_width = ImGui::CalcTextSize(pin.name.c_str()).x;\n\t\t\t\t\tImGui::Indent(node_width - label_width);\n\t\t\t\t\tImGui::TextUnformatted(pin.name.c_str());\n\t\t\t\t\tImNodes::EndOutputAttribute();\n\t\t\t\t\tImNodes::PopColorStyle();\n\t\t\t\t}\n\t\t\t}\n\t\t\tImNodes::EndNode();\n\t\t}\n\t}\n\n\tvoid DrawEdges(Resource<ResourceType::RenderPipeline> *resource)\n\t{\n\t\tfor (auto &[dst, src] : resource->GetDesc().GetEdges())\n\t\t{\n\t\t\tconst auto &src_node = resource->GetDesc().GetPass(src);\n\t\t\tconst auto &dst_node = resource->GetDesc().GetPass(dst);\n\n\t\t\tif ((src == src_node.GetHandle()) &&\n\t\t\t    (dst == dst_node.GetHandle()))\n\t\t\t{\n\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Link, m_color[RenderPassPin::Type::Unknown]);\n\t\t\t\tImNodes::Link(static_cast<int32_t>(Hash(src, dst)), -static_cast<int32_t>(src), static_cast<int32_t>(dst));\n\t\t\t\tImNodes::PopColorStyle();\n\t\t\t}\n\t\t\telse if ((src != src_node.GetHandle()) &&\n\t\t\t         (dst != dst_node.GetHandle()))\n\t\t\t{\n\t\t\t\tauto type = src_node.GetPin(src).type;\n\t\t\t\tImNodes::PushColorStyle(ImNodesCol_Link, m_color[type]);\n\t\t\t\tImNodes::Link(static_cast<int32_t>(Hash(src, dst)), static_cast<int32_t>(src), static_cast<int32_t>(dst));\n\t\t\t\tImNodes::PopColorStyle();\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid SetRenderPipeline(Resource<ResourceType::RenderPipeline> *resource, ResourceManager *manager)\n\t{\n\t\tImGui::PushItemWidth(100.f);\n\t\tchar buf[128] = {0};\n\t\tstd::memcpy(buf, m_pipeline_name.data(), sizeof(buf));\n\t\tif (ImGui::InputText(\"##NewRenderPipeline\", buf, sizeof(buf)))\n\t\t{\n\t\t\tm_pipeline_name = buf;\n\t\t}\n\t\tImGui::PopItemWidth();\n\n\t\tImGui::SameLine();\n\n\t\tif (!m_pipeline_name.empty() && !resource)\n\t\t{\n\t\t\tif (ImGui::Button(\"New Render Pipeline\"))\n\t\t\t{\n\t\t\t\tRenderGraphDesc desc;\n\t\t\t\tdesc.SetName(m_pipeline_name);\n\t\t\t\tmanager->Add<ResourceType::RenderPipeline>(p_editor->GetRHIContext(), m_pipeline_name, std::move(desc));\n\t\t\t\tresource = manager->Get<ResourceType::RenderPipeline>(m_pipeline_name);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tImGui::Text(\"Render Pipeline Name\");\n\t\t}\n\t}\n\n\tvoid DragDropResource()\n\t{\n\t\tif (ImGui::BeginDragDropTarget())\n\t\t{\n\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"RenderPipeline\"))\n\t\t\t{\n\t\t\t\tm_pipeline_name = static_cast<const char *>(pay_load->Data);\n\t\t\t\tauto *resource  = p_editor->GetRenderer()->GetResourceManager()->Get<ResourceType::RenderPipeline>(m_pipeline_name);\n\t\t\t\tif (resource)\n\t\t\t\t{\n\t\t\t\t\tImNodes::LoadCurrentEditorStateFromIniString(resource->GetLayout().data(), resource->GetLayout().length());\n\t\t\t\t\tauto &desc = resource->GetDesc();\n\t\t\t\t\tfor (auto &[node_handle, node] : desc.GetPasses())\n\t\t\t\t\t{\n\t\t\t\t\t\tm_current_handle = glm::max(m_current_handle, node_handle + 1);\n\t\t\t\t\t\tfor (auto &[pin_handle, pin] : node.GetPins())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_current_handle = glm::max(m_current_handle, pin_handle + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid DrawInspector()\n\t{\n\t\tImGui::BeginChild(\"Render Graph Inspector\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\tif (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())\n\t\t{\n\t\t\tImGui::SetScrollHereY(1.0f);\n\t\t}\n\n\t\tImGui::EndChild();\n\t}\n\n  private:\n\tImNodesEditorContext *m_context = nullptr;\n\n\tstd::string m_pipeline_name = \"\";\n\n\tsize_t m_current_handle = 0;\n\n\tstd::vector<int32_t> m_select_nodes;\n\tstd::vector<int32_t> m_select_links;\n\n\tstd::vector<int32_t> m_new_nodes;\n\n\tstd::vector<std::tuple<int32_t, int32_t, uint32_t>> m_edges;\n\n\tstd::map<RenderPassPin::Type, uint32_t> m_color = {\n\t    {RenderPassPin::Type::Buffer, IM_COL32(0, 128, 0, 255)},\n\t    {RenderPassPin::Type::Texture, IM_COL32(128, 0, 0, 255)},\n\t    {RenderPassPin::Type::Unknown, IM_COL32(255, 255, 255, 255)},\n\t};\n};\n\nextern \"C\"\n{\n\tEXPORT_API RenderGraphEditor *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new RenderGraphEditor(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/ResourceBrowser.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/Resource.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\n#include <nfd.h>\n\nusing namespace Ilum;\n\nclass ResourceBrowser : public Widget\n{\n  public:\n\tResourceBrowser(Editor *editor) :\n\t    Widget(\"Resource Browser\", editor)\n\t{\n\t}\n\n\tvirtual ~ResourceBrowser() = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tauto *resource_manager = p_editor->GetRenderer()->GetResourceManager();\n\n\t\tImGui::Columns(2);\n\t\tImGui::SetColumnWidth(0, 200.f);\n\n\t\tImGui::BeginChild(\"Resource Browser Category\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\tif (ImGui::Button(\"Import\"))\n\t\t{\n\t\t\tchar *path = nullptr;\n\t\t\tif (NFD_OpenDialog(\"jpg,png,bmp,jpeg,dds,hdr,gltf,obj,glb,fbx,ply,blend,dae,mat\", Path::GetInstance().GetCurrent(false).c_str(), &path) == NFD_OKAY)\n\t\t\t{\n\t\t\t\tResourceType type = m_resource_map.at(Path::GetInstance().GetFileExtension(path));\n\t\t\t\tswitch (type)\n\t\t\t\t{\n\t\t\t\t\tcase ResourceType::Prefab:\n\t\t\t\t\t\tresource_manager->Import<ResourceType::Prefab>(path);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ResourceType::Texture2D:\n\t\t\t\t\t\tresource_manager->Import<ResourceType::Texture2D>(path);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ResourceType::TextureCube:\n\t\t\t\t\t\tresource_manager->Import<ResourceType::TextureCube>(path);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &[type, name] : m_resource_types)\n\t\t{\n\t\t\tbool open = ImGui::TreeNodeEx(name, ImGuiTreeNodeFlags_FramePadding | ImGuiTreeNodeFlags_DefaultOpen | (m_current_type == type ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_Leaf);\n\t\t\tif (ImGui::IsItemClicked())\n\t\t\t{\n\t\t\t\tm_current_type = type;\n\t\t\t}\n\n\t\t\tif (open)\n\t\t\t{\n\t\t\t\tImGui::TreePop();\n\t\t\t}\n\t\t}\n\n\t\tif (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())\n\t\t{\n\t\t\tImGui::SetScrollHereY(1.0f);\n\t\t}\n\n\t\tImGui::EndChild();\n\n\t\tImGui::NextColumn();\n\n\t\tImGui::BeginChild(\"Resource Browser Viewer\", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);\n\n\t\tstd::unordered_map<ResourceType, std::function<void(void)>> draw_resources = {\n#define DRAW_RESOURCE(TYPE)                                          \\\n\t{                                                                \\\n\t\tTYPE, [&]() { DrawResource<TYPE>(resource_manager, 100.f); } \\\n\t}\n\n\t\t    DRAW_RESOURCE(ResourceType::Prefab),\n\t\t    DRAW_RESOURCE(ResourceType::Mesh),\n\t\t    DRAW_RESOURCE(ResourceType::SkinnedMesh),\n\t\t    DRAW_RESOURCE(ResourceType::Texture2D),\n\t\t    DRAW_RESOURCE(ResourceType::TextureCube),\n\t\t    DRAW_RESOURCE(ResourceType::Material),\n\t\t    DRAW_RESOURCE(ResourceType::Animation),\n\t\t    DRAW_RESOURCE(ResourceType::RenderPipeline),\n\t\t    DRAW_RESOURCE(ResourceType::Scene),\n\t\t};\n\n\t\tdraw_resources.at(m_current_type)();\n\n\t\tif (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())\n\t\t{\n\t\t\tImGui::SetScrollHereY(1.0f);\n\t\t}\n\n\t\tImGui::EndChild();\n\n\t\tImGui::End();\n\t}\n\n  private:\n\ttemplate <ResourceType _Ty>\n\tinline void DrawResource(ResourceManager *manager, float button_size)\n\t{\n\t\tfloat width = 0.f;\n\n\t\tImGuiStyle &style    = ImGui::GetStyle();\n\t\tstyle.ItemSpacing    = ImVec2(10.f, 10.f);\n\t\tfloat window_visible = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;\n\n\t\tconst std::vector<std::string> resources = manager->GetResources<_Ty>(false);\n\n\t\tfor (const auto &resource_name : resources)\n\t\t{\n\t\t\tauto *thumbnail = manager->GetThumbnail<_Ty>(resource_name);\n\n\t\t\tImGui::PushID(resource_name.c_str());\n\t\t\tImGui::ImageButton(thumbnail ? thumbnail : ImGui::GetIO().Fonts->TexID, ImVec2{button_size, button_size});\n\n\t\t\t// Drag&Drop source\n\t\t\tif (ImGui::BeginDragDropSource())\n\t\t\t{\n\t\t\t\tImGui::SetDragDropPayload(m_resource_types.at(_Ty), resource_name.c_str(), resource_name.length() + 1);\n\t\t\t\tImGui::EndDragDropSource();\n\t\t\t}\n\n\t\t\tif (ImGui::BeginPopupContextItem(resource_name.c_str()))\n\t\t\t{\n\t\t\t\tif (ImGui::MenuItem(\"Delete\"))\n\t\t\t\t{\n\t\t\t\t\tmanager->Erase<_Ty>(resource_name);\n\t\t\t\t\tImGui::EndPopup();\n\t\t\t\t\tImGui::PopID();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tImGui::EndPopup();\n\t\t\t}\n\t\t\telse if (ImGui::IsItemHovered() && ImGui::IsWindowFocused())\n\t\t\t{\n\t\t\t\tImVec2 pos = ImGui::GetIO().MousePos;\n\t\t\t\tImGui::SetNextWindowPos(ImVec2(pos.x + 10.f, pos.y + 10.f));\n\t\t\t\tImGui::Begin(resource_name.c_str(), NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar);\n\t\t\t\tImGui::Text(resource_name.c_str());\n\t\t\t\tImGui::End();\n\t\t\t}\n\n\t\t\tfloat last_button = ImGui::GetItemRectMax().x;\n\t\t\tfloat next_button = last_button + style.ItemSpacing.x + button_size;\n\t\t\tif (next_button < window_visible)\n\t\t\t{\n\t\t\t\tImGui::SameLine();\n\t\t\t}\n\n\t\t\tImGui::PopID();\n\t\t}\n\t}\n\n  private:\n\tResourceType m_current_type = ResourceType::Prefab;\n\n\tstd::unordered_map<ResourceType, const char *const> m_resource_types = {\n\t    {ResourceType::Mesh, \"Mesh\"},\n\t    {ResourceType::SkinnedMesh, \"SkinnedMesh\"},\n\t    {ResourceType::Prefab, \"Prefab\"},\n\t    {ResourceType::Texture2D, \"Texture2D\"},\n\t    {ResourceType::TextureCube, \"TextureCube\"},\n\t    {ResourceType::Animation, \"Animation\"},\n\t    {ResourceType::Material, \"Material\"},\n\t    {ResourceType::RenderPipeline, \"RenderPipeline\"},\n\t    {ResourceType::Scene, \"Scene\"},\n\t};\n\n\tstd::unordered_map<std::string, ResourceType> m_resource_map = {\n\t    {\".jpg\", ResourceType::Texture2D},\n\t    {\".png\", ResourceType::Texture2D},\n\t    {\".bmp\", ResourceType::Texture2D},\n\t    {\".jpeg\", ResourceType::Texture2D},\n\t    {\".dds\", ResourceType::Texture2D},\n\t    {\".hdr\", ResourceType::TextureCube},\n\t    {\".gltf\", ResourceType::Prefab},\n\t    {\".obj\", ResourceType::Prefab},\n\t    {\".glb\", ResourceType::Prefab},\n\t    {\".fbx\", ResourceType::Prefab},\n\t    {\".ply\", ResourceType::Prefab},\n\t    {\".dae\", ResourceType::Prefab},\n\t};\n};\n\nextern \"C\"\n{\n\tEXPORT_API ResourceBrowser *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new ResourceBrowser(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/SceneView.cpp",
    "content": "#pragma once\n\n#include <Core/Window.hpp>\n#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/Resource/Animation.hpp>\n#include <Resource/Resource/Prefab.hpp>\n#include <Resource/Resource/RenderPipeline.hpp>\n#include <Resource/Resource/Scene.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Node.hpp>\n#include <Scene/Scene.hpp>\n\n#include <glm/glm.hpp>\n#include <glm/gtc/type_ptr.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\n#include <IconsFontAwesome/IconsFontAwesome5.h>\n\n#include <ImGuizmo/ImGuizmo.h>\n\n#include <GLFW/glfw3.h>\n\n#define STB_IMAGE_WRITE_IMPLEMENTATION\n#include <stb/stb_image_write.h>\n\n#include <nfd.h>\n\nusing namespace Ilum;\n\ninline glm::vec3 SmoothStep(const glm::vec3 &v1, const glm::vec3 &v2, float t)\n{\n\tt = glm::clamp(t, 0.f, 1.f);\n\tt = t * t * (3.f - 2.f * t);\n\n\tglm::vec3 v = glm::mix(v1, v2, t);\n\n\treturn v;\n}\n\nclass SceneView : public Widget\n{\n  private:\n\tstruct\n\t{\n\t\tfloat speed     = 1.f;\n\t\tfloat sensitity = 3.f;\n\n\t\tglm::vec3 velocity = glm::vec3(0.f);\n\t\tglm::vec2 viewport = glm::vec2(0.f);\n\t} m_camera_config;\n\n\tglm::vec2 m_cursor_position = glm::vec2(0.f);\n\n\tbool m_hide_cursor = false;\n\n  public:\n\tSceneView(Editor *editor) :\n\t    Widget(\"Scene View\", editor)\n\t{\n\t\tglfwInit();\n\t}\n\n\tvirtual ~SceneView() override\n\t{\n\t\tglfwTerminate();\n\t}\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!p_editor->GetMainCamera())\n\t\t{\n\t\t\tauto perspectives = p_editor->GetRenderer()->GetScene()->GetComponents<Cmpt::PerspectiveCamera>();\n\t\t\tif (!perspectives.empty())\n\t\t\t{\n\t\t\t\tp_editor->SetMainCamera(perspectives[0]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto orthographics = p_editor->GetRenderer()->GetScene()->GetComponents<Cmpt::OrthographicCamera>();\n\t\t\t\tif (!orthographics.empty())\n\t\t\t\t{\n\t\t\t\t\tp_editor->SetMainCamera(orthographics[0]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!ImGui::Begin(m_name.c_str()))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tUpdateAnimation();\n\n\t\tShowToolBar();\n\n\t\tauto *camera = p_editor->GetMainCamera();\n\n\t\tImGuizmo::SetDrawlist();\n\n\t\tImVec2 offset              = ImGui::GetCursorPos();\n\t\tImVec2 scene_view_size     = ImVec2(ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x, ImGui::GetWindowContentRegionMax().y - ImGui::GetWindowContentRegionMin().y);\n\t\tImVec2 scene_view_position = ImVec2(ImGui::GetWindowPos().x + offset.x, ImGui::GetWindowPos().y + offset.y);\n\n\t\tm_camera_config.viewport.x = scene_view_size.x - (static_cast<uint32_t>(scene_view_size.x) % 2 != 0 ? 1.0f : 0.0f);\n\t\tm_camera_config.viewport.y = scene_view_size.y - (static_cast<uint32_t>(scene_view_size.y) % 2 != 0 ? 1.0f : 0.0f);\n\n\t\tif (camera)\n\t\t{\n\t\t\tUpdateCamera();\n\t\t}\n\n\t\tImGuizmo::SetRect(scene_view_position.x, scene_view_position.y, m_camera_config.viewport.x, m_camera_config.viewport.y);\n\n\t\tif (camera)\n\t\t{\n\t\t\tImGuizmo::DrawGrid(glm::value_ptr(camera->GetViewMatrix()), glm::value_ptr(camera->GetProjectionMatrix()), glm::value_ptr(glm::mat4(1.0)), 1000.f);\n\t\t}\n\n\t\tDisplayPresent();\n\n\t\tMoveEntity();\n\n\t\tImGui::End();\n\t}\n\n  private:\n\ttemplate <ResourceType _Ty>\n\tvoid DropTarget(Editor *editor, const std::string &name)\n\t{\n\t}\n\n\ttemplate <>\n\tvoid DropTarget<ResourceType::Mesh>(Editor *editor, const std::string &name)\n\t{\n\t\tauto *resource = editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Mesh>(name);\n\t\tif (resource)\n\t\t{\n\t\t\tauto *node = p_editor->GetRenderer()->GetScene()->CreateNode(resource->GetName());\n\t\t\tnode->AddComponent<Cmpt::Transform>(std::make_unique<Cmpt::Transform>(node));\n\t\t\tauto *mesh_renderer = node->AddComponent<Cmpt::MeshRenderer>(std::make_unique<Cmpt::MeshRenderer>(node));\n\t\t\tmesh_renderer->AddSubmesh(resource->GetName());\n\t\t}\n\t}\n\n\ttemplate <>\n\tvoid DropTarget<ResourceType::Prefab>(Editor *editor, const std::string &name)\n\t{\n\t\tauto *prefab = editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Prefab>(name);\n\n\t\tif (prefab)\n\t\t{\n\t\t\tauto &root  = prefab->GetRoot();\n\t\t\tauto *scene = editor->GetRenderer()->GetScene();\n\n\t\t\tstd::function<Node *(decltype(root) &)> create_node = [&](decltype(root) &prefab_node) {\n\t\t\t\tNode *node = scene->CreateNode(prefab_node.name);\n\n\t\t\t\tCmpt::Transform *transform   = node->AddComponent<Cmpt::Transform>(std::make_unique<Cmpt::Transform>(node));\n\t\t\t\tglm::vec3        translation = glm::vec3(0.f);\n\t\t\t\tglm::vec3        rotation    = glm::vec3(0.f);\n\t\t\t\tglm::vec3        scale       = glm::vec3(0.f);\n\t\t\t\tImGuizmo::DecomposeMatrixToComponents(\n\t\t\t\t    glm::value_ptr(prefab_node.transform),\n\t\t\t\t    glm::value_ptr(translation),\n\t\t\t\t    glm::value_ptr(rotation),\n\t\t\t\t    glm::value_ptr(scale));\n\t\t\t\ttransform->SetTranslation(translation);\n\t\t\t\ttransform->SetRotation(rotation);\n\t\t\t\ttransform->SetScale(scale);\n\n\t\t\t\tstd::vector<std::string> materials;\n\t\t\t\tstd::vector<std::string> animations;\n\t\t\t\tCmpt::Renderable        *renderable = nullptr;\n\t\t\t\tfor (auto &[type, uuid] : prefab_node.resources)\n\t\t\t\t{\n\t\t\t\t\tswitch (type)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase ResourceType::Mesh: {\n\t\t\t\t\t\t\tCmpt::MeshRenderer *mesh_renderer = node->HasComponent<Cmpt::MeshRenderer>() ?\n\t\t\t\t\t\t\t                                        node->GetComponent<Cmpt::MeshRenderer>() :\n\t\t\t\t\t\t\t                                        node->AddComponent<Cmpt::MeshRenderer>(std::make_unique<Cmpt::MeshRenderer>(node));\n\t\t\t\t\t\t\tmesh_renderer->AddSubmesh(uuid);\n\t\t\t\t\t\t\trenderable = mesh_renderer;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ResourceType::SkinnedMesh: {\n\t\t\t\t\t\t\tCmpt::SkinnedMeshRenderer *skinned_mesh_renderer = node->HasComponent<Cmpt::SkinnedMeshRenderer>() ?\n\t\t\t\t\t\t\t                                                       node->GetComponent<Cmpt::SkinnedMeshRenderer>() :\n\t\t\t\t\t\t\t                                                       node->AddComponent<Cmpt::SkinnedMeshRenderer>(std::make_unique<Cmpt::SkinnedMeshRenderer>(node));\n\t\t\t\t\t\t\tskinned_mesh_renderer->AddSubmesh(uuid);\n\t\t\t\t\t\t\trenderable = skinned_mesh_renderer;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ResourceType::Material: {\n\t\t\t\t\t\t\tmaterials.push_back(uuid);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ResourceType::Animation: {\n\t\t\t\t\t\t\tanimations.push_back(uuid);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (renderable)\n\t\t\t\t{\n\t\t\t\t\tfor (auto &uuid : materials)\n\t\t\t\t\t{\n\t\t\t\t\t\trenderable->AddMaterial(uuid);\n\t\t\t\t\t}\n\t\t\t\t\tfor (auto &uuid : animations)\n\t\t\t\t\t{\n\t\t\t\t\t\trenderable->AddAnimation(uuid);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (auto &prefab_child : prefab_node.children)\n\t\t\t\t{\n\t\t\t\t\tNode *child = create_node(prefab_child);\n\t\t\t\t\tchild->SetParent(node);\n\t\t\t\t}\n\n\t\t\t\treturn node;\n\t\t\t};\n\n\t\t\tcreate_node(root);\n\t\t}\n\t}\n\n\ttemplate <>\n\tvoid DropTarget<ResourceType::RenderPipeline>(Editor *editor, const std::string &name)\n\t{\n\t\tauto *resource = editor->GetRenderer()->GetResourceManager()->Get<ResourceType::RenderPipeline>(name);\n\n\t\tif (resource)\n\t\t{\n\t\t\tauto *rhi_context  = editor->GetRHIContext();\n\t\t\tauto *renderer     = editor->GetRenderer();\n\t\t\tauto  render_graph = resource->Compile(rhi_context, renderer, m_camera_config.viewport);\n\n\t\t\tif (render_graph)\n\t\t\t{\n\t\t\t\trenderer->SetRenderGraph(std::move(render_graph));\n\t\t\t}\n\t\t}\n\t}\n\n\ttemplate <>\n\tvoid DropTarget<ResourceType::Scene>(Editor *editor, const std::string &name)\n\t{\n\t\tauto *resource = editor->GetRenderer()->GetResourceManager()->Get<ResourceType::Scene>(name);\n\t\tauto *scene    = editor->GetRenderer()->GetScene();\n\t\teditor->SelectNode();\n\n\t\tif (resource)\n\t\t{\n\t\t\teditor->SetMainCamera();\n\t\t\tauto *rhi_context = editor->GetRHIContext();\n\t\t\tresource->Update(scene);\n\t\t\tm_scene_name = name;\n\t\t\tscene->SetName(m_scene_name);\n\t\t}\n\t}\n\n\tvoid DropTarget(Editor *editor)\n\t{\n#define DROP_TARGET(TYPE)                                                                  \\\n\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(#TYPE))                        \\\n\t{                                                                                      \\\n\t\tDropTarget<ResourceType::TYPE>(editor, static_cast<const char *>(pay_load->Data)); \\\n\t}\n\n\t\tDROP_TARGET(Prefab)\n\t\tDROP_TARGET(RenderPipeline)\n\t\tDROP_TARGET(Scene)\n\t\tDROP_TARGET(Mesh)\n\t}\n\n\tvoid DisplayPresent()\n\t{\n\t\tauto *renderer = p_editor->GetRenderer();\n\t\trenderer->SetViewport(m_camera_config.viewport.x, m_camera_config.viewport.y);\n\n\t\tauto *present_texture = renderer->GetPresentTexture();\n\n\t\tif (present_texture)\n\t\t{\n\t\t\tImGui::Image(present_texture, ImGui::GetContentRegionAvail());\n\t\t}\n\n\t\tif (ImGui::BeginDragDropTarget())\n\t\t{\n\t\t\tDropTarget(p_editor);\n\t\t}\n\t}\n\n\tvoid UpdateCamera()\n\t{\n\t\tauto *camera    = p_editor->GetMainCamera();\n\t\tauto *transform = camera->GetNode()->GetComponent<Cmpt::Transform>();\n\n\t\tglm::mat4 view_matrix = camera->GetViewMatrix();\n\n\t\tcamera->SetAspect(m_camera_config.viewport.x / m_camera_config.viewport.y);\n\n\t\tif (!ImGui::IsWindowFocused() || !ImGui::IsWindowHovered())\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (ImGui::IsMouseDown(ImGuiMouseButton_Right))\n\t\t{\n\t\t\tif (!m_hide_cursor)\n\t\t\t{\n\t\t\t\tm_hide_cursor     = true;\n\t\t\t\tm_cursor_position = p_editor->GetWindow()->GetMousePosition();\n\t\t\t}\n\n\t\t\tauto delta_time = ImGui::GetIO().DeltaTime;\n\t\t\tauto delta_pos  = p_editor->GetWindow()->GetMousePosition() - m_cursor_position;\n\t\t\tp_editor->GetWindow()->SetCursorPosition(m_cursor_position);\n\t\t\tImGui::SetMouseCursor(ImGuiMouseCursor_None);\n\n\t\t\tfloat yaw   = std::atan2f(-view_matrix[2][2], -view_matrix[0][2]);\n\t\t\tfloat pitch = std::asinf(-glm::clamp(view_matrix[1][2], -0.99f, 0.99f));\n\n\t\t\tif (delta_pos.x != 0.f)\n\t\t\t{\n\t\t\t\tyaw += m_camera_config.sensitity * delta_time * delta_pos.x * 0.1f;\n\t\t\t\tglm::vec3 rotation = transform->GetRotation();\n\t\t\t\trotation.y         = -glm::degrees(yaw) - 90.f;\n\t\t\t\ttransform->SetRotation(rotation);\n\t\t\t}\n\n\t\t\tif (delta_pos.y != 0.f)\n\t\t\t{\n\t\t\t\tpitch -= m_camera_config.sensitity * delta_time * delta_pos.y * 0.1f;\n\t\t\t\tglm::vec3 rotation = transform->GetRotation();\n\t\t\t\trotation.x         = glm::degrees(pitch);\n\t\t\t\ttransform->SetRotation(rotation);\n\t\t\t}\n\n\t\t\tglm::vec3 forward = {};\n\n\t\t\tforward.x = glm::cos(yaw) * glm::cos(pitch);\n\t\t\tforward.y = glm::sin(pitch);\n\t\t\tforward.z = glm::sin(yaw) * glm::cos(pitch);\n\n\t\t\tforward = glm::normalize(forward);\n\n\t\t\tglm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3{0.f, 1.f, 0.f}));\n\t\t\tglm::vec3 up    = glm::normalize(glm::cross(right, forward));\n\n\t\t\tglm::vec3 direction = glm::vec3(0.f);\n\n\t\t\tm_camera_config.speed = glm::clamp(m_camera_config.speed + 0.5f * ImGui::GetIO().MouseWheel, 0.f, 30.f);\n\n\t\t\tif (p_editor->GetWindow()->IsKeyPressed(KeyCode::W))\n\t\t\t{\n\t\t\t\tdirection += forward;\n\t\t\t}\n\t\t\tif (p_editor->GetWindow()->IsKeyPressed(KeyCode::S))\n\t\t\t{\n\t\t\t\tdirection -= forward;\n\t\t\t}\n\t\t\tif (p_editor->GetWindow()->IsKeyPressed(KeyCode::D))\n\t\t\t{\n\t\t\t\tdirection += right;\n\t\t\t}\n\t\t\tif (p_editor->GetWindow()->IsKeyPressed(KeyCode::A))\n\t\t\t{\n\t\t\t\tdirection -= right;\n\t\t\t}\n\t\t\tif (p_editor->GetWindow()->IsKeyPressed(KeyCode::Q))\n\t\t\t{\n\t\t\t\tdirection += up;\n\t\t\t}\n\t\t\tif (p_editor->GetWindow()->IsKeyPressed(KeyCode::E))\n\t\t\t{\n\t\t\t\tdirection -= up;\n\t\t\t}\n\n\t\t\tm_camera_config.velocity = SmoothStep(m_camera_config.velocity, direction * m_camera_config.speed, 0.2f);\n\n\t\t\ttransform->SetTranslation(transform->GetTranslation() + delta_time * m_camera_config.velocity);\n\t\t}\n\t\telse if (m_hide_cursor)\n\t\t{\n\t\t\tm_hide_cursor            = false;\n\t\t\tm_camera_config.velocity = glm::vec3(0.f);\n\t\t}\n\n\t\tp_editor->GetRenderer()->UpdateView(camera);\n\t}\n\n\tvoid MoveEntity()\n\t{\n\t\tNode *node   = p_editor->GetSelectedNode();\n\t\tauto *camera = p_editor->GetMainCamera();\n\n\t\tif (!node || !camera)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tauto *transform = node->GetComponent<Cmpt::Transform>();\n\n\t\tglm::mat4 local_transform = transform->GetLocalTransform();\n\n\t\tif (ImGuizmo::Manipulate(\n\t\t        glm::value_ptr(camera->GetViewMatrix()),\n\t\t        glm::value_ptr(camera->GetProjectionMatrix()),\n\t\t        ImGuizmo::OPERATION::UNIVERSAL,\n\t\t        ImGuizmo::WORLD, glm::value_ptr(local_transform), NULL, NULL, NULL, NULL))\n\t\t{\n\t\t\tglm::vec3 translation = glm::vec3(0.f);\n\t\t\tglm::vec3 rotation    = glm::vec3(0.f);\n\t\t\tglm::vec3 scale       = glm::vec3(0.f);\n\n\t\t\tImGuizmo::DecomposeMatrixToComponents(glm::value_ptr(local_transform),\n\t\t\t                                      glm::value_ptr(translation),\n\t\t\t                                      glm::value_ptr(rotation),\n\t\t\t                                      glm::value_ptr(scale));\n\t\t\ttransform->SetTranslation(translation);\n\t\t\ttransform->SetRotation(rotation);\n\t\t\ttransform->SetScale(scale);\n\t\t}\n\t}\n\n\tvoid ShowToolBar()\n\t{\n#define SHOW_TIPS(str)               \\\n\tif (ImGui::IsItemHovered())      \\\n\t{                                \\\n\t\tImGui::BeginTooltip();       \\\n\t\tImGui::TextUnformatted(str); \\\n\t\tImGui::EndTooltip();         \\\n\t}\n\n\t\tImGui::Indent();\n\t\tImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));\n\t\tImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.f);\n\t\tImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 0.f));\n\t\tImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5.f, 5.f));\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(\"Scene\", ImVec2(60.f, 20.f)))\n\t\t{\n\t\t\tImGui::OpenPopup(\"ScenePopup\");\n\t\t}\n\n\t\tSHOW_TIPS(\"Scene\");\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(ICON_FA_CAMERA, ImVec2(20.f, 20.f)))\n\t\t{\n\t\t\tImGui::OpenPopup(\"CameraPopup\");\n\t\t}\n\n\t\tSHOW_TIPS(\"Camera\");\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(ICON_FA_SAVE, ImVec2(20.f, 20.f)))\n\t\t{\n\t\t\tauto *present_texture = p_editor->GetRenderer()->GetPresentTexture();\n\t\t\tauto *rhi_context     = p_editor->GetRHIContext();\n\t\t\t char *path            = nullptr;\n\n\t\t\tif (present_texture && NFD_SaveDialog(\"png\", Path::GetInstance().GetCurrent(false).c_str(), &path) == NFD_OKAY)\n\t\t\t{\n\t\t\t\tauto  staging_texture = rhi_context->CreateTexture2D(present_texture->GetDesc().width, present_texture->GetDesc().height, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::Transfer, false);\n\t\t\t\tauto  staging_buffer  = rhi_context->CreateBuffer(GetFormatStride(staging_texture->GetDesc().format) * staging_texture->GetDesc().width * staging_texture->GetDesc().height, RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_TO_CPU);\n\t\t\t\tauto *cmd_buffer      = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\t\t\tcmd_buffer->Begin();\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {TextureStateTransition{present_texture, RHIResourceState::ShaderResource, RHIResourceState::TransferSource},\n\t\t\t\t     TextureStateTransition{staging_texture.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest}},\n\t\t\t\t    {});\n\t\t\t\tcmd_buffer->BlitTexture(present_texture, {}, RHIResourceState::TransferSource, staging_texture.get(), {}, RHIResourceState::TransferDest);\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {TextureStateTransition{staging_texture.get(), RHIResourceState::TransferDest, RHIResourceState::TransferSource}},\n\t\t\t\t    {});\n\t\t\t\tcmd_buffer->CopyTextureToBuffer(staging_texture.get(), staging_buffer.get(), 0, 0, 1);\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {TextureStateTransition{present_texture, RHIResourceState::TransferSource, RHIResourceState::ShaderResource}}, {});\n\t\t\t\tcmd_buffer->End();\n\t\t\t\trhi_context->Execute(cmd_buffer);\n\n\t\t\t\tstd::vector<uint8_t> staging_data(staging_buffer->GetDesc().size);\n\t\t\t\tstaging_buffer->CopyToHost(staging_data.data(), staging_buffer->GetDesc().size);\n\n\n\t\t\t\tstbi_write_png(\n\t\t\t\t    (Path::GetInstance().GetFileName(path, false) + \".png\").c_str(),\n\t\t\t\t    static_cast<int32_t>(staging_texture->GetDesc().width),\n\t\t\t\t    static_cast<int32_t>(staging_texture->GetDesc().height),\n\t\t\t\t    4, staging_data.data(), static_cast<int32_t>(staging_texture->GetDesc().width) * 4);\n\t\t\t}\n\t\t}\n\n\t\tSHOW_TIPS(\"Save\");\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(m_play_animation ? ICON_FA_PAUSE : ICON_FA_PLAY, ImVec2(20.f, 20.f)))\n\t\t{\n\t\t\tm_play_animation = !m_play_animation;\n\t\t}\n\n\t\tif (m_play_animation)\n\t\t{\n\t\t\tm_animation_time += ImGui::GetIO().DeltaTime * 0.5f;\n\t\t\tif (m_animation_time > p_editor->GetRenderer()->GetMaxAnimationTime())\n\t\t\t{\n\t\t\t\tm_animation_time = 0.f;\n\t\t\t}\n\t\t}\n\n\t\tImGui::SameLine();\n\n\t\tImGui::PushItemWidth(200.f);\n\t\tif (ImGui::SliderFloat(\"Animation Time\", &m_animation_time, 0.f, p_editor->GetRenderer()->GetMaxAnimationTime()) || m_play_animation)\n\t\t{\n\t\t\tp_editor->GetRenderer()->SetAnimationTime(m_animation_time);\n\t\t}\n\t\tImGui::PopItemWidth();\n\n\t\tSHOW_TIPS(\"Play Animation\");\n\n\t\tif (ImGui::BeginPopup(\"CameraPopup\"))\n\t\t{\n\t\t\tauto perspective_cameras  = p_editor->GetRenderer()->GetScene()->GetComponents<Cmpt::PerspectiveCamera>();\n\t\t\tauto orthographic_cameras = p_editor->GetRenderer()->GetScene()->GetComponents<Cmpt::OrthographicCamera>();\n\n\t\t\tImGui::PushItemWidth(80.f);\n\t\t\tImGui::Text(\"Camera Properties\");\n\t\t\tif ((!perspective_cameras.empty() || !orthographic_cameras.empty()) && ImGui::BeginMenu(\"Main Camera\"))\n\t\t\t{\n\t\t\t\tfor (auto &perspective_camera : perspective_cameras)\n\t\t\t\t{\n\t\t\t\t\tbool selected = perspective_camera == p_editor->GetMainCamera();\n\t\t\t\t\tif (ImGui::MenuItem(perspective_camera->GetNode()->GetName().c_str(), nullptr, &selected))\n\t\t\t\t\t{\n\t\t\t\t\t\tp_editor->SetMainCamera(perspective_camera);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (auto &orthographic_camera : orthographic_cameras)\n\t\t\t\t{\n\t\t\t\t\tbool selected = orthographic_camera == p_editor->GetMainCamera();\n\t\t\t\t\tif (ImGui::MenuItem(orthographic_camera->GetNode()->GetName().c_str(), nullptr, &selected))\n\t\t\t\t\t{\n\t\t\t\t\t\tp_editor->SetMainCamera(orthographic_camera);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\t\t\tImGui::DragFloat(\"Speed\", &m_camera_config.speed, 0.01f, 0.f, std::numeric_limits<float>::max());\n\t\t\tImGui::DragFloat(\"Sensitity\", &m_camera_config.sensitity, 0.01f, 0.f, std::numeric_limits<float>::max());\n\t\t\tImGui::PopItemWidth();\n\t\t\tImGui::EndPopup();\n\t\t}\n\n\t\tif (ImGui::BeginPopup(\"ScenePopup\"))\n\t\t{\n\t\t\tauto *manager = p_editor->GetRenderer()->GetResourceManager();\n\t\t\tauto *scene   = p_editor->GetRenderer()->GetScene();\n\n\t\t\tImGui::PushItemWidth(80.f);\n\t\t\tchar buf[128] = {0};\n\t\t\tstd::memcpy(buf, m_scene_name.data(), sizeof(buf));\n\t\t\tif (ImGui::InputText(\"##NewScene\", buf, sizeof(buf)))\n\t\t\t{\n\t\t\t\tm_scene_name = buf;\n\t\t\t}\n\n\t\t\tauto *resource = manager->Get<ResourceType::Scene>(m_scene_name);\n\n\t\t\tif (!m_scene_name.empty() && !resource)\n\t\t\t{\n\t\t\t\tif (ImGui::Button(\"New Scene\"))\n\t\t\t\t{\n\t\t\t\t\tmanager->Add<ResourceType::Scene>(p_editor->GetRHIContext(), m_scene_name, scene);\n\t\t\t\t\tresource = manager->Get<ResourceType::Scene>(m_scene_name);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (ImGui::Button(\"Save Scene\"))\n\t\t\t\t{\n\t\t\t\t\tresource->Save(p_editor->GetRHIContext(), scene);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::PopItemWidth();\n\t\t\tImGui::EndPopup();\n\t\t}\n\n\t\tImGui::PopStyleVar();\n\t\tImGui::PopStyleVar();\n\t\tImGui::PopStyleVar();\n\t\tImGui::PopStyleColor();\n\n\t\tImGui::Unindent();\n\t}\n\n\tvoid UpdateAnimation()\n\t{\n\t\tif (m_play_animation)\n\t\t{\n\t\t\tm_animation_time += ImGui::GetIO().DeltaTime;\n\n\t\t\tauto *resource_manager = p_editor->GetRenderer()->GetResourceManager();\n\t\t\tauto  animation_names  = resource_manager->GetResources<ResourceType::Animation>();\n\t\t\tfor (auto &animation_name : animation_names)\n\t\t\t{\n\t\t\t\tauto *animation = resource_manager->Get<ResourceType::Animation>(animation_name);\n\t\t\t}\n\t\t}\n\t}\n\n  private:\n\tstd::map<std::string, std::unique_ptr<RHITexture>> m_icons;\n\n\tstd::string m_scene_name = \"\";\n\n\tfloat m_animation_time = 0.f;\n\tbool  m_play_animation = false;\n};\n\nextern \"C\"\n{\n\tEXPORT_API SceneView *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new SceneView(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/ShaderToy.cpp",
    "content": "#include <Editor/Editor.hpp>\n#include <Editor/Widget.hpp>\n#include <Renderer/Renderer.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\nusing namespace Ilum;\n\nclass ShaderToy : public Widget\n{\n  public:\n\tShaderToy(Editor *editor) :\n\t    Widget(\"Shader Toy\", editor)\n\t{\n\t}\n\n\tvirtual ~ShaderToy() override = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tif (!ImGui::Begin(m_name.c_str(), nullptr, ImGuiWindowFlags_MenuBar))\n\t\t{\n\t\t\tImGui::End();\n\t\t\treturn;\n\t\t}\n\n\t\tif (ImGui::BeginMenuBar())\n\t\t{\n\t\t\tif (ImGui::MenuItem(\"Load\"))\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tImGui::EndMenuBar();\n\t\t}\n\n\n\t\tImGui::End();\n\t}\n};\n\nextern \"C\"\n{\n\tEXPORT_API ShaderToy *Create(Editor *editor, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\t\treturn new ShaderToy(editor);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Editor/xmake.lua",
    "content": "function add_editor_plugin(name, deps, pkgs)\n    target(string.format(\"Editor.%s\", name))\n\n    set_kind(\"shared\")\n    set_group(\"Plugin/Editor\")\n\n    add_rules(\"plugin\")\n    add_files(string.format(\"%s.cpp\", name))\n    add_deps(\"Core\", \"RHI\", \"Renderer\", \"Editor\", deps)\n    add_packages(\"imgui\", pkgs)\n\n    target(\"Plugin\")\n        add_deps(string.format(\"Editor.%s\", name))\n    target_end()\n\n    target_end()\nend\n\nadd_editor_plugin(\"SceneView\", {\"Resource\", \"Scene\", \"RenderGraph\"}, {\"stb\", \"nativefiledialog\"})\nadd_editor_plugin(\"Hierarchy\", {\"Scene\"}, {})\nadd_editor_plugin(\"Inspector\", {\"Scene\", \"RenderGraph\"}, {})\nadd_editor_plugin(\"MainMenu\", {\"Scene\"}, {\"nativefiledialog\"})\nadd_editor_plugin(\"MeshEditor\", {\"Resource\", \"Geometry\"}, {})\nadd_editor_plugin(\"AnimationEditor\", {\"Resource\", \"Geometry\"}, {\"nativefiledialog\"})\nadd_editor_plugin(\"ResourceBrowser\", {\"Resource\"}, {\"nativefiledialog\"})\nadd_editor_plugin(\"RenderGraphEditor\", {\"Resource\", \"RenderGraph\"}, {\"nativefiledialog\"})\nadd_editor_plugin(\"MaterialGraphEditor\", {\"Resource\", \"Material\", \"Geometry\", \"RenderGraph\"}, {\"nativefiledialog\"})\n"
  },
  {
    "path": "Source/Plugin/Geometry/Parameterization/MinimumSurface.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/Geometry/Parameterization/Tutte.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/Geometry/Subdivision/Loop.cpp",
    "content": "#include <Geometry/MeshProcess.hpp>\n\nusing namespace Ilum;\n\nclass LoopSubdivision : public Subdivision\n{\n  public:\n\tvirtual TriMesh Execute(const TriMesh &mesh) override\n\t{\n\t\tstd::vector<VertexData> vertices = mesh.vertices;\n\t\tstd::vector<uint32_t>   indices  = mesh.indices;\n\n\t\tuint32_t old_vertices_count = static_cast<uint32_t>(vertices.size());\n\t\tuint32_t old_triangle_count = static_cast<uint32_t>(indices.size() / 3);\n\n\t\tstd::map<uint32_t, std::unordered_set<uint32_t>>                      vertex_connect_map;\n\t\tstd::map<uint32_t, std::vector<uint32_t>>                             triangle_connect_map;\n\t\tstd::unordered_map<std::pair<uint32_t, uint32_t>, uint32_t, PairHash> new_vertex_map;\n\n\t\tfor (uint32_t i = 0; i < indices.size(); i += 3)\n\t\t{\n\t\t\tfor (uint32_t j = 0; j < 3; j++)\n\t\t\t{\n\t\t\t\t// Adding vertex connection\n\t\t\t\tvertex_connect_map[indices[i + j]].insert(indices[i + (j + 1) % 3]);\n\t\t\t\tvertex_connect_map[indices[i + (j + 1) % 3]].insert(indices[i + j]);\n\n\t\t\t\t// Add triangle connection\n\t\t\t\ttriangle_connect_map[indices[i + j]].push_back(i / 3);\n\n\t\t\t\t// Adding new vertices\n\t\t\t\tuint32_t nv = 0;\n\t\t\t\tif (new_vertex_map.find(std::make_pair(indices[i + j], indices[i + (j + 1) % 3])) == new_vertex_map.end())\n\t\t\t\t{\n\t\t\t\t\tVertexData v;\n\t\t\t\t\tv.position = (vertices[indices[i + j]].position + vertices[indices[i + (j + 1) % 3]].position) * 0.5f;\n\t\t\t\t\tv.uv       = (vertices[indices[i + j]].uv + vertices[indices[i + (j + 1) % 3]].uv) * 0.5f;\n\t\t\t\t\tvertices.push_back(v);\n\n\t\t\t\t\tnew_vertex_map[std::make_pair(indices[i + j], indices[i + (j + 1) % 3])] = static_cast<uint32_t>(vertices.size() - 1);\n\t\t\t\t\tnew_vertex_map[std::make_pair(indices[i + (j + 1) % 3], indices[i + j])] = static_cast<uint32_t>(vertices.size() - 1);\n\n\t\t\t\t\tnv = static_cast<uint32_t>(vertices.size() - 1);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnv = new_vertex_map[std::make_pair(indices[i + j], indices[i + (j + 1) % 3])];\n\t\t\t\t}\n\n\t\t\t\tvertex_connect_map[nv].insert(indices[i + j]);\n\t\t\t\tvertex_connect_map[nv].insert(indices[i + (j + 1) % 3]);\n\t\t\t\ttriangle_connect_map[nv].push_back(i / 3);\n\t\t\t}\n\t\t}\n\n\t\t// Reconstruct mesh\n\t\tstd::vector<uint32_t> new_indices;\n\t\tfor (uint32_t i = 0; i < indices.size(); i += 3)\n\t\t{\n\t\t\tuint32_t v0 = indices[i];\n\t\t\tuint32_t v1 = indices[i + 1];\n\t\t\tuint32_t v2 = indices[i + 2];\n\n\t\t\tuint32_t nv0 = new_vertex_map[std::make_pair(v0, v1)];\n\t\t\tuint32_t nv1 = new_vertex_map[std::make_pair(v1, v2)];\n\t\t\tuint32_t nv2 = new_vertex_map[std::make_pair(v2, v0)];\n\n\t\t\tstd::vector<uint32_t> triangle_indices = {\n\t\t\t    v0, nv0, nv2,\n\t\t\t    nv0, v1, nv1,\n\t\t\t    nv2, nv1, v2,\n\t\t\t    nv1, nv2, nv0};\n\n\t\t\tnew_indices.insert(new_indices.end(), triangle_indices.begin(), triangle_indices.end());\n\t\t}\n\n\t\t// auto boundary_points = find_boundary(vertices, new_indices);\n\t\tstd::unordered_set<uint32_t> boundary_points;\n\n\t\t// Update new vertex position\n\t\t// 3/8 *(A+B)+1/8*(C+D)\n\t\t//\t\t\t\tD\n\t\t//           /   \\\n\t\t//         A-n-B\n\t\t//\t\t\t \\    /\n\t\t//            C\n\t\tstd::vector<VertexData> new_vertices(vertices.size());\n\n\t\tboundary_points.reserve(vertices.size());\n\t\tfor (uint32_t i = old_vertices_count; i < vertices.size(); i++)\n\t\t{\n\t\t\tVertexData new_vertex = {};\n\n\t\t\t// Check boundary\n\t\t\tif (triangle_connect_map[i].size() == 1)\n\t\t\t{\n\t\t\t\tfor (auto v : vertex_connect_map[i])\n\t\t\t\t{\n\t\t\t\t\tboundary_points.insert(v);\n\t\t\t\t\tnew_vertex.position += 0.5f * vertices[v].position;\n\t\t\t\t\tnew_vertex.uv += 0.5f * vertices[v].uv;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (auto t : triangle_connect_map[i])\n\t\t\t\t{\n\t\t\t\t\tfor (uint32_t j = 0; j < 3; j++)\n\t\t\t\t\t{\n\t\t\t\t\t\tnew_vertex.position += 0.125f * vertices[indices[3 * t + j]].position;\n\t\t\t\t\t\tnew_vertex.uv += 0.125f * vertices[indices[3 * t + j]].uv;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (auto v : vertex_connect_map[i])\n\t\t\t\t{\n\t\t\t\t\tnew_vertex.position += 0.125f * vertices[v].position;\n\t\t\t\t\tnew_vertex.uv += 0.125f * vertices[v].uv;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnew_vertices[i] = new_vertex;\n\t\t}\n\n\t\t// Update old vertex position\n\t\tfor (uint32_t i = 0; i < old_vertices_count; i++)\n\t\t{\n\t\t\tVertexData new_v = {};\n\n\t\t\tif (boundary_points.find(i) == boundary_points.end())\n\t\t\t{\n\t\t\t\tuint32_t degree = static_cast<uint32_t>(vertex_connect_map[i].size());\n\t\t\t\tfloat    u      = 0.f;\n\t\t\t\tif (degree == 3)\n\t\t\t\t{\n\t\t\t\t\tu = 3.f / 16.f;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tu = 3.f / (8.f * static_cast<float>(degree));\n\t\t\t\t}\n\n\t\t\t\tfor (auto v : vertex_connect_map[i])\n\t\t\t\t{\n\t\t\t\t\tnew_v.position += u * vertices[v].position;\n\t\t\t\t\tnew_v.uv += u * vertices[v].uv;\n\t\t\t\t}\n\t\t\t\tnew_v.position += (1 - static_cast<float>(degree) * u) * vertices[i].position;\n\t\t\t\tnew_v.uv += (1 - static_cast<float>(degree) * u) * vertices[i].uv;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnew_v.position = vertices[i].position;\n\t\t\t\tnew_v.uv       = vertices[i].uv;\n\t\t\t}\n\n\t\t\tnew_vertices[i] = new_v;\n\t\t}\n\n\t\tTriMesh result;\n\t\tresult.vertices = std::move(new_vertices);\n\t\tresult.indices  = std::move(new_indices);\n\t\tresult.GenerateNormal();\n\t\treturn result;\n\t}\n};\n\nextern \"C\"\n{\n\tEXPORT_API LoopSubdivision *Create()\n\t{\n\t\treturn new LoopSubdivision;\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Geometry/xmake.lua",
    "content": "function add_geometry_plugin(category, name)\n    target(string.format(\"Geometry.%s.%s\", category, name))\n\n    set_kind(\"shared\")\n    set_group(\"Plugin/Geometry\")\n\n    add_rules(\"plugin\")\n    add_files(string.format(\"%s/%s.cpp\", category, name))\n    add_deps(\"Core\", \"Geometry\")\n\n    target(\"Plugin\")\n        add_deps(string.format(\"Geometry.%s.%s\", category, name))\n    target_end()\n\n    target_end()\nend\n\nadd_geometry_plugin(\"Subdivision\", \"Loop\")"
  },
  {
    "path": "Source/Plugin/Importer/Assimp.cpp",
    "content": "#include <Resource/Importer.hpp>\n#include <Resource/Resource/Animation.hpp>\n#include <Resource/Resource/Material.hpp>\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/Resource/Prefab.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/Resource/Texture2D.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <Material/MaterialGraph.hpp>\n\n#include <Geometry/Meshlet.hpp>\n\n#include <assimp/DefaultLogger.hpp>\n#include <assimp/Importer.hpp>\n#include <assimp/material.h>\n#include <assimp/postprocess.h>\n#include <assimp/scene.h>\n\n#include <meshoptimizer.h>\n\n#include <glm/glm.hpp>\n#include <glm/gtc/quaternion.hpp>\n\n#include <stb_image.h>\n\nusing namespace Ilum;\n\nusing Vertex        = Resource<ResourceType::Mesh>::Vertex;\nusing SkinnedVertex = Resource<ResourceType::SkinnedMesh>::SkinnedVertex;\nusing Node          = Resource<ResourceType::Prefab>::Node;\n\ninline glm::mat4 ToMatrix(const aiMatrix4x4 &matrix)\n{\n\treturn glm::mat4(\n\t    matrix.a1, matrix.b1, matrix.c1, matrix.d1,\n\t    matrix.a2, matrix.b2, matrix.c2, matrix.d2,\n\t    matrix.a3, matrix.b3, matrix.c3, matrix.d3,\n\t    matrix.a4, matrix.b4, matrix.c4, matrix.d4);\n}\n\ninline glm::mat3 ToMatrix(const aiMatrix3x3 &matrix)\n{\n\treturn glm::mat3(\n\t    matrix.a1, matrix.b1, matrix.c1,\n\t    matrix.a2, matrix.b2, matrix.c2,\n\t    matrix.a3, matrix.b3, matrix.c3);\n}\n\ninline glm::vec2 ToVector(const aiVector2D &vec)\n{\n\treturn glm::vec2(vec.x, vec.y);\n}\n\ninline glm::vec3 ToVector(const aiVector3D &vec)\n{\n\treturn glm::vec3(vec.x, vec.y, vec.z);\n}\n\ninline glm::vec3 ToVector(const aiColor3D &color)\n{\n\treturn glm::vec3(color.r, color.g, color.b);\n}\n\ninline glm::vec4 ToVector(const aiColor4D &color)\n{\n\treturn glm::vec4(color.r, color.g, color.b, color.a);\n}\n\ninline glm::quat ToQuaternion(const aiQuaternion &quat)\n{\n\treturn glm::quat(quat.w, quat.x, quat.y, quat.z);\n}\n\nclass AssimpImporter : public Importer<ResourceType::Prefab>\n{\n  public:\n\tstruct BoneInfo\n\t{\n\t\tuint32_t  id;\n\t\tglm::mat4 offset;\n\t};\n\n\tstruct ModelInfo\n\t{\n\t\tstd::map<std::string, BoneInfo> bones;\n\n\t\tstd::vector<std::string> animations;\n\n\t\tNode root;\n\n\t\tstd::map<std::string, std::unordered_set<uint32_t>> skinned_mesh_bones;\n\t};\n\n\tstruct MeshletInfo\n\t{\n\t\tstd::vector<Meshlet>  meshlets;\n\t\tstd::vector<uint32_t> meshletdata;\n\t};\n\n\tvoid ProcessAnimation(ResourceManager *manager, RHIContext *rhi_context, const std::string &path, uint32_t animation_id, const aiScene *assimp_scene, ModelInfo &data)\n\t{\n\t\tstd::vector<Bone> bones;\n\n\t\tstd::string animation_name   = fmt::format(\"{}.animation.{}\", Path::GetInstance().ValidFileName(path), animation_id);\n\t\tconst auto *assimp_animation = assimp_scene->mAnimations[animation_id];\n\n\t\tfor (uint32_t j = 0; j < assimp_animation->mNumChannels; j++)\n\t\t{\n\t\t\tauto        channel   = assimp_animation->mChannels[j];\n\t\t\tstd::string bone_name = channel->mNodeName.data;\n\t\t\tif (data.bones.find(bone_name) == data.bones.end())\n\t\t\t{\n\t\t\t\tdata.bones[bone_name].id = static_cast<uint32_t>(data.bones.size());\n\t\t\t}\n\n\t\t\t// Parsing bone key frame data\n\t\t\tuint32_t bone_id = data.bones[bone_name].id;\n\n\t\t\tstd::vector<Bone::KeyPosition> key_positions;\n\t\t\tstd::vector<Bone::KeyRotation> key_rotations;\n\t\t\tstd::vector<Bone::KeyScale>    key_scales;\n\n\t\t\tfor (uint32_t position_idx = 0; position_idx < channel->mNumPositionKeys; position_idx++)\n\t\t\t{\n\t\t\t\tBone::KeyPosition data = {};\n\n\t\t\t\tdata.position   = ToVector(channel->mPositionKeys[position_idx].mValue);\n\t\t\t\tdata.time_stamp = static_cast<float>(channel->mPositionKeys[position_idx].mTime / assimp_animation->mTicksPerSecond);\n\t\t\t\tkey_positions.push_back(data);\n\t\t\t}\n\n\t\t\tfor (uint32_t rotation_idx = 0; rotation_idx < channel->mNumRotationKeys; rotation_idx++)\n\t\t\t{\n\t\t\t\tBone::KeyRotation data = {};\n\n\t\t\t\tdata.orientation = ToQuaternion(channel->mRotationKeys[rotation_idx].mValue);\n\t\t\t\tdata.time_stamp  = static_cast<float>(channel->mRotationKeys[rotation_idx].mTime / assimp_animation->mTicksPerSecond);\n\t\t\t\tkey_rotations.push_back(data);\n\t\t\t}\n\n\t\t\tfor (uint32_t scale_idx = 0; scale_idx < channel->mNumScalingKeys; scale_idx++)\n\t\t\t{\n\t\t\t\tBone::KeyScale data = {};\n\n\t\t\t\tdata.scale      = ToVector(channel->mScalingKeys[scale_idx].mValue);\n\t\t\t\tdata.time_stamp = static_cast<float>(channel->mScalingKeys[scale_idx].mTime / assimp_animation->mTicksPerSecond);\n\t\t\t\tkey_scales.push_back(data);\n\t\t\t}\n\n\t\t\tbones.emplace_back(bone_name, bone_id, data.bones.at(bone_name).offset, std::move(key_positions), std::move(key_rotations), std::move(key_scales));\n\t\t}\n\n\t\tif (bones.size() < data.bones.size())\n\t\t{\n\t\t\tfor (auto &[name, bone] : data.bones)\n\t\t\t{\n\t\t\t\tbool found = false;\n\t\t\t\tfor (auto &anim_bone : bones)\n\t\t\t\t{\n\t\t\t\t\tif (anim_bone.GetBoneName() == name)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!found)\n\t\t\t\t{\n\t\t\t\t\tbones.emplace_back(name, bone.id, data.bones.at(name).offset, std::vector<Bone::KeyPosition>{}, std::vector<Bone::KeyRotation>{}, std::vector<Bone::KeyScale>{});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstd::function<void(HierarchyNode &, Node &)> build_skeleton =\n\t\t    [&](HierarchyNode &hierarchy, Node &node) {\n\t\t\t    uint32_t skinned_mesh_count = 0;\n\t\t\t    uint32_t animation_count    = 0;\n\n\t\t\t    std::vector<std::pair<ResourceType, std::string>> animations;\n\t\t\t    for (auto &[type, uuid] : node.resources)\n\t\t\t    {\n\t\t\t\t    if (type == ResourceType::SkinnedMesh)\n\t\t\t\t    {\n\t\t\t\t\t    skinned_mesh_count++;\n\t\t\t\t\t    if (skinned_mesh_count > animation_count)\n\t\t\t\t\t    {\n\t\t\t\t\t\t    for (auto &bone : bones)\n\t\t\t\t\t\t    {\n\t\t\t\t\t\t\t    if (data.skinned_mesh_bones[uuid].find(bone.GetBoneID()) != data.skinned_mesh_bones[uuid].end())\n\t\t\t\t\t\t\t    {\n\t\t\t\t\t\t\t\t    animations.push_back(std::make_pair(ResourceType::Animation, animation_name));\n\t\t\t\t\t\t\t\t    animation_count++;\n\t\t\t\t\t\t\t\t    break;\n\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t    }\n\t\t\t\t\t    }\n\t\t\t\t    }\n\t\t\t    }\n\t\t\t    node.resources.insert(node.resources.end(), animations.begin(), animations.end());\n\n\t\t\t    hierarchy.name      = node.name;\n\t\t\t    hierarchy.transform = node.transform;\n\t\t\t    for (auto &child : node.children)\n\t\t\t    {\n\t\t\t\t    HierarchyNode node;\n\t\t\t\t    build_skeleton(node, child);\n\t\t\t\t    hierarchy.children.push_back(node);\n\t\t\t    }\n\t\t    };\n\n\t\tHierarchyNode hierarchy;\n\t\tbuild_skeleton(hierarchy, data.root);\n\n\t\tdata.animations.push_back(animation_name);\n\t\tmanager->Add<ResourceType::Animation>(rhi_context, animation_name, std::move(bones), std::move(hierarchy));\n\t}\n\n\ttemplate <typename T>\n\tMeshletInfo ProcessMeshlet(std::vector<T> &vertices, std::vector<uint32_t> &indices)\n\t{\n\t\tMeshletInfo meshlet_info;\n\n\t\tconst size_t max_vertices  = 64;\n\t\tconst size_t max_triangles = 124;\n\t\tconst float  cone_weight   = 0.5f;\n\n\t\tstd::vector<meshopt_Meshlet> meshlets(meshopt_buildMeshletsBound(indices.size(), max_vertices, max_triangles));\n\n\t\tstd::vector<uint32_t> meshlet_vertices(meshlets.size() * max_vertices);\n\t\tstd::vector<uint8_t>  meshlet_triangles(meshlets.size() * max_triangles * 3);\n\n\t\tmeshlets.resize(meshopt_buildMeshlets(meshlets.data(), meshlet_vertices.data(), meshlet_triangles.data(), indices.data(), indices.size(), &vertices[0].position.x, vertices.size(), sizeof(T), max_vertices, max_triangles, cone_weight));\n\n\t\tstd::unordered_map<size_t, uint32_t> primitive_map;\n\t\tfor (size_t i = 0; i < indices.size() / 3; i++)\n\t\t{\n\t\t\tsize_t hash         = Hash(indices[3 * i], indices[3 * i + 1], indices[3 * i + 2]);\n\t\t\tprimitive_map[hash] = static_cast<uint32_t>(i);\n\t\t}\n\n\t\tfor (auto &meshlet : meshlets)\n\t\t{\n\t\t\tsize_t data_offset = meshlet_info.meshletdata.size();\n\n\t\t\tfor (uint32_t i = 0; i < meshlet.vertex_count; i++)\n\t\t\t{\n\t\t\t\tmeshlet_info.meshletdata.push_back(meshlet_vertices[meshlet.vertex_offset + i]);\n\t\t\t}\n\n\t\t\tconst uint8_t *index_group = &meshlet_triangles[0] + meshlet.triangle_offset;\n\n\t\t\tfor (uint32_t i = 0; i < meshlet.triangle_count; i++)\n\t\t\t{\n\t\t\t\tsize_t hash = Hash(meshlet_vertices[(uint32_t) index_group[3 * i] + meshlet.vertex_offset], meshlet_vertices[(uint32_t) index_group[3 * i + 1] + meshlet.vertex_offset], meshlet_vertices[(uint32_t) index_group[3 * i + 2] + meshlet.vertex_offset]);\n\t\t\t\tmeshlet_info.meshletdata.push_back(primitive_map.at(hash));\n\t\t\t}\n\n\t\t\tfor (uint32_t i = 0; i < meshlet.triangle_count; i++)\n\t\t\t{\n\t\t\t\tuint32_t triangle = 0;\n\t\t\t\ttriangle += (uint32_t) index_group[3 * i];\n\t\t\t\ttriangle += (uint32_t) index_group[3 * i + 1] << 8;\n\t\t\t\ttriangle += (uint32_t) index_group[3 * i + 2] << 16;\n\t\t\t\tmeshlet_info.meshletdata.push_back(triangle);\n\t\t\t}\n\n\t\t\tmeshopt_Bounds bounds = meshopt_computeMeshletBounds(&meshlet_vertices[meshlet.vertex_offset], &meshlet_triangles[meshlet.triangle_offset], meshlet.triangle_count, &vertices[0].position.x, vertices.size(), sizeof(T));\n\n\t\t\tMeshlet tmp_meshlet = {};\n\n\t\t\ttmp_meshlet.data_offset    = uint32_t(data_offset);\n\t\t\ttmp_meshlet.triangle_count = meshlet.triangle_count;\n\t\t\ttmp_meshlet.vertex_count   = meshlet.vertex_count;\n\t\t\ttmp_meshlet.vertex_offset  = meshlet.vertex_offset;\n\t\t\ttmp_meshlet.center         = glm::vec3(bounds.center[0], bounds.center[1], bounds.center[2]);\n\t\t\ttmp_meshlet.radius         = bounds.radius;\n\t\t\ttmp_meshlet.cone_cutoff    = bounds.cone_cutoff;\n\n\t\t\tstd::memcpy(&tmp_meshlet.cone_axis, bounds.cone_axis, sizeof(glm::vec3));\n\t\t\tstd::memcpy(&tmp_meshlet.cone_apex, bounds.cone_apex, sizeof(glm::vec3));\n\n\t\t\tmeshlet_info.meshlets.push_back(tmp_meshlet);\n\t\t}\n\n\t\treturn meshlet_info;\n\t}\n\n\tvoid ProcessMesh(ResourceManager *manager, RHIContext *rhi_context, const std::string &path, uint32_t mesh_id, const aiScene *assimp_scene, ModelInfo &data)\n\t{\n\t\tstd::string mesh_name   = fmt::format(\"{}.mesh.{}\", Path::GetInstance().ValidFileName(path), mesh_id);\n\t\taiMesh     *assimp_mesh = assimp_scene->mMeshes[mesh_id];\n\n\t\tif (manager->Has<ResourceType::Mesh>(mesh_name))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::vector<Vertex>   vertices;\n\t\tstd::vector<uint32_t> indices;\n\n\t\t// Parsing vertices\n\t\tfor (uint32_t j = 0; j < assimp_mesh->mNumVertices; j++)\n\t\t{\n\t\t\tVertex vertex    = {};\n\t\t\tvertex.position  = glm::vec3(assimp_mesh->mVertices[j].x, assimp_mesh->mVertices[j].y, assimp_mesh->mVertices[j].z);\n\t\t\tvertex.normal    = assimp_mesh->mNormals ? glm::vec3(assimp_mesh->mNormals[j].x, assimp_mesh->mNormals[j].y, assimp_mesh->mNormals[j].z) : glm::vec3(0.f);\n\t\t\tvertex.tangent   = assimp_mesh->mTangents ? glm::vec3(assimp_mesh->mTangents[j].x, assimp_mesh->mTangents[j].y, assimp_mesh->mTangents[j].z) : glm::vec3(0.f);\n\t\t\tvertex.texcoord0 = assimp_mesh->mTextureCoords[0] ? glm::vec2(assimp_mesh->mTextureCoords[0][j].x, assimp_mesh->mTextureCoords[0][j].y) : glm::vec2(0.f);\n\t\t\tvertex.texcoord1 = assimp_mesh->mTextureCoords[1] ? glm::vec2(assimp_mesh->mTextureCoords[1][j].x, assimp_mesh->mTextureCoords[1][j].y) : glm::vec2(0.f);\n\t\t\tvertices.emplace_back(std::move(vertex));\n\t\t}\n\n\t\t// Parsing indices\n\t\tfor (uint32_t j = 0; j < assimp_mesh->mNumFaces; j++)\n\t\t{\n\t\t\tfor (uint32_t k = 0; k < 3; k++)\n\t\t\t{\n\t\t\t\tindices.push_back(assimp_mesh->mFaces[j].mIndices[k]);\n\t\t\t}\n\t\t}\n\n\t\tMeshletInfo meshlet_info = ProcessMeshlet(vertices, indices);\n\t\tmanager->Add<ResourceType::Mesh>(rhi_context, mesh_name, std::move(vertices), std::move(indices), std::move(meshlet_info.meshlets), std::move(meshlet_info.meshletdata));\n\t}\n\n\tvoid ProcessSkinnedMesh(ResourceManager *manager, RHIContext *rhi_context, const std::string &path, uint32_t mesh_id, const aiScene *assimp_scene, ModelInfo &data)\n\t{\n\t\tstd::string mesh_name   = fmt::format(\"{}.mesh.{}\", Path::GetInstance().ValidFileName(path), mesh_id);\n\t\taiMesh     *assimp_mesh = assimp_scene->mMeshes[mesh_id];\n\n\t\tif (manager->Has<ResourceType::SkinnedMesh>(mesh_name))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::vector<SkinnedVertex>   vertices;\n\t\tstd::vector<uint32_t>        indices;\n\t\tstd::unordered_set<uint32_t> bones;\n\n\t\t// Parsing vertices\n\t\tfor (uint32_t j = 0; j < assimp_mesh->mNumVertices; j++)\n\t\t{\n\t\t\tSkinnedVertex vertex = {};\n\t\t\tvertex.position      = glm::vec3(assimp_mesh->mVertices[j].x, assimp_mesh->mVertices[j].y, assimp_mesh->mVertices[j].z);\n\t\t\tvertex.normal        = glm::vec3(assimp_mesh->mNormals[j].x, assimp_mesh->mNormals[j].y, assimp_mesh->mNormals[j].z);\n\t\t\tvertex.tangent       = assimp_mesh->mTangents ? glm::vec3(assimp_mesh->mTangents[j].x, assimp_mesh->mTangents[j].y, assimp_mesh->mTangents[j].z) : glm::vec3(0.f);\n\t\t\tvertex.texcoord0     = assimp_mesh->mTextureCoords[0] ? glm::vec2(assimp_mesh->mTextureCoords[0][j].x, assimp_mesh->mTextureCoords[0][j].y) : glm::vec2(0.f);\n\t\t\tvertex.texcoord1     = assimp_mesh->mTextureCoords[1] ? glm::vec2(assimp_mesh->mTextureCoords[1][j].x, assimp_mesh->mTextureCoords[1][j].y) : glm::vec2(0.f);\n\t\t\tvertices.emplace_back(std::move(vertex));\n\t\t}\n\n\t\t// Parsing indices\n\t\tfor (uint32_t j = 0; j < assimp_mesh->mNumFaces; j++)\n\t\t{\n\t\t\tfor (uint32_t k = 0; k < 3; k++)\n\t\t\t{\n\t\t\t\tindices.push_back(assimp_mesh->mFaces[j].mIndices[k]);\n\t\t\t}\n\t\t}\n\n\t\t// Parsing bones\n\t\tfor (uint32_t bone_index = 0; bone_index < assimp_mesh->mNumBones; bone_index++)\n\t\t{\n\t\t\tint32_t     bone_id   = -1;\n\t\t\tstd::string bone_name = assimp_mesh->mBones[bone_index]->mName.C_Str();\n\n\t\t\tif (data.bones.find(bone_name) == data.bones.end())\n\t\t\t{\n\t\t\t\tBoneInfo bone = {};\n\t\t\t\tbone.id       = static_cast<uint32_t>(data.bones.size());\n\t\t\t\tbone.offset   = ToMatrix(assimp_mesh->mBones[bone_index]->mOffsetMatrix);\n\n\t\t\t\tdata.bones[bone_name] = bone;\n\n\t\t\t\tbone_id = bone.id;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbone_id = data.bones.at(bone_name).id;\n\t\t\t}\n\n\t\t\tbones.insert(bone_id);\n\n\t\t\tdata.bones[bone_name] = data.bones.at(bone_name);\n\n\t\t\tauto     weights    = assimp_mesh->mBones[bone_index]->mWeights;\n\t\t\tuint32_t weight_num = assimp_mesh->mBones[bone_index]->mNumWeights;\n\n\t\t\tfor (uint32_t weight_index = 0; weight_index < weight_num; weight_index++)\n\t\t\t{\n\t\t\t\tint32_t vertex_id = weights[weight_index].mVertexId;\n\t\t\t\tfloat   weight    = weights[weight_index].mWeight;\n\n\t\t\t\tfor (int i = 0; i < MAX_BONE_INFLUENCE; ++i)\n\t\t\t\t{\n\t\t\t\t\tif (vertices[vertex_id].bones[i] < 0 && weight > 0.f)\n\t\t\t\t\t{\n\t\t\t\t\t\tvertices[vertex_id].weights[i] = weight;\n\t\t\t\t\t\tvertices[vertex_id].bones[i]   = bone_id;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tMeshletInfo meshlet_info = ProcessMeshlet(vertices, indices);\n\n\t\tdata.skinned_mesh_bones[mesh_name] = bones;\n\n\t\tmanager->Add<ResourceType::SkinnedMesh>(rhi_context, mesh_name, std::move(vertices), std::move(indices), std::move(meshlet_info.meshlets), std::move(meshlet_info.meshletdata));\n\t}\n\n\tNode ProcessNode(ResourceManager *manager, RHIContext *rhi_context, const std::string &path, const aiScene *assimp_scene, aiNode *assimp_node, ModelInfo &data, aiMatrix4x4 transform = aiMatrix4x4())\n\t{\n\t\tNode node = {};\n\n\t\tnode.transform = ToMatrix(assimp_node->mTransformation);\n\t\tnode.name      = assimp_node->mName.C_Str();\n\n\t\tfor (uint32_t i = 0; i < assimp_node->mNumMeshes; i++)\n\t\t{\n\t\t\taiMesh     *assimp_mesh   = assimp_scene->mMeshes[assimp_node->mMeshes[i]];\n\t\t\tstd::string mesh_name     = fmt::format(\"{}.mesh.{}\", Path::GetInstance().ValidFileName(path), assimp_node->mMeshes[i]);\n\t\t\tstd::string material_name = fmt::format(\"{}.material.{}\", Path::GetInstance().ValidFileName(path), assimp_mesh->mMaterialIndex);\n\n\t\t\tif (assimp_mesh->HasBones())\n\t\t\t{\n\t\t\t\tnode.resources.emplace_back(std::make_pair(ResourceType::SkinnedMesh, mesh_name));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnode.resources.emplace_back(std::make_pair(ResourceType::Mesh, mesh_name));\n\t\t\t}\n\n\t\t\tnode.resources.emplace_back(std::make_pair(ResourceType::Material, material_name));\n\t\t}\n\n\t\tfor (uint32_t i = 0; i < assimp_node->mNumChildren; i++)\n\t\t{\n\t\t\tNode child = ProcessNode(manager, rhi_context, path, assimp_scene, assimp_node->mChildren[i], data, transform);\n\t\t\tnode.children.emplace_back(std::move(child));\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tvoid ProcessMaterial(ResourceManager *manager, RHIContext *rhi_context, const std::string &path, uint32_t material_id, const aiScene *assimp_scene)\n\t{\n\t\tstd::string material_name = fmt::format(\"{}.material.{}\", Path::GetInstance().ValidFileName(path), material_id);\n\n\t\tif (manager->Has<ResourceType::Material>(material_name))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\taiMaterial *assimp_material = assimp_scene->mMaterials[material_id];\n\n\t\tMaterialGraphDesc desc;\n\t\tdesc.SetName(material_name);\n\n\t\tstruct ImageConfig\n\t\t{\n\t\t\tSamplerDesc sampler;\n\t\t\tchar        filename[200];\n\t\t};\n\n\t\tauto create_material_node = [](size_t &handle, const std::string &category, const std::string &name) {\n\t\t\tMaterialNodeDesc desc;\n\t\t\tPluginManager::GetInstance().Call(fmt::format(\"shared/Material/Material.{}.{}.dll\", category, name), \"Create\", &desc, &handle);\n\t\t\treturn desc;\n\t\t};\n\n\t\tsize_t current_handle = 0;\n\n\t\tMaterialNodeDesc &principled_bsdf_node     = desc.AddNode(current_handle++, create_material_node(current_handle, \"BSDF\", \"DisneyMaterial\"));\n\t\tMaterialNodeDesc &output_node              = desc.AddNode(current_handle++, create_material_node(current_handle, \"Output\", \"MaterialOutput\"));\n\t\tMaterialNodeDesc *surface_interaction_node = nullptr;\n\n\t\tauto set_image_texture = [&](MaterialNodeDesc &texture_node, const std::string &name) {\n\t\t\tif (!surface_interaction_node)\n\t\t\t{\n\t\t\t\tsurface_interaction_node = &desc.AddNode(current_handle++, create_material_node(current_handle, \"Input\", \"SurfaceInteraction\"));\n\t\t\t}\n\t\t\tVariant      variant  = texture_node.GetVariant();\n\t\t\tstd::string  filename = Path::GetInstance().ValidFileName(name);\n\t\t\tImageConfig *config   = variant.Convert<ImageConfig>();\n\t\t\tstd::memset(config->filename, '\\0', 200);\n\t\t\tstd::memcpy(config->filename, filename.data(), filename.length());\n\t\t\tdesc.Link(surface_interaction_node->GetPin(\"UV\").handle, texture_node.GetPin(\"UV\").handle);\n\t\t\tdesc.Link(surface_interaction_node->GetPin(\"dUVdx\").handle, texture_node.GetPin(\"dUVdx\").handle);\n\t\t\tdesc.Link(surface_interaction_node->GetPin(\"dUVdy\").handle, texture_node.GetPin(\"dUVdy\").handle);\n\t\t};\n\n\t\tdesc.Link(principled_bsdf_node.GetPin(\"Out\").handle, output_node.GetPin(\"Surface\").handle);\n\n\t\t// Base Color\n\t\t{\n\t\t\tglm::vec3 base_color = glm::vec3(0.f);\n\t\t\taiString  color_texture;\n\n\t\t\tassimp_material->Get(AI_MATKEY_BASE_COLOR, base_color.x);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &color_texture);\n\n\t\t\tstd::string color_texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, color_texture.C_Str());\n\t\t\tif (!color_texture_name.empty())\n\t\t\t{\n\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\tset_image_texture(texture_node, color_texture_name);\n\n\t\t\t\tif (base_color != glm::vec3(1.f))\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &multiply_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"VectorCalculate\"));\n\t\t\t\t\tmultiply_node.GetPin(\"X\").variant = base_color;\n\t\t\t\t\tmultiply_node.SetVariant(7);\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, multiply_node.GetPin(\"Y\").handle);\n\n\t\t\t\t\tMaterialNodeDesc &srgb2linear_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"SRGBToLinear\"));\n\t\t\t\t\tdesc.Link(multiply_node.GetPin(\"Out\").handle, srgb2linear_node.GetPin(\"In\").handle);\n\t\t\t\t\tdesc.Link(srgb2linear_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"BaseColor\").handle);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &srgb2linear_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"SRGBToLinear\"));\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, srgb2linear_node.GetPin(\"In\").handle);\n\t\t\t\t\tdesc.Link(srgb2linear_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"BaseColor\").handle);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tprincipled_bsdf_node.GetPin(\"BaseColor\").variant = base_color;\n\t\t\t}\n\t\t}\n\n\t\t// Metallic & Roughness & Occlusion\n\t\t{\n\t\t\tfloat    metallic  = 0.f;\n\t\t\tfloat    roughness = 0.f;\n\t\t\taiString metallic_texture;\n\t\t\taiString roughness_texture;\n\t\t\taiString occlusion_texture;\n\n\t\t\tassimp_material->Get(AI_MATKEY_METALLIC_FACTOR, metallic);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_METALLIC_TEXTURE, &metallic_texture);\n\t\t\tassimp_material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_ROUGHNESS_TEXTURE, &roughness_texture);\n\t\t\tassimp_material->GetTexture(aiTextureType_LIGHTMAP, 0, &occlusion_texture);\n\n\t\t\tbool pack_metallic_roughness = (metallic_texture == roughness_texture);\n\t\t\tbool pack_occlusion          = (occlusion_texture.length == 0 || metallic_texture == occlusion_texture);\n\n\t\t\tif (pack_metallic_roughness)\n\t\t\t{\n\t\t\t\t// Pack Texture: Occlusion (R) [optional] + Roughness G + Metallic B\n\t\t\t\tstd::string texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, metallic_texture.C_Str());\n\t\t\t\tif (!texture_name.empty())\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\t\tset_image_texture(texture_node, texture_name);\n\n\t\t\t\t\tMaterialNodeDesc &split_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"VectorSplit\"));\n\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, split_node.GetPin(\"In\").handle);\n\n\t\t\t\t\tif (metallic == 1.f && roughness == 1.f)\n\t\t\t\t\t{\n\t\t\t\t\t\t// TODO : AO Map\n\t\t\t\t\t\tdesc.Link(split_node.GetPin(\"Y\").handle, principled_bsdf_node.GetPin(\"Roughness\").handle);\n\t\t\t\t\t\tdesc.Link(split_node.GetPin(\"Z\").handle, principled_bsdf_node.GetPin(\"Metallic\").handle);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tMaterialNodeDesc &metallic_scale_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"Calculate\"));\n\t\t\t\t\t\tmetallic_scale_node.GetPin(\"X\").variant = metallic;\n\t\t\t\t\t\tmetallic_scale_node.SetVariant(2);\n\n\t\t\t\t\t\tMaterialNodeDesc &roughness_scale_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"Calculate\"));\n\t\t\t\t\t\troughness_scale_node.GetPin(\"X\").variant = roughness;\n\t\t\t\t\t\troughness_scale_node.SetVariant(2);\n\n\t\t\t\t\t\tdesc.Link(split_node.GetPin(\"Y\").handle, roughness_scale_node.GetPin(\"Y\").handle);\n\t\t\t\t\t\tdesc.Link(roughness_scale_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"Roughness\").handle);\n\n\t\t\t\t\t\tdesc.Link(split_node.GetPin(\"Z\").handle, metallic_scale_node.GetPin(\"Y\").handle);\n\t\t\t\t\t\tdesc.Link(metallic_scale_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"Metallic\").handle);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tprincipled_bsdf_node.GetPin(\"Metallic\").variant = metallic;\n\t\t\t\t\tprincipled_bsdf_node.GetPin(\"Roughness\").variant = roughness;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Separated Texture\n\t\t\t\t// Metallic\n\t\t\t\tstd::string metallic_texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, metallic_texture.C_Str());\n\t\t\t\tif (!metallic_texture_name.empty())\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\t\tset_image_texture(texture_node, metallic_texture_name);\n\n\t\t\t\t\tif (metallic == 1.f)\n\t\t\t\t\t{\n\t\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, principled_bsdf_node.GetPin(\"Metallic\").handle);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tMaterialNodeDesc &scale_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"Calculate\"));\n\t\t\t\t\t\tscale_node.GetPin(\"X\").variant = metallic;\n\t\t\t\t\t\tscale_node.SetVariant(2);\n\t\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, scale_node.GetPin(\"Y\").handle);\n\t\t\t\t\t\tdesc.Link(scale_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"Metallic\").handle);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tprincipled_bsdf_node.GetPin(\"Metallic\").variant = metallic;\n\t\t\t\t}\n\n\t\t\t\t// Roughness\n\t\t\t\tstd::string roughness_texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, roughness_texture.C_Str());\n\t\t\t\tif (!roughness_texture_name.empty())\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\t\tset_image_texture(texture_node, roughness_texture_name);\n\n\t\t\t\t\tif (roughness == 1.f)\n\t\t\t\t\t{\n\t\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, principled_bsdf_node.GetPin(\"Roughness\").handle);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tMaterialNodeDesc &scale_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"Calculate\"));\n\t\t\t\t\t\tscale_node.GetPin(\"X\").variant = roughness;\n\t\t\t\t\t\tscale_node.SetVariant(2);\n\t\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, scale_node.GetPin(\"Y\").handle);\n\t\t\t\t\t\tdesc.Link(scale_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"Roughness\").handle);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tprincipled_bsdf_node.GetPin(\"Roughness\").variant = roughness;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!pack_occlusion)\n\t\t\t{\n\t\t\t\t// TODO: AO Map\n\t\t\t}\n\t\t}\n\n\t\t// Normal\n\t\t{\n\t\t\taiString normal_texture;\n\t\t\tassimp_material->GetTexture(aiTextureType_NORMALS, 0, &normal_texture);\n\n\t\t\tstd::string normal_texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, normal_texture.C_Str());\n\t\t\tif (!normal_texture_name.empty())\n\t\t\t{\n\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\tset_image_texture(texture_node, normal_texture_name);\n\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, principled_bsdf_node.GetPin(\"Normal\").handle);\n\t\t\t}\n\t\t}\n\n\t\t// Emissive\n\t\t{\n\t\t\tglm::vec3 emissive_color = glm::vec3(0.f);\n\t\t\taiString  emissive_texture;\n\n\t\t\tassimp_material->Get(AI_MATKEY_COLOR_EMISSIVE, emissive_color.x);\n\t\t\tassimp_material->GetTexture(aiTextureType_EMISSIVE, 0, &emissive_texture);\n\n\t\t\tstd::string emissive_texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, emissive_texture.C_Str());\n\t\t\tif (!emissive_texture_name.empty())\n\t\t\t{\n\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\tset_image_texture(texture_node, emissive_texture_name);\n\n\t\t\t\tif (emissive_color == glm::vec3(1.f))\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &srgb2linear_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"SRGBToLinear\"));\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, srgb2linear_node.GetPin(\"In\").handle);\n\t\t\t\t\tdesc.Link(srgb2linear_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"Emissive\").handle);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &multiply_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"VectorCalculate\"));\n\t\t\t\t\tmultiply_node.GetPin(\"X\").variant = emissive_color;\n\t\t\t\t\tmultiply_node.SetVariant(7);\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, multiply_node.GetPin(\"Y\").handle);\n\n\t\t\t\t\tMaterialNodeDesc &srgb2linear_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"SRGBToLinear\"));\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, srgb2linear_node.GetPin(\"In\").handle);\n\t\t\t\t\tdesc.Link(srgb2linear_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"Emissive\").handle);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tprincipled_bsdf_node.GetPin(\"Emissive\").variant = emissive_color;\n\t\t\t}\n\t\t}\n\n\t\t// Anisotropic\n\t\t{\n\t\t\tfloat anisotropic = 0.f;\n\t\t\tassimp_material->Get(AI_MATKEY_ANISOTROPY_FACTOR, anisotropic);\n\t\t\tprincipled_bsdf_node.GetPin(\"Anisotropic\").variant = anisotropic;\n\t\t}\n\n\t\t// Sheen\n\t\t{\n\t\t\tglm::vec3 sheen_color     = glm::vec3(0.f);\n\t\t\tfloat     sheen_roughness = 0.f;\n\t\t\taiString  sheen_color_texture;\n\t\t\taiString  sheen_roughness_texture;\n\t\t\tassimp_material->Get(AI_MATKEY_SHEEN_COLOR_FACTOR, sheen_color.x);\n\t\t\tassimp_material->Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen_roughness);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_SHEEN_COLOR_TEXTURE, &sheen_color_texture);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE, &sheen_roughness_texture);\n\t\t\tProcessTexture(manager, rhi_context, path, assimp_scene, sheen_color_texture.C_Str());\n\t\t\tProcessTexture(manager, rhi_context, path, assimp_scene, sheen_roughness_texture.C_Str());\n\t\t}\n\n\t\t// Clearcoat\n\t\t{\n\t\t\tfloat    clearcoat_factor    = 0.f;\n\t\t\tfloat    clearcoat_roughness = 0.f;\n\t\t\taiString clearcoat_texture;\n\t\t\taiString clearcoat_roughness_texture;\n\t\t\taiString clearcoat_normal_texture;\n\n\t\t\tassimp_material->Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat_factor);\n\t\t\tassimp_material->Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat_roughness);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_SHEEN_COLOR_TEXTURE, &clearcoat_texture);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_SHEEN_COLOR_TEXTURE, &clearcoat_roughness_texture);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_SHEEN_COLOR_TEXTURE, &clearcoat_normal_texture);\n\t\t\tProcessTexture(manager, rhi_context, path, assimp_scene, clearcoat_texture.C_Str());\n\t\t\tProcessTexture(manager, rhi_context, path, assimp_scene, clearcoat_roughness_texture.C_Str());\n\t\t\tProcessTexture(manager, rhi_context, path, assimp_scene, clearcoat_normal_texture.C_Str());\n\t\t}\n\n\t\t// Transmission\n\t\t{\n\t\t\tfloat    transmission_factor = 0.f;\n\t\t\taiString transmission_texture;\n\t\t\tassimp_material->Get(AI_MATKEY_TRANSMISSION_FACTOR, transmission_factor);\n\t\t\tassimp_material->GetTexture(AI_MATKEY_TRANSMISSION_TEXTURE, &transmission_texture);\n\n\t\t\tstd::string transmission_texture_name = ProcessTexture(manager, rhi_context, path, assimp_scene, transmission_texture.C_Str());\n\t\t\tif (!transmission_texture_name.empty())\n\t\t\t{\n\t\t\t\tMaterialNodeDesc &texture_node = desc.AddNode(current_handle++, create_material_node(current_handle, \"Texture\", \"ImageTexture\"));\n\t\t\t\tset_image_texture(texture_node, transmission_texture_name);\n\n\t\t\t\tif (transmission_factor == 1.f)\n\t\t\t\t{\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, principled_bsdf_node.GetPin(\"SpecTrans\").handle);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tMaterialNodeDesc &scale_node   = desc.AddNode(current_handle++, create_material_node(current_handle, \"Converter\", \"Calculate\"));\n\t\t\t\t\tscale_node.GetPin(\"X\").variant = transmission_factor;\n\t\t\t\t\tscale_node.SetVariant(2);\n\t\t\t\t\tdesc.Link(texture_node.GetPin(\"Color\").handle, scale_node.GetPin(\"Y\").handle);\n\t\t\t\t\tdesc.Link(scale_node.GetPin(\"Out\").handle, principled_bsdf_node.GetPin(\"SpecTrans\").handle);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tprincipled_bsdf_node.GetPin(\"SpecTrans\").variant = transmission_factor;\n\t\t\t}\n\t\t}\n\n\t\t// Volume\n\t\t{\n\t\t    // TODO\n\t\t}\n\n\t\t// Displacement\n\t\t{\n\t\t\taiString displacement_texture;\n\t\t\tassimp_material->GetTexture(aiTextureType_DISPLACEMENT, 0, &displacement_texture);\n\t\t\tProcessTexture(manager, rhi_context, path, assimp_scene, displacement_texture.C_Str());\n\t\t}\n\n\t\tmanager->Add<ResourceType::Material>(rhi_context, material_name, std::move(desc));\n\t}\n\n\tstd::string ProcessTexture(ResourceManager *manager, RHIContext *rhi_context, const std::string &path, const aiScene *assimp_scene, const std::string &filename)\n\t{\n\t\tauto [assimp_texture, texture_id] = assimp_scene->GetEmbeddedTextureAndIndex(filename.c_str());\n\t\tif (texture_id < 0 && filename.empty())\n\t\t{\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (texture_id < 0)\n\t\t{\n\t\t\t// External texture\n\t\t\tauto &importer = Importer<ResourceType::Texture2D>::GetInstance(\"STB\");\n\t\t\tif (importer)\n\t\t\t{\n\t\t\t\tstd::string file_path = Path::GetInstance().GetFileDirectory(path) + filename;\n\t\t\t\timporter->Import(manager, file_path, rhi_context);\n\t\t\t\treturn Path::GetInstance().ValidFileName(file_path);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string texture_name = fmt::format(\"{}.texture.{}\", Path::GetInstance().ValidFileName(path), texture_id);\n\t\t\tif (manager->Has<ResourceType::Texture2D>(texture_name))\n\t\t\t{\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\tTextureDesc desc = {};\n\t\t\tdesc.name        = texture_name;\n\t\t\tdesc.width       = 1;\n\t\t\tdesc.height      = 1;\n\t\t\tdesc.depth       = 1;\n\t\t\tdesc.mips        = 1;\n\t\t\tdesc.layers      = 1;\n\t\t\tdesc.samples     = 1;\n\n\t\t\tvoid   *raw_data = nullptr;\n\t\t\tsize_t  size     = 0;\n\t\t\tint32_t width = 0, height = 0, channel = 0;\n\n\t\t\tconst int32_t req_channel = 4;\n\n\t\t\tstbi_uc *assimp_texture_data     = reinterpret_cast<stbi_uc *>(assimp_texture->pcData);\n\t\t\tint32_t  assimp_texture_data_len = static_cast<int32_t>(assimp_texture->mWidth * glm::max(1u, assimp_texture->mHeight) * 4);\n\n\t\t\tif (stbi_is_hdr_from_memory(assimp_texture_data, assimp_texture_data_len))\n\t\t\t{\n\t\t\t\traw_data    = stbi_loadf_from_memory(assimp_texture_data, assimp_texture_data_len, &width, &height, &channel, req_channel);\n\t\t\t\tsize        = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(req_channel) * sizeof(float);\n\t\t\t\tdesc.format = RHIFormat::R32G32B32A32_FLOAT;\n\t\t\t}\n\t\t\telse if (stbi_is_16_bit_from_memory(assimp_texture_data, assimp_texture_data_len))\n\t\t\t{\n\t\t\t\traw_data    = stbi_load_16_from_memory(assimp_texture_data, assimp_texture_data_len, &width, &height, &channel, req_channel);\n\t\t\t\tsize        = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(req_channel) * sizeof(uint16_t);\n\t\t\t\tdesc.format = RHIFormat::R16G16B16A16_FLOAT;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\traw_data    = stbi_load_from_memory(assimp_texture_data, assimp_texture_data_len, &width, &height, &channel, req_channel);\n\t\t\t\tsize        = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(req_channel) * sizeof(uint8_t);\n\t\t\t\tdesc.format = RHIFormat::R8G8B8A8_UNORM;\n\t\t\t}\n\n\t\t\tdesc.width  = static_cast<uint32_t>(width);\n\t\t\tdesc.height = static_cast<uint32_t>(height);\n\t\t\tdesc.mips   = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height))) + 1);\n\t\t\tdesc.usage  = RHITextureUsage::ShaderResource | RHITextureUsage::Transfer;\n\n\t\t\tstd::vector<uint8_t> data;\n\n\t\t\tdata.resize(size);\n\t\t\tstd::memcpy(data.data(), raw_data, size);\n\n\t\t\tstbi_image_free(raw_data);\n\n\t\t\tmanager->Add<ResourceType::Texture2D>(rhi_context, std::move(data), desc);\n\n\t\t\treturn desc.name;\n\t\t}\n\n\t\treturn \"\";\n\t}\n\n  protected:\n\tvirtual void Import_(ResourceManager *manager, const std::string &path, RHIContext *rhi_context) override\n\t{\n\t\tstd::string prefab_name = Path::GetInstance().ValidFileName(path);\n\n\t\tAssimp::Importer importer;\n\n\t\tif (const aiScene *assimp_scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace))\n\t\t{\n\t\t\tModelInfo data;\n\n\t\t\tfor (uint32_t i = 0; i < assimp_scene->mNumMeshes; i++)\n\t\t\t{\n\t\t\t\taiMesh *assimp_mesh = assimp_scene->mMeshes[i];\n\t\t\t\tif (assimp_mesh->HasBones())\n\t\t\t\t{\n\t\t\t\t\tProcessSkinnedMesh(manager, rhi_context, path, i, assimp_scene, data);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tProcessMesh(manager, rhi_context, path, i, assimp_scene, data);\n\t\t\t\t}\n\n\t\t\t\tProcessMaterial(manager, rhi_context, path, assimp_mesh->mMaterialIndex, assimp_scene);\n\t\t\t}\n\n\t\t\taiMatrix4x4 identity;\n\t\t\tdata.root = ProcessNode(manager, rhi_context, path, assimp_scene, assimp_scene->mRootNode, data, identity);\n\n\t\t\tfor (uint32_t i = 0; i < assimp_scene->mNumAnimations; i++)\n\t\t\t{\n\t\t\t\tProcessAnimation(manager, rhi_context, path, i, assimp_scene, data);\n\t\t\t}\n\n\t\t\tif (!manager->Has<ResourceType::Prefab>(prefab_name))\n\t\t\t{\n\t\t\t\tmanager->Add<ResourceType::Prefab>(rhi_context, prefab_name, std::move(data.root));\n\t\t\t}\n\t\t}\n\t}\n};\n\nextern \"C\"\n{\n\tEXPORT_API AssimpImporter *Create()\n\t{\n\t\treturn new AssimpImporter;\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Importer/DDS.cpp",
    "content": "#include <RHI/RHITexture.hpp>\n#include <Resource/Importer.hpp>\n#include <Resource/Resource/Texture2D.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <dxgiformat.h>\n\nusing namespace Ilum;\n\n// reference: https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/MiniEngine/Core/dds.h\nconst uint32_t DDS_MAGIC = 0x20534444;        // \"DDS \"\n\ninline static std::unordered_map<DXGI_FORMAT, RHIFormat> FormatMap = {\n    {DXGI_FORMAT_UNKNOWN, RHIFormat::Undefined},\n    {DXGI_FORMAT_R8G8B8A8_UNORM, RHIFormat::R8G8B8A8_UNORM},\n    {DXGI_FORMAT_R16_UINT, RHIFormat::R16_UINT},\n    {DXGI_FORMAT_R16_SINT, RHIFormat::R16_SINT},\n    {DXGI_FORMAT_R16_FLOAT, RHIFormat::R16_FLOAT},\n    {DXGI_FORMAT_R16G16_UINT, RHIFormat::R16G16_UINT},\n    {DXGI_FORMAT_R16G16_SINT, RHIFormat::R16G16_SINT},\n    {DXGI_FORMAT_R16G16_FLOAT, RHIFormat::R16G16_FLOAT},\n    {DXGI_FORMAT_R16G16B16A16_UINT, RHIFormat::R16G16B16A16_UINT},\n    {DXGI_FORMAT_R16G16B16A16_SINT, RHIFormat::R16G16B16A16_SINT},\n    {DXGI_FORMAT_R16G16B16A16_FLOAT, RHIFormat::R16G16B16A16_FLOAT},\n    {DXGI_FORMAT_R10G10B10A2_UNORM, RHIFormat::R10G10B10A2_UNORM},\n    {DXGI_FORMAT_R10G10B10A2_UINT, RHIFormat::R10G10B10A2_UINT},\n    {DXGI_FORMAT_R11G11B10_FLOAT, RHIFormat::R11G11B10_FLOAT},\n    {DXGI_FORMAT_R32_UINT, RHIFormat::R32_UINT},\n    {DXGI_FORMAT_R32_SINT, RHIFormat::R32_SINT},\n    {DXGI_FORMAT_R32_FLOAT, RHIFormat::R32_FLOAT},\n    {DXGI_FORMAT_R32G32_UINT, RHIFormat::R32G32_UINT},\n    {DXGI_FORMAT_R32G32_SINT, RHIFormat::R32G32_SINT},\n    {DXGI_FORMAT_R32G32_FLOAT, RHIFormat::R32G32_FLOAT},\n    {DXGI_FORMAT_R32G32B32_UINT, RHIFormat::R32G32B32_UINT},\n    {DXGI_FORMAT_R32G32B32_SINT, RHIFormat::R32G32B32_SINT},\n    {DXGI_FORMAT_R32G32B32_FLOAT, RHIFormat::R32G32B32_FLOAT},\n    {DXGI_FORMAT_R32G32B32A32_UINT, RHIFormat::R32G32B32A32_UINT},\n    {DXGI_FORMAT_R32G32B32A32_SINT, RHIFormat::R32G32B32A32_SINT},\n    {DXGI_FORMAT_R32G32B32A32_FLOAT, RHIFormat::R32G32B32A32_FLOAT},\n    {DXGI_FORMAT_D32_FLOAT, RHIFormat::D32_FLOAT},\n    {DXGI_FORMAT_D24_UNORM_S8_UINT, RHIFormat::D24_UNORM_S8_UINT},\n};\n\nstruct DDS_PIXELFORMAT\n{\n\tuint32_t size;\n\tuint32_t flags;\n\tuint32_t fourCC;\n\tuint32_t RGBBitCount;\n\tuint32_t RBitMask;\n\tuint32_t GBitMask;\n\tuint32_t BBitMask;\n\tuint32_t ABitMask;\n};\n\n#define DDS_FOURCC 0x00000004            // DDPF_FOURCC\n#define DDS_RGB 0x00000040               // DDPF_RGB\n#define DDS_RGBA 0x00000041              // DDPF_RGB | DDPF_ALPHAPIXELS\n#define DDS_LUMINANCE 0x00020000         // DDPF_LUMINANCE\n#define DDS_LUMINANCEA 0x00020001        // DDPF_LUMINANCE | DDPF_ALPHAPIXELS\n#define DDS_ALPHA 0x00000002             // DDPF_ALPHA\n#define DDS_PAL8 0x00000020              // DDPF_PALETTEINDEXED8\n\n#ifndef MAKEFOURCC\n#\tdefine MAKEFOURCC(ch0, ch1, ch2, ch3)                                \\\n\t\t((uint32_t) (uint8_t) (ch0) | ((uint32_t) (uint8_t) (ch1) << 8) | \\\n\t\t ((uint32_t) (uint8_t) (ch2) << 16) | ((uint32_t) (uint8_t) (ch3) << 24))\n#endif /* defined(MAKEFOURCC) */\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'), 0, 0, 0, 0, 0};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 =\n    {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00};\n\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 =\n    {sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff};\n\n// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue\n\n// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 =\n    {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0};\n\n#define DDS_HEADER_FLAGS_TEXTURE 0x00001007           // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT\n#define DDS_HEADER_FLAGS_MIPMAP 0x00020000            // DDSD_MIPMAPCOUNT\n#define DDS_HEADER_FLAGS_VOLUME 0x00800000            // DDSD_DEPTH\n#define DDS_HEADER_FLAGS_PITCH 0x00000008             // DDSD_PITCH\n#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000        // DDSD_LINEARSIZE\n\n#define DDS_HEIGHT 0x00000002        // DDSD_HEIGHT\n#define DDS_WIDTH 0x00000004         // DDSD_WIDTH\n\n#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000        // DDSCAPS_TEXTURE\n#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008         // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP\n#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008        // DDSCAPS_COMPLEX\n\n#define DDS_CUBEMAP_POSITIVEX 0x00000600        // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX\n#define DDS_CUBEMAP_NEGATIVEX 0x00000a00        // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX\n#define DDS_CUBEMAP_POSITIVEY 0x00001200        // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY\n#define DDS_CUBEMAP_NEGATIVEY 0x00002200        // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY\n#define DDS_CUBEMAP_POSITIVEZ 0x00004200        // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ\n#define DDS_CUBEMAP_NEGATIVEZ 0x00008200        // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ\n\n#define DDS_CUBEMAP_ALLFACES (DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX | \\\n\t                          DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY | \\\n\t                          DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ)\n\n#define DDS_CUBEMAP 0x00000200        // DDSCAPS2_CUBEMAP\n\n#define DDS_FLAGS_VOLUME 0x00200000        // DDSCAPS2_VOLUME\n\n// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION\nenum DDS_RESOURCE_DIMENSION\n{\n\tDDS_DIMENSION_TEXTURE1D = 2,\n\tDDS_DIMENSION_TEXTURE2D = 3,\n\tDDS_DIMENSION_TEXTURE3D = 4,\n};\n\n// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG\nenum DDS_RESOURCE_MISC_FLAG\n{\n\tDDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,\n};\n\nenum DDS_MISC_FLAGS2\n{\n\tDDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,\n};\n\nstruct DDS_HEADER\n{\n\tuint32_t        size;\n\tuint32_t        flags;\n\tuint32_t        height;\n\tuint32_t        width;\n\tuint32_t        pitchOrLinearSize;\n\tuint32_t        depth;        // only if DDS_HEADER_FLAGS_VOLUME is set in flags\n\tuint32_t        mipMapCount;\n\tuint32_t        reserved1[11];\n\tDDS_PIXELFORMAT ddspf;\n\tuint32_t        caps;\n\tuint32_t        caps2;\n\tuint32_t        caps3;\n\tuint32_t        caps4;\n\tuint32_t        reserved2;\n};\n\nstruct DDS_HEADER_DXT10\n{\n\tDXGI_FORMAT dxgiFormat;\n\tuint32_t    resourceDimension;\n\tuint32_t    miscFlag;        // see D3D11_RESOURCE_MISC_FLAG\n\tuint32_t    arraySize;\n\tuint32_t    miscFlags2;        // see DDS_MISC_FLAGS2\n};\n\nstatic_assert(sizeof(DDS_HEADER) == 124, \"DDS Header size mismatch\");\nstatic_assert(sizeof(DDS_HEADER_DXT10) == 20, \"DDS DX10 Extended Header size mismatch\");\n\n#define ISBITMASK(r, g, b, a) (ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a)\n\nstatic DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT &ddpf)\n{\n\tif (ddpf.flags & DDS_RGB)\n\t{\n\t\t// Note that sRGB formats are written using the \"DX10\" extended header\n\n\t\tswitch (ddpf.RGBBitCount)\n\t\t{\n\t\t\tcase 32:\n\t\t\t\tif (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_R8G8B8A8_UNORM;\n\t\t\t\t}\n\n\t\t\t\tif (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_B8G8R8A8_UNORM;\n\t\t\t\t}\n\n\t\t\t\tif (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_B8G8R8X8_UNORM;\n\t\t\t\t}\n\n\t\t\t\t// No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8\n\n\t\t\t\t// Note that many common DDS reader/writers (including D3DX) swap the\n\t\t\t\t// the RED/BLUE masks for 10:10:10:2 formats. We assumme\n\t\t\t\t// below that the 'backwards' header mask is being used since it is most\n\t\t\t\t// likely written by D3DX. The more robust solution is to use the 'DX10'\n\t\t\t\t// header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly\n\n\t\t\t\t// For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data\n\t\t\t\tif (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_R10G10B10A2_UNORM;\n\t\t\t\t}\n\n\t\t\t\t// No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10\n\n\t\t\t\tif (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_R16G16_UNORM;\n\t\t\t\t}\n\n\t\t\t\tif (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000))\n\t\t\t\t{\n\t\t\t\t\t// Only 32-bit color channel format in D3D9 was R32F\n\t\t\t\t\treturn DXGI_FORMAT_R32_FLOAT;        // D3DX writes this out as a FourCC of 114\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 24:\n\t\t\t\t// No 24bpp DXGI formats aka D3DFMT_R8G8B8\n\t\t\t\tbreak;\n\n\t\t\tcase 16:\n\t\t\t\tif (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_B5G5R5A1_UNORM;\n\t\t\t\t}\n\t\t\t\tif (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_B5G6R5_UNORM;\n\t\t\t\t}\n\n\t\t\t\t// No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5\n\n\t\t\t\tif (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000))\n\t\t\t\t{\n\t\t\t\t\treturn DXGI_FORMAT_B4G4R4A4_UNORM;\n\t\t\t\t}\n\n\t\t\t\t// No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4\n\n\t\t\t\t// No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.\n\t\t\t\tbreak;\n\t\t}\n\t}\n\telse if (ddpf.flags & DDS_LUMINANCE)\n\t{\n\t\tif (8 == ddpf.RGBBitCount)\n\t\t{\n\t\t\tif (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000))\n\t\t\t{\n\t\t\t\treturn DXGI_FORMAT_R8_UNORM;        // D3DX10/11 writes this out as DX10 extension\n\t\t\t}\n\n\t\t\t// No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4\n\t\t}\n\n\t\tif (16 == ddpf.RGBBitCount)\n\t\t{\n\t\t\tif (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000))\n\t\t\t{\n\t\t\t\treturn DXGI_FORMAT_R16_UNORM;        // D3DX10/11 writes this out as DX10 extension\n\t\t\t}\n\t\t\tif (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))\n\t\t\t{\n\t\t\t\treturn DXGI_FORMAT_R8G8_UNORM;        // D3DX10/11 writes this out as DX10 extension\n\t\t\t}\n\t\t}\n\t}\n\telse if (ddpf.flags & DDS_ALPHA)\n\t{\n\t\tif (8 == ddpf.RGBBitCount)\n\t\t{\n\t\t\treturn DXGI_FORMAT_A8_UNORM;\n\t\t}\n\t}\n\telse if (ddpf.flags & DDS_FOURCC)\n\t{\n\t\tif (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC1_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC2_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC3_UNORM;\n\t\t}\n\n\t\t// While pre-mulitplied alpha isn't directly supported by the DXGI formats,\n\t\t// they are basically the same as these BC formats so they can be mapped\n\t\tif (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC2_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC3_UNORM;\n\t\t}\n\n\t\tif (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC4_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC4_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC4_SNORM;\n\t\t}\n\n\t\tif (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC5_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC5_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_BC5_SNORM;\n\t\t}\n\n\t\t// BC6H and BC7 are written using the \"DX10\" extended header\n\n\t\tif (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_R8G8_B8G8_UNORM;\n\t\t}\n\t\tif (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_G8R8_G8B8_UNORM;\n\t\t}\n\n\t\tif (MAKEFOURCC('Y', 'U', 'Y', '2') == ddpf.fourCC)\n\t\t{\n\t\t\treturn DXGI_FORMAT_YUY2;\n\t\t}\n\n\t\t// Check for D3DFORMAT enums being set here\n\t\tswitch (ddpf.fourCC)\n\t\t{\n\t\t\tcase 36:        // D3DFMT_A16B16G16R16\n\t\t\t\treturn DXGI_FORMAT_R16G16B16A16_UNORM;\n\n\t\t\tcase 110:        // D3DFMT_Q16W16V16U16\n\t\t\t\treturn DXGI_FORMAT_R16G16B16A16_SNORM;\n\n\t\t\tcase 111:        // D3DFMT_R16F\n\t\t\t\treturn DXGI_FORMAT_R16_FLOAT;\n\n\t\t\tcase 112:        // D3DFMT_G16R16F\n\t\t\t\treturn DXGI_FORMAT_R16G16_FLOAT;\n\n\t\t\tcase 113:        // D3DFMT_A16B16G16R16F\n\t\t\t\treturn DXGI_FORMAT_R16G16B16A16_FLOAT;\n\n\t\t\tcase 114:        // D3DFMT_R32F\n\t\t\t\treturn DXGI_FORMAT_R32_FLOAT;\n\n\t\t\tcase 115:        // D3DFMT_G32R32F\n\t\t\t\treturn DXGI_FORMAT_R32G32_FLOAT;\n\n\t\t\tcase 116:        // D3DFMT_A32B32G32R32F\n\t\t\t\treturn DXGI_FORMAT_R32G32B32A32_FLOAT;\n\t\t}\n\t}\n\n\treturn DXGI_FORMAT_UNKNOWN;\n}\n\nclass DDSImporter : public Importer<ResourceType::Texture2D>\n{\n  protected:\n\tvirtual void Import_(ResourceManager *manager, const std::string &path, RHIContext *rhi_context) override\n\n\t{\n\t\tTextureDesc desc;\n\t\tdesc.name    = Path::GetInstance().GetFileName(path, false);\n\t\tdesc.width   = 1;\n\t\tdesc.height  = 1;\n\t\tdesc.depth   = 1;\n\t\tdesc.mips    = 1;\n\t\tdesc.layers  = 1;\n\t\tdesc.samples = 1;\n\n\t\tstd::vector<uint8_t> raw_data;\n\t\tPath::GetInstance().Read(path, raw_data, true);\n\n\t\tsize_t   data_size = raw_data.size();\n\t\tuint8_t *data      = raw_data.data();\n\n\t\tuint32_t dwMagicNumber = *(const uint32_t *) (data);\n\t\tif (dwMagicNumber != DDS_MAGIC)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tauto header = reinterpret_cast<const DDS_HEADER *>(data + sizeof(uint32_t));\n\t\tif (header->size != sizeof(DDS_HEADER) ||\n\t\t    header->ddspf.size != sizeof(DDS_PIXELFORMAT))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tsize_t offset = sizeof(DDS_HEADER) + sizeof(uint32_t);\n\n\t\t// Check for extensions\n\t\tif (header->ddspf.flags & DDS_FOURCC)\n\t\t{\n\t\t\tif (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC)\n\t\t\t{\n\t\t\t\toffset += sizeof(DDS_HEADER_DXT10);\n\t\t\t}\n\t\t}\n\n\t\tif (data_size < offset)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tdesc.width  = header->width;\n\t\tdesc.height = header->height;\n\t\tdesc.depth  = header->depth;\n\n\t\tif ((header->ddspf.flags & DDS_FOURCC) && (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))\n\t\t{\n\t\t\tauto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10 *>((const char *) header + sizeof(DDS_HEADER));\n\n\t\t\tdesc.layers = d3d10ext->arraySize;\n\t\t\tif (desc.layers == 0)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (FormatMap.find(d3d10ext->dxgiFormat) != FormatMap.end())\n\t\t\t{\n\t\t\t\tdesc.format = FormatMap[d3d10ext->dxgiFormat];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto dxgi_format = GetDXGIFormat(header->ddspf);\n\t\t\tif (FormatMap.find(dxgi_format) != FormatMap.end())\n\t\t\t{\n\t\t\t\tdesc.format = FormatMap[dxgi_format];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (header->flags & DDS_HEADER_FLAGS_VOLUME)\n\t\t\t{\n\t\t\t\t// So it's a 3D texture\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdesc.depth  = 1;\n\t\t\t\tdesc.layers = 1;\n\n\t\t\t\tif (header->caps2 & DDS_CUBEMAP)\n\t\t\t\t{\n\t\t\t\t\t// Require all six faces to be defined\n\t\t\t\t\tif ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tdesc.layers = 6;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (desc.depth > 1)\n\t\t{\n\t\t\tLOG_WARN(\"Texture is not 2D Texture!\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (desc.layers > 1)\n\t\t{\n\t\t\tLOG_WARN(\"Texture is not 2D Texture!\");\n\t\t\treturn;\n\t\t}\n\n\t\tuint8_t *tex_data = data + offset;\n\t\tdata_size -= offset;\n\n\t\tstd::vector<uint8_t> final_data;\n\n\t\tfinal_data.resize(data_size);\n\t\tstd::memcpy(final_data.data(), tex_data, data_size);\n\n\t\tdesc.mips  = static_cast<uint32_t>(std::floor(std::log2(std::max(desc.width, desc.height))) + 1);\n\t\tdesc.usage = RHITextureUsage::ShaderResource | RHITextureUsage::Transfer;\n\n\t\tmanager->Add<ResourceType::Texture2D>(rhi_context, std::move(final_data), desc);\n\t}\n};\n\nextern \"C\"\n{\n\tEXPORT_API DDSImporter *Create()\n\t{\n\t\treturn new DDSImporter;\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Importer/STB.cpp",
    "content": "#include <RHI/RHITexture.hpp>\n#include <Resource/Importer.hpp>\n#include <Resource/Resource/Texture2D.hpp>\n#include <Resource/Resource/TextureCube.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <stb_image.h>\n\nusing namespace Ilum;\n\nclass STBImporter : public Importer<ResourceType::Texture2D>\n{\n  protected:\n\tvirtual void Import_(ResourceManager *manager, const std::string &path, RHIContext *rhi_context) override\n\t{\n\t\tstd::string texture_name = Path::GetInstance().ValidFileName(path);\n\n\t\tif (manager->Has<ResourceType::Texture2D>(texture_name))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tTextureDesc desc = {};\n\t\tdesc.name        = texture_name;\n\t\tdesc.width       = 1;\n\t\tdesc.height      = 1;\n\t\tdesc.depth       = 1;\n\t\tdesc.mips        = 1;\n\t\tdesc.layers      = 1;\n\t\tdesc.samples     = 1;\n\n\t\tint32_t width = 0, height = 0, channel = 0;\n\n\t\tconst int32_t req_channel = 4;\n\n\t\tvoid  *raw_data = nullptr;\n\t\tsize_t size     = 0;\n\n\t\tif (stbi_is_hdr(path.c_str()))\n\t\t{\n\t\t\traw_data    = stbi_loadf(path.c_str(), &width, &height, &channel, req_channel);\n\t\t\tsize        = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(req_channel) * sizeof(float);\n\t\t\tdesc.format = RHIFormat::R32G32B32A32_FLOAT;\n\t\t}\n\t\telse if (stbi_is_16_bit(path.c_str()))\n\t\t{\n\t\t\traw_data    = stbi_load_16(path.c_str(), &width, &height, &channel, req_channel);\n\t\t\tsize        = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(req_channel) * sizeof(uint16_t);\n\t\t\tdesc.format = RHIFormat::R16G16B16A16_FLOAT;\n\t\t}\n\t\telse\n\t\t{\n\t\t\traw_data    = stbi_load(path.c_str(), &width, &height, &channel, req_channel);\n\t\t\tsize        = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(req_channel) * sizeof(uint8_t);\n\t\t\tdesc.format = RHIFormat::R8G8B8A8_UNORM;\n\t\t}\n\n\t\tdesc.width  = static_cast<uint32_t>(width);\n\t\tdesc.height = static_cast<uint32_t>(height);\n\t\tdesc.usage  = RHITextureUsage::ShaderResource | RHITextureUsage::Transfer;\n\n\t\tstd::vector<uint8_t> data;\n\n\t\tdata.resize(size);\n\t\tstd::memcpy(data.data(), raw_data, size);\n\n\t\tstbi_image_free(raw_data);\n\n\t\tif (Path::GetInstance().GetFileExtension(path) == \".hdr\")\n\t\t{\n\t\t\tdesc.mips = 1;\n\t\t\tmanager->Add<ResourceType::TextureCube>(rhi_context, std::move(data), desc);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdesc.mips = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height))) + 1);\n\t\t\tmanager->Add<ResourceType::Texture2D>(rhi_context, std::move(data), desc);\n\t\t}\n\t}\n};\n\nextern \"C\"\n{\n\tEXPORT_API STBImporter *Create()\n\t{\n\t\treturn new STBImporter;\n\t}\n}"
  },
  {
    "path": "Source/Plugin/Importer/xmake.lua",
    "content": "function add_importer_plugin(name, deps, pkgs)\n    target(string.format(\"Importer.%s\", name))\n\n    set_kind(\"shared\")\n    set_group(\"Plugin/Importer\")\n\n    add_rules(\"plugin\")\n    add_files(string.format(\"%s.cpp\", name))\n    add_deps(\"Core\", \"RHI\", \"Resource\", deps)\n    add_packages(pkgs)\n\n    target(\"Plugin\")\n        add_deps(string.format(\"Importer.%s\", name))\n    target_end()\n\n    target_end()\nend\n\nadd_importer_plugin(\"STB\", {}, {\"stb\"})\nadd_importer_plugin(\"DDS\", {}, {})\nadd_importer_plugin(\"Assimp\", {\"Geometry\"}, {\"assimp\", \"stb\", \"meshoptimizer\"})"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/ConductorMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n#include \"Utils/SPDLoader.hpp\"\n\nusing namespace Ilum;\n\nclass ConductorMaterial : public MaterialNode<ConductorMaterial>\n{\n\tconst std::vector<const char *> m_materials = {\n\t    \"a-C\", \"Ag\", \"Al\", \"AlAs\", \"AlSb\", \"a-SiH\", \"Au\", \"Be\", \"Cr\", \"Csl\", \"Cu\",\n\t    \"Cu2O\", \"CuO\", \"d-C\", \"Hg\", \"HgTe\", \"Ir\", \"K\", \"KBr\", \"KCl\", \"Li\", \"MgO\", \"Mo\",\n\t    \"NaCl\", \"Nb\", \"Rh\", \"Se\", \"Se-e\", \"SiC\", \"SiO\", \"SnTe\", \"Ta\", \"Te\", \"Te-e\", \"ThF4\",\n\t    \"TiC\", \"TiN\", \"TiO2\", \"TiO2-e\", \"VC\", \"VN\", \"W\"};\n\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"ConductorMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .SetVariant(int32_t(1))\n\t\t    .Input(handle++, \"Reflectance\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"Roughness\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.1f))\n\t\t    .Input(handle++, \"Normal\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t\tint32_t &material_type = *node_desc.GetVariant().Convert<int32_t>();\n\n\t\tImGui::PushID(\"material type\");\n\t\tif (ImGui::BeginCombo(\"\", \"Type\"))\n\t\t{\n\t\t\tfor (size_t i = 0; i < m_materials.size(); i++)\n\t\t\t{\n\t\t\t\tconst bool is_selected = (i == material_type);\n\t\t\t\tif (ImGui::Selectable(m_materials[i], i == material_type))\n\t\t\t\t{\n\t\t\t\t\tmaterial_type = static_cast<int32_t>(i);\n\t\t\t\t}\n\t\t\t\tif (is_selected)\n\t\t\t\t{\n\t\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t\t\t}\n\t\t\t}\n\t\t\tImGui::EndCombo();\n\t\t}\n\t\tImGui::PopID();\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tint32_t material_type = *node_desc.GetVariant().Convert<int32_t>();\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tif (!context->HasParameter<glm::vec3>(parameters, node_desc.GetPin(\"Normal\"), graph_desc, manager, context))\n\t\t{\n\t\t\tparameters[\"Normal\"] = \"surface_interaction.isect.n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tparameters[\"Normal\"] = fmt::format(\"ExtractNormalMap(surface_interaction, {})\", parameters[\"Normal\"]);\n\t\t}\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Reflectance\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Roughness\"), graph_desc, manager, context);\n\n\t\tglm::vec3 eta = SPDLoader::Load(fmt::format(\"Asset/SPD/metals/{}.eta.spd\", m_materials[material_type]));\n\t\tglm::vec3 k   = SPDLoader::Load(fmt::format(\"Asset/SPD/metals/{}.k.spd\", m_materials[material_type]));\n\n\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t    \"ConductorMaterial\",\n\t\t    fmt::format(\"S_{}.Init({}, {}, float3({}, {}, {}),  float3({}, {}, {}), {});\", node_desc.GetPin(\"Out\").handle,\n\t\t                parameters[\"Reflectance\"],\n\t\t                parameters[\"Roughness\"],\n\t\t                eta.x, eta.y, eta.z,\n\t\t                k.x, k.y, k.z,\n\t\t                parameters[\"Normal\"])});\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(ConductorMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/DielectricMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass DielectricMaterial : public MaterialNode<DielectricMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"DielectricMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"Reflectance\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"Transmittance\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"Roughness\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.1f))\n\t\t    .Input(handle++, \"IOR\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(1.45f))\n\t\t    .Input(handle++, \"Normal\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tif (!context->HasParameter<glm::vec3>(parameters, node_desc.GetPin(\"Normal\"), graph_desc, manager, context))\n\t\t{\n\t\t\tparameters[\"Normal\"] = \"surface_interaction.isect.n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tparameters[\"Normal\"] = fmt::format(\"ExtractNormalMap(surface_interaction, {})\", parameters[\"Normal\"]);\n\t\t}\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Reflectance\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Transmittance\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Roughness\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"IOR\"), graph_desc, manager, context);\n\n\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t    \"DielectricMaterial\",\n\t\t    fmt::format(\"S_{}.Init({}, {}, {}, {}, {});\", node_desc.GetPin(\"Out\").handle,\n\t\t                parameters[\"Reflectance\"],\n\t\t                parameters[\"Transmittance\"],\n\t\t                parameters[\"IOR\"],\n\t\t                parameters[\"Roughness\"],\n\t\t                parameters[\"Normal\"])});\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(DielectricMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/DiffuseMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass DiffuseMaterial : public MaterialNode<DiffuseMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"DiffuseMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"Normal\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3)\n\t\t    .Input(handle++, \"Reflectance\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tif (!context->HasParameter<glm::vec3>(parameters, node_desc.GetPin(\"Normal\"), graph_desc, manager, context))\n\t\t{\n\t\t\tparameters[\"Normal\"] = \"surface_interaction.isect.n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tparameters[\"Normal\"] = fmt::format(\"ExtractNormalMap(surface_interaction, {})\", parameters[\"Normal\"]);\n\t\t}\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Reflectance\"), graph_desc, manager, context);\n\n\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t    \"DiffuseMaterial\",\n\t\t    fmt::format(\"S_{}.Init({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"Reflectance\"], parameters[\"Normal\"])});\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(DiffuseMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/DisneyMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass DisneyMaterial : public MaterialNode<DisneyMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"DisneyMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"BaseColor\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"Metallic\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.5f))\n\t\t    .Input(handle++, \"Roughness\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.5f))\n\t\t    .Input(handle++, \"Anisotropic\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Sheen\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"SheenTint\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Specular\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"SpecTint\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Clearcoat\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"ClearcoatGloss\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Flatness\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"SpecTrans\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"IOR\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(1.45f))\n\t\t    .Input(handle++, \"Emissive\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Input(handle++, \"TwoSide\", MaterialNodePin::Type::Bool, MaterialNodePin::Type::Bool, true)\n\t\t\t.Input(handle++, \"Normal\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tif (!context->HasParameter<glm::vec3>(parameters, node_desc.GetPin(\"Normal\"), graph_desc, manager, context))\n\t\t{\n\t\t\tparameters[\"Normal\"] = \"surface_interaction.isect.n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tparameters[\"Normal\"] = fmt::format(\"ExtractNormalMap(surface_interaction, {})\", parameters[\"Normal\"]);\n\t\t}\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"BaseColor\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Metallic\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Roughness\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Anisotropic\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Sheen\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"SheenTint\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Specular\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"SpecTint\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Clearcoat\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"ClearcoatGloss\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Flatness\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"SpecTrans\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"IOR\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Emissive\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<bool>(parameters, node_desc.GetPin(\"TwoSide\"), graph_desc, manager, context);\n\n\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t    \"DisneyMaterial\",\n\t\t    fmt::format(\"S_{}.Init({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});\", node_desc.GetPin(\"Out\").handle,\n\t\t                parameters[\"BaseColor\"],\n\t\t                parameters[\"Metallic\"],\n\t\t                parameters[\"Roughness\"],\n\t\t                parameters[\"Anisotropic\"],\n\t\t                parameters[\"Sheen\"],\n\t\t                parameters[\"SheenTint\"],\n\t\t                parameters[\"Specular\"],\n\t\t                parameters[\"SpecTint\"],\n\t\t                parameters[\"Clearcoat\"],\n\t\t                parameters[\"ClearcoatGloss\"],\n\t\t                parameters[\"Flatness\"],\n\t\t                parameters[\"SpecTrans\"],\n\t\t                parameters[\"IOR\"],\n\t\t                parameters[\"Emissive\"],\n\t\t                parameters[\"TwoSide\"],\n\t\t                parameters[\"Normal\"])});\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(DisneyMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/MaskedMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass MaskedMaterial : public MaterialNode<MaskedMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"MaskedMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"BSDF\", MaterialNodePin::Type::BSDF, MaterialNodePin::Type::BSDF)\n\t\t    .Input(handle++, \"Opacity\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::Float3 | MaterialNodePin::Type::RGB, float(0.f))\n\t\t    .Input(handle++, \"Threshold\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::Float3 | MaterialNodePin::Type::RGB, float(0.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Opacity\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Threshold\"), graph_desc, manager, context);\n\n\t\tauto &bsdf_node = node_desc.GetPin(\"BSDF\");\n\n\t\tif (graph_desc.HasLink(bsdf_node.handle))\n\t\t{\n\t\t\tsize_t bsdf = 0;\n\n\t\t\t{\n\t\t\t\tauto &src_node = graph_desc.GetNode(graph_desc.LinkFrom(bsdf_node.handle));\n\t\t\t\tsrc_node.EmitHLSL(graph_desc, manager, context);\n\t\t\t\tauto &src_pin = src_node.GetPin(graph_desc.LinkFrom(bsdf_node.handle));\n\n\t\t\t\tbsdf = src_pin.handle;\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tstd::string bsdf_type = \"\";\n\n\t\t\t\tstd::string bsdf_name = fmt::format(\"S_{}\", bsdf);\n\n\t\t\t\tfor (auto &bsdf : context->bsdfs)\n\t\t\t\t{\n\t\t\t\t\tif (bsdf.name == bsdf_name)\n\t\t\t\t\t{\n\t\t\t\t\t\tbsdf_type = bsdf.type;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t\t\t    fmt::format(\"MaskedMaterial< {} >\", bsdf_type),\n\t\t\t\t    fmt::format(\"S_{}.Init(S_{}, {}, {});\", node_desc.GetPin(\"Out\").handle,\n\t\t\t\t                bsdf,\n\t\t\t\t                parameters[\"Opacity\"],\n\t\t\t\t                parameters[\"Threshold\"])});\n\t\t\t}\n\t\t}\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(MaskedMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/MixMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass MixMaterial : public MaterialNode<MixMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"MixMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"X\", MaterialNodePin::Type::BSDF, MaterialNodePin::Type::BSDF)\n\t\t    .Input(handle++, \"Y\", MaterialNodePin::Type::BSDF, MaterialNodePin::Type::BSDF)\n\t\t    .Input(handle++, \"Weight\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::Float3 | MaterialNodePin::Type::RGB, float(0.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Weight\"), graph_desc, manager, context);\n\n\t\tauto &bsdf1_node = node_desc.GetPin(\"X\");\n\t\tauto &bsdf2_node = node_desc.GetPin(\"Y\");\n\n\t\tif (graph_desc.HasLink(bsdf1_node.handle) && graph_desc.HasLink(bsdf2_node.handle))\n\t\t{\n\t\t\tsize_t bsdf1 = 0;\n\t\t\tsize_t bsdf2 = 0;\n\n\t\t\t{\n\t\t\t\tauto &src_node = graph_desc.GetNode(graph_desc.LinkFrom(bsdf1_node.handle));\n\t\t\t\tsrc_node.EmitHLSL(graph_desc, manager, context);\n\t\t\t\tauto &src_pin = src_node.GetPin(graph_desc.LinkFrom(bsdf1_node.handle));\n\n\t\t\t\tbsdf1 = src_pin.handle;\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto &src_node = graph_desc.GetNode(graph_desc.LinkFrom(bsdf2_node.handle));\n\t\t\t\tsrc_node.EmitHLSL(graph_desc, manager, context);\n\t\t\t\tauto &src_pin = src_node.GetPin(graph_desc.LinkFrom(bsdf2_node.handle));\n\n\t\t\t\tbsdf2 = src_pin.handle;\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tstd::string bsdf1_type = \"\";\n\t\t\t\tstd::string bsdf2_type = \"\";\n\n\t\t\t\tstd::string bsdf1_name = fmt::format(\"S_{}\", bsdf1);\n\t\t\t\tstd::string bsdf2_name = fmt::format(\"S_{}\", bsdf2);\n\n\t\t\t\tfor (auto &bsdf : context->bsdfs)\n\t\t\t\t{\n\t\t\t\t\tif (bsdf.name == bsdf1_name)\n\t\t\t\t\t{\n\t\t\t\t\t\tbsdf1_type = bsdf.type;\n\t\t\t\t\t}\n\t\t\t\t\tif (bsdf.name == bsdf2_name)\n\t\t\t\t\t{\n\t\t\t\t\t\tbsdf2_type = bsdf.type;\n\t\t\t\t\t}\n\t\t\t\t\tif (!bsdf1_type.empty() && !bsdf2_type.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t\t\t    fmt::format(\"MixMaterial< {}, {} >\", bsdf1_type, bsdf2_type),\n\t\t\t\t    fmt::format(\"S_{}.Init(S_{}, S_{}, {});\", node_desc.GetPin(\"Out\").handle, bsdf1, bsdf2, parameters[\"Weight\"])});\n\t\t\t}\n\t\t}\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(MixMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/PrincipledMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass PrincipledMaterial : public MaterialNode<PrincipledMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"PrincipledMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"BaseColor\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"Metallic\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.5f))\n\t\t    .Input(handle++, \"Roughness\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.5f))\n\t\t    .Input(handle++, \"Anisotropic\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Sheen\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"SheenTint\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Specular\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"SpecTint\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Clearcoat\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"ClearcoatGloss\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Flatness\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"SpecTrans\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"IOR\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(1.45f))\n\t\t    .Input(handle++, \"Emissive\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Input(handle++, \"TwoSide\", MaterialNodePin::Type::Bool, MaterialNodePin::Type::Bool, true)\n\t\t\t.Input(handle++, \"Normal\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tif (!context->HasParameter<glm::vec3>(parameters, node_desc.GetPin(\"Normal\"), graph_desc, manager, context))\n\t\t{\n\t\t\tparameters[\"Normal\"] = \"surface_interaction.isect.n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tparameters[\"Normal\"] = fmt::format(\"ExtractNormalMap(surface_interaction, {})\", parameters[\"Normal\"]);\n\t\t}\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"BaseColor\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Metallic\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Roughness\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Anisotropic\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Sheen\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"SheenTint\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Specular\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"SpecTint\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Clearcoat\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"ClearcoatGloss\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Flatness\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"SpecTrans\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"IOR\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Emissive\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<bool>(parameters, node_desc.GetPin(\"TwoSide\"), graph_desc, manager, context);\n\n\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t    \"PrincipledMaterial\",\n\t\t    fmt::format(\"S_{}.Init({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});\", node_desc.GetPin(\"Out\").handle,\n\t\t                parameters[\"BaseColor\"],\n\t\t                parameters[\"Metallic\"],\n\t\t                parameters[\"Roughness\"],\n\t\t                parameters[\"Anisotropic\"],\n\t\t                parameters[\"Sheen\"],\n\t\t                parameters[\"SheenTint\"],\n\t\t                parameters[\"Specular\"],\n\t\t                parameters[\"SpecTint\"],\n\t\t                parameters[\"Clearcoat\"],\n\t\t                parameters[\"ClearcoatGloss\"],\n\t\t                parameters[\"Flatness\"],\n\t\t                parameters[\"SpecTrans\"],\n\t\t                parameters[\"IOR\"],\n\t\t                parameters[\"Emissive\"],\n\t\t                parameters[\"TwoSide\"],\n\t\t                parameters[\"Normal\"])});\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(PrincipledMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/ThinDielectricMaterial.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass ThinDielectricMaterial : public MaterialNode<ThinDielectricMaterial>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"ThinDielectricMaterial\")\n\t\t    .SetCategory(\"BSDF\")\n\t\t    .Input(handle++, \"Reflectance\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"Transmittance\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(1.f))\n\t\t    .Input(handle++, \"IOR\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(1.45f))\n\t\t    .Input(handle++, \"Normal\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::BSDF);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tif (!context->HasParameter<glm::vec3>(parameters, node_desc.GetPin(\"Normal\"), graph_desc, manager, context))\n\t\t{\n\t\t\tparameters[\"Normal\"] = \"surface_interaction.isect.n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tparameters[\"Normal\"] = fmt::format(\"ExtractNormalMap(surface_interaction, {})\", parameters[\"Normal\"]);\n\t\t}\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Reflectance\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Transmittance\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"IOR\"), graph_desc, manager, context);\n\n\t\tcontext->bsdfs.emplace_back(MaterialCompilationContext::BSDF{\n\t\t    fmt::format(\"S_{}\", node_desc.GetPin(\"Out\").handle),\n\t\t    \"ThinDielectricMaterial\",\n\t\t    fmt::format(\"S_{}.Init({}, {}, {}, {});\", node_desc.GetPin(\"Out\").handle,\n\t\t                parameters[\"Reflectance\"],\n\t\t                parameters[\"Transmittance\"],\n\t\t                parameters[\"IOR\"],\n\t\t                parameters[\"Normal\"])});\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(ThinDielectricMaterial)"
  },
  {
    "path": "Source/Plugin/MaterialNode/BSDF/Utils/SPDLoader.hpp",
    "content": "#pragma once\n\n#include <Material/Spectrum.hpp>\n\n#include <glm/glm.hpp>\n\n#include <fstream>\n\nnamespace Ilum\n{\n// Loading *.spd spectrum data\nclass SPDLoader\n{\n  public:\n\tinline static glm::vec3 Load(const std::string &path)\n\t{\n\t\tstd::fstream fs;\n\t\tfs.open(path.c_str(), std::ios::in);\n\n\t\tstd::vector<float> vals;\n\n\t\tstd::string line;\n\t\twhile (std::getline(fs, line))\n\t\t{\n\t\t\tif (!line.empty() && line[0] != '#')\n\t\t\t{\n\t\t\t\tauto line_data = Path::GetInstance().Split(line, ' ');\n\t\t\t\tfor (auto &x : line_data)\n\t\t\t\t{\n\t\t\t\t\tvals.push_back(std::stof(x));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstd::vector<float> wls, v;\n\t\tfor (size_t j = 0; j < vals.size() / 2; ++j)\n\t\t{\n\t\t\twls.push_back(vals[2 * j]);\n\t\t\tv.push_back(vals[2 * j + 1]);\n\t\t}\n\t\tglm::vec3 result = FromSampled(&wls[0], &v[0], static_cast<int32_t>(wls.size()));\n\n\t\tfs.close();\n\n\t\treturn result;\n\t}\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Plugin/MaterialNode/Converter/Calculate.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass Calculate : public MaterialNode<Calculate>\n{\n\tenum class CalculationType\n\t{\n\t\tAddition,\n\t\tSubstrate,\n\t\tMultiplication,\n\t\tDivision,\n\n\t\tMaximum,\n\t\tMinimum,\n\n\t\tGreater,\n\t\tLess,\n\n\t\tSquare,\n\t\tLog,\n\t\tExp,\n\t\tSqrt,\n\t\tRcp,\n\t\tAbs,\n\t\tSign,\n\n\t\tSin,\n\t\tCos,\n\t\tTan,\n\n\t\tAsin,\n\t\tAcos,\n\t\tAtan,\n\t\tAtan2,\n\n\t\tSinh,\n\t\tCosh,\n\t\tTanh,\n\t};\n\n\tconst std::vector<const char *> calculation_types = {\n\t    \"Addition\",\n\t    \"Substrate\",\n\t    \"Multiplication\",\n\t    \"Division\",\n\t    \"Maximum\",\n\t    \"Minimum\",\n\t    \"Greater\",\n\t    \"Less\",\n\t    \"Square\",\n\t    \"Log\",\n\t    \"Exp\",\n\t    \"Sqrt\",\n\t    \"Rcp\",\n\t    \"Abs\",\n\t    \"Sign\",\n\t    \"Sin\",\n\t    \"Cos\",\n\t    \"Tan\",\n\t    \"Asin\",\n\t    \"Acos\",\n\t    \"Atan\",\n\t    \"Atan2\",\n\t    \"Sinh\",\n\t    \"Cosh\",\n\t    \"Tanh\",\n\t};\n\n\tconst std::unordered_set<CalculationType> binary_op = {\n\t    CalculationType::Addition,\n\t    CalculationType::Substrate,\n\t    CalculationType::Multiplication,\n\t    CalculationType::Division,\n\t    CalculationType::Maximum,\n\t    CalculationType::Minimum,\n\t    CalculationType::Greater,\n\t    CalculationType::Less,\n\t    CalculationType::Square,\n\t    CalculationType::Atan2,\n\t};\n\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"Calculate\")\n\t\t    .SetCategory(\"Converter\")\n\t\t    .SetVariant(CalculationType::Addition)\n\t\t    .Input(handle++, \"X\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Y\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::Float);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t\tCalculationType &type = *node_desc.GetVariant().Convert<CalculationType>();\n\t\tif (ImGui::Combo(\"\", (int32_t *) (&type), calculation_types.data(), static_cast<int32_t>(calculation_types.size())))\n\t\t{\n\t\t\tnode_desc.GetPin(\"Y\").enable = binary_op.find(type) != binary_op.end();\n\t\t}\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"X\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Y\"), graph_desc, manager, context);\n\n\t\tCalculationType type = *node_desc.GetVariant().Convert<CalculationType>();\n\n\t\tswitch (type)\n\t\t{\n\t\t\tcase CalculationType::Addition:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} + {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Substrate:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} - {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Multiplication:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} * {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Division:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} / {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Maximum:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = max({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Minimum:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = min({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Greater:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} > {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Less:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} < {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Square:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {} * {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Log:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = log({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Exp:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = exp({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Sqrt:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = sqrt({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Rcp:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = rcp({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Abs:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = abs({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Sign:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = sign({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Sin:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = sin({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Cos:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = cos({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Tan:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = tan({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Asin:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = asin({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Acos:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = acos({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Atan:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = atan({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Atan2:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = atan2({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"Y\"], parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Sinh:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = sinh({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Cosh:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = cosh({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Tanh:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = tanh({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(Calculate)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Converter/SRGBToLinear.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass SRGBToLinear : public MaterialNode<SRGBToLinear>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"SRGBToLinear\")\n\t\t    .SetCategory(\"Converter\")\n\t\t    .Input(handle++, \"In\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::Float3);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"In\"), graph_desc, manager, context);\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = SRGBtoLINEAR({});\", node_desc.GetPin(\"Out\").handle, parameters[\"In\"]));\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(SRGBToLinear)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Converter/VectorCalculate.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass VectorCalculate : public MaterialNode<VectorCalculate>\n{\n\tenum class CalculationType\n\t{\n\t\tScale,\n\t\tLength,\n\t\tDistance,\n\n\t\tDot,\n\t\tCross,\n\n\t\tAddition,\n\t\tSubstrate,\n\t\tMultiplication,\n\t\tDivision,\n\n\t\tSin,\n\t\tCos,\n\t\tTan,\n\n\t\tMaximum,\n\t\tMinimum,\n\n\t\tAbs,\n\n\t\tNormalize,\n\t};\n\n\tconst std::vector<const char *> calculation_types = {\n\t    \"Scale\",\n\t    \"Length\",\n\t    \"Distance\",\n\t    \"Dot\",\n\t    \"Cross\",\n\t    \"Addition\",\n\t    \"Substrate\",\n\t    \"Multiplication\",\n\t    \"Division\",\n\t    \"Sin\",\n\t    \"Cos\",\n\t    \"Tan\",\n\t    \"Maximum\",\n\t    \"Minimum\",\n\t    \"Abs\",\n\t    \"Normalize\",\n\t};\n\n\tconst std::unordered_set<CalculationType> binary_op = {\n\t    CalculationType::Addition,\n\t    CalculationType::Substrate,\n\t    CalculationType::Multiplication,\n\t    CalculationType::Division,\n\t    CalculationType::Maximum,\n\t    CalculationType::Minimum,\n\t    CalculationType::Dot,\n\t    CalculationType::Cross,\n\t    CalculationType::Distance,\n\t    CalculationType::Scale,\n\t};\n\n\tconst std::unordered_set<CalculationType> scale_output = {\n\t    CalculationType::Length,\n\t    CalculationType::Distance,\n\t    CalculationType::Dot,\n\t};\n\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"VectorCalculate\")\n\t\t    .SetCategory(\"Converter\")\n\t\t    .SetVariant(CalculationType::Addition)\n\t\t    .Input(handle++, \"X\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Input(handle++, \"Y\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::Float3);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t\tCalculationType &type = *node_desc.GetVariant().Convert<CalculationType>();\n\t\tif (ImGui::Combo(\"\", (int32_t *) (&type), calculation_types.data(), static_cast<int32_t>(calculation_types.size())))\n\t\t{\n\t\t\tnode_desc.GetPin(\"Y\").enable  = binary_op.find(type) != binary_op.end();\n\t\t\tnode_desc.GetPin(\"Y\").type    = type == CalculationType::Scale ? MaterialNodePin::Type::Float : MaterialNodePin::Type::Float3;\n\t\t\tnode_desc.GetPin(\"Y\").variant = type == CalculationType::Scale ? Variant(float(0.f)) : Variant(glm::vec3(0.f));\n\t\t\tnode_desc.GetPin(\"Out\").type  = scale_output.find(type) != scale_output.end() ? MaterialNodePin::Type::Float : MaterialNodePin::Type::Float3;\n\t\t}\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tCalculationType type = *node_desc.GetVariant().Convert<CalculationType>();\n\n\t\tstd::map<std::string, std::string> parameters;\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"X\"), graph_desc, manager, context);\n\t\tif (type == CalculationType::Scale)\n\t\t{\n\t\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Y\"), graph_desc, manager, context);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"Y\"), graph_desc, manager, context);\n\t\t}\n\n\t\tswitch (type)\n\t\t{\n\t\t\tcase CalculationType::Scale:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = {} * {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Length:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = length({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Distance:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = length({} - {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Dot:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = dot({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Cross:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = cross({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Addition:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = {} + {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Substrate:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = {} - {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Multiplication:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = {} * {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Division:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = {} / {};\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Sin:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = sin({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Cos:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = cos({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Tan:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = tan({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Maximum:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = max({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Minimum:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = min({}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Abs:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = abs({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tcase CalculationType::Normalize:\n\t\t\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = normalize({});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"]));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(VectorCalculate)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Converter/VectorMerge.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass VectorMerge : public MaterialNode<VectorMerge>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"VectorMerge\")\n\t\t    .SetCategory(\"Converter\")\n\t\t    .Input(handle++, \"X\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Y\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Input(handle++, \"Z\", MaterialNodePin::Type::Float, MaterialNodePin::Type::Float | MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, float(0.f))\n\t\t    .Output(handle++, \"Out\", MaterialNodePin::Type::Float3);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"X\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Y\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<float>(parameters, node_desc.GetPin(\"Z\"), graph_desc, manager, context);\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = float3({}, {}, {});\", node_desc.GetPin(\"Out\").handle, parameters[\"X\"], parameters[\"Y\"], parameters[\"Z\"]));\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(VectorMerge)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Converter/VectorSplit.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass VectorSplit : public MaterialNode<VectorSplit>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"VectorSplit\")\n\t\t    .SetCategory(\"Converter\")\n\t\t    .Input(handle++, \"In\", MaterialNodePin::Type::Float3, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Output(handle++, \"X\", MaterialNodePin::Type::Float)\n\t\t    .Output(handle++, \"Y\", MaterialNodePin::Type::Float)\n\t\t    .Output(handle++, \"Z\", MaterialNodePin::Type::Float);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tstd::map<std::string, std::string> parameters;\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"In\"), graph_desc, manager, context);\n\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {}.x;\", node_desc.GetPin(\"X\").handle, parameters[\"In\"]));\n\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {}.y;\", node_desc.GetPin(\"Y\").handle, parameters[\"In\"]));\n\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = {}.z;\", node_desc.GetPin(\"Z\").handle, parameters[\"In\"]));\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(VectorSplit)"
  },
  {
    "path": "Source/Plugin/MaterialNode/IMaterialNode.hpp",
    "content": "#pragma once\n\n#include <Editor/Editor.hpp>\n#include <Material/MaterialCompiler.hpp>\n#include <Material/MaterialGraph.hpp>\n#include <Material/MaterialNode.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Resource/ResourceManager.hpp>\n\n#include <imgui.h>\n\nusing namespace Ilum;\n\ntemplate <typename _Ty>\nclass MaterialNode\n{\n  public:\n\tstatic _Ty &GetInstance()\n\t{\n\t\tstatic _Ty node;\n\t\treturn node;\n\t}\n\n\tvirtual MaterialNodeDesc Create(size_t &handle) = 0;\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) = 0;\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) = 0;\n};\n\n#define CONFIGURATION_MATERIAL_NODE(NODE)                                                                                                                         \\\n\textern \"C\"                                                                                                                                                    \\\n\t{                                                                                                                                                             \\\n\t\tEXPORT_API void Create(MaterialNodeDesc *desc, size_t *handle)                                                                                            \\\n\t\t{                                                                                                                                                         \\\n\t\t\t*desc = NODE::GetInstance().Create(*handle);                                                                                                          \\\n\t\t}                                                                                                                                                         \\\n\t\tEXPORT_API void OnImGui(MaterialNodeDesc *desc, Editor *editor, ImGuiContext *context)                                                                    \\\n\t\t{                                                                                                                                                         \\\n\t\t\tImGui::SetCurrentContext(context);                                                                                                                    \\\n\t\t\tNODE::GetInstance().OnImGui(*desc, editor);                                                                                                           \\\n\t\t}                                                                                                                                                         \\\n\t\tEXPORT_API void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) \\\n\t\t{                                                                                                                                                         \\\n\t\t\tNODE::GetInstance().EmitHLSL(node_desc, graph_desc, manager, context);                                                                               \\\n\t\t}                                                                                                                                                         \\\n\t}\n"
  },
  {
    "path": "Source/Plugin/MaterialNode/Input/RGB.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass RGB : public MaterialNode<RGB>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"RGB\")\n\t\t    .SetCategory(\"Input\")\n\t\t    .Output(handle++, \"Color\", MaterialNodePin::Type::RGB, glm::vec3(0.f));\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tglm::vec3 color = *node_desc.GetPin(\"Color\").variant.Convert<glm::vec3>();\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = float3({}, {}, {});\", node_desc.GetPin(\"Color\").handle, color.x, color.y, color.z));\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(RGB)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Input/SurfaceInteraction.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass SurfaceInteraction : public MaterialNode<SurfaceInteraction>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"SurfaceInteraction\")\n\t\t    .SetCategory(\"Input\")\n\t\t    .Output(handle++, \"Position\", MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"Normal\", MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"UV\", MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"dUVdx\", MaterialNodePin::Type::Float3)\n\t\t    .Output(handle++, \"dUVdy\", MaterialNodePin::Type::Float3);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = surface_interaction.isect.p;\", node_desc.GetPin(\"Position\").handle));\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = surface_interaction.isect.n;\", node_desc.GetPin(\"Normal\").handle));\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = float3(surface_interaction.isect.uv, 0.f);\", node_desc.GetPin(\"UV\").handle));\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = float3(surface_interaction.duvdx, 0.f);\", node_desc.GetPin(\"dUVdx\").handle));\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = float3(surface_interaction.duvdy, 0.f);\", node_desc.GetPin(\"dUVdy\").handle));\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(SurfaceInteraction)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Output/MaterialOutput.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\nusing namespace Ilum;\n\nclass MaterialOutput : public MaterialNode<MaterialOutput>\n{\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"MaterialOutput\")\n\t\t    .SetCategory(\"Output\")\n\t\t    .Input(handle++, \"Surface\", MaterialNodePin::Type::BSDF)\n\t\t    .Input(handle++, \"Volume\", MaterialNodePin::Type::Media);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tauto &surface_bsdf_pin = node_desc.GetPin(\"Surface\");\n\t\tauto &volume_bsdf_pin  = node_desc.GetPin(\"Volume\");\n\n\t\t// Surface BSDF\n\t\tif (graph_desc.HasLink(surface_bsdf_pin.handle))\n\t\t{\n\t\t\tauto &surface_bsdf_node = graph_desc.GetNode(graph_desc.LinkFrom(surface_bsdf_pin.handle));\n\t\t\tsurface_bsdf_node.EmitHLSL(graph_desc, manager, context);\n\t\t\tcontext->output.bsdf = fmt::format(\"S_{}\", surface_bsdf_node.GetPin(graph_desc.LinkFrom(surface_bsdf_pin.handle)).handle);\n\t\t}\n\n\t\t// Volume BSDF\n\t\tif (graph_desc.HasLink(volume_bsdf_pin.handle))\n\t\t{\n\t\t}\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(MaterialOutput)"
  },
  {
    "path": "Source/Plugin/MaterialNode/Texture/ImageTexture.cpp",
    "content": "#include \"IMaterialNode.hpp\"\n\n#include <Resource/Resource/Texture2D.hpp>\n\nusing namespace Ilum;\n\nclass ImageTexture : public MaterialNode<ImageTexture>\n{\n\tstd::vector<const char *> filters = {\n\t    \"Nearest\",\n\t    \"Linear\",\n\t};\n\n\tstd::vector<const char *> address_modes = {\n\t    \"Repeat\",\n\t    \"Mirror Repeat\",\n\t    \"Clamp Edge\",\n\t    \"Clamp Border\",\n\t    \"Mirror Clamp\",\n\t};\n\n\tstruct ImageConfig\n\t{\n\t\tSamplerDesc sampler;\n\t\tchar        filename[200];\n\t};\n\n  public:\n\tvirtual MaterialNodeDesc Create(size_t &handle) override\n\t{\n\t\tMaterialNodeDesc desc;\n\t\treturn desc\n\t\t    .SetHandle(handle++)\n\t\t    .SetName(\"ImageTexture\")\n\t\t    .SetCategory(\"Texture\")\n\t\t    .SetVariant(ImageConfig{})\n\t\t    .Input(handle++, \"UV\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Input(handle++, \"dUVdx\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Input(handle++, \"dUVdy\", MaterialNodePin::Type::RGB, MaterialNodePin::Type::RGB | MaterialNodePin::Type::Float3, glm::vec3(0.f))\n\t\t    .Output(handle++, \"Color\", MaterialNodePin::Type::RGB)\n\t\t    .Output(handle++, \"Alpha\", MaterialNodePin::Type::Float);\n\t}\n\n\tvirtual void OnImGui(MaterialNodeDesc &node_desc, Editor *editor) override\n\t{\n\t\tImageConfig &config = *node_desc.GetVariant().Convert<ImageConfig>();\n\n\t\tauto edit_filter = [&](const std::string &name, size_t *filter) {\n\t\t\tImGui::PushID(name.c_str());\n\t\t\tbool update = false;\n\t\t\tif (ImGui::BeginCombo(\"\", name.c_str()))\n\t\t\t{\n\t\t\t\tfor (size_t i = 0; i < filters.size(); i++)\n\t\t\t\t{\n\t\t\t\t\tconst bool is_selected = i == *filter;\n\t\t\t\t\tif (ImGui::Selectable(filters[i], is_selected))\n\t\t\t\t\t{\n\t\t\t\t\t\t*filter = i;\n\t\t\t\t\t\tupdate  = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (is_selected)\n\t\t\t\t\t{\n\t\t\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tImGui::EndCombo();\n\t\t\t}\n\t\t\tImGui::PopID();\n\t\t\treturn update;\n\t\t};\n\n\t\tauto edit_address_mode = [&](const std::string &name, size_t *address_mode) {\n\t\t\tImGui::PushID(name.c_str());\n\t\t\tbool update = false;\n\t\t\tif (ImGui::BeginCombo(\"\", name.c_str()))\n\t\t\t{\n\t\t\t\tfor (size_t i = 0; i < address_modes.size(); i++)\n\t\t\t\t{\n\t\t\t\t\tconst bool is_selected = i == *address_mode;\n\t\t\t\t\tif (ImGui::Selectable(address_modes[i], is_selected))\n\t\t\t\t\t{\n\t\t\t\t\t\t*address_mode = i;\n\t\t\t\t\t\tupdate        = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (is_selected)\n\t\t\t\t\t{\n\t\t\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tImGui::EndCombo();\n\t\t\t}\n\t\t\tImGui::PopID();\n\t\t\treturn update;\n\t\t};\n\n\t\tRHIFilter filter = config.sampler.min_filter;\n\t\tRHIAddressMode address_mode = config.sampler.address_mode_u;\n\n\t\tif (edit_filter(\"Filter\", (size_t*)(&filter)))\n\t\t{\n\t\t\tconfig.sampler.min_filter = filter;\n\t\t\tconfig.sampler.mag_filter = filter;\n\t\t\tconfig.sampler.mipmap_mode = static_cast<RHIMipmapMode>(filter);\n\t\t}\n\n\t\tif (edit_address_mode(\"Address\", (size_t *) (&address_mode)))\n\t\t{\n\t\t\tconfig.sampler.address_mode_u = address_mode;\n\t\t\tconfig.sampler.address_mode_v = address_mode;\n\t\t\tconfig.sampler.address_mode_w = address_mode;\n\t\t}\n\n\t\tauto *resource_manager = editor->GetRenderer()->GetResourceManager();\n\t\tif (resource_manager->Has<ResourceType::Texture2D>(config.filename))\n\t\t{\n\t\t\tif (ImGui::ImageButton(resource_manager->Get<ResourceType::Texture2D>(config.filename)->GetTexture(), ImVec2(100, 100)))\n\t\t\t{\n\t\t\t\tstd::memset(config.filename, '\\0', 200);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tImGui::Button(config.filename, ImVec2(100.f, 100.f));\n\t\t}\n\n\t\tif (ImGui::BeginDragDropTarget())\n\t\t{\n\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Texture2D\"))\n\t\t\t{\n\t\t\t\tstd::memset(config.filename, '\\0', 200);\n\t\t\t\tstd::memcpy(config.filename, pay_load->Data, std::strlen(static_cast<const char *>(pay_load->Data)));\n\t\t\t}\n\t\t\tImGui::EndDragDropTarget();\n\t\t}\n\t}\n\n\tvirtual void EmitHLSL(const MaterialNodeDesc &node_desc, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) override\n\t{\n\t\tif (context->IsCompiled(node_desc))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tauto *config = node_desc.GetVariant().Convert<ImageConfig>();\n\n\t\tcontext->samplers[fmt::format(\"sampler_{}\", node_desc.GetHandle())] = config->sampler;\n\t\tcontext->textures[fmt::format(\"texture_{}\", node_desc.GetHandle())] = std::string(config->filename);\n\n\t\tstd::map<std::string, std::string> parameters;\n\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"UV\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"dUVdx\"), graph_desc, manager, context);\n\t\tcontext->SetParameter<glm::vec3>(parameters, node_desc.GetPin(\"dUVdy\"), graph_desc, manager, context);\n\n\t\tcontext->variables.emplace_back(fmt::format(\"float4 S_{} = SampleTexture2D(material_data.texture_{}, material_data.sampler_{}, {}.xy, {}.xy, {}.xy);\", node_desc.GetHandle(), node_desc.GetHandle(), node_desc.GetHandle(), parameters[\"UV\"], parameters[\"dUVdx\"], parameters[\"dUVdy\"]));\n\t\tcontext->variables.emplace_back(fmt::format(\"float3 S_{} = S_{}.xyz;\", node_desc.GetPin(\"Color\").handle, node_desc.GetHandle()));\n\t\tcontext->variables.emplace_back(fmt::format(\"float S_{} = S_{}.w;\", node_desc.GetPin(\"Alpha\").handle, node_desc.GetHandle()));\n\t}\n};\n\nCONFIGURATION_MATERIAL_NODE(ImageTexture)"
  },
  {
    "path": "Source/Plugin/MaterialNode/xmake.lua",
    "content": "function add_material_node_plugin(category, name)\n    target(string.format(\"Material.%s.%s\", category, name))\n\n    set_kind(\"shared\")\n    set_group(string.format(\"Plugin/MaterialNode/%s\", category))\n\n    add_rules(\"plugin\")\n    add_files(string.format(\"%s/%s.cpp\", category, name))\n    add_headerfiles(\"IMaterialNode.hpp\")\n    add_includedirs(\"./\")\n    add_deps(\"Core\", \"RHI\", \"Material\", \"Renderer\", \"Editor\", \"Resource\")\n    add_packages(\"imgui\")\n\n    target(\"Plugin\")\n        add_deps(string.format(\"Material.%s.%s\", category, name))\n    target_end()\n\n    target_end()\nend\n\nadd_material_node_plugin(\"Output\", \"MaterialOutput\")\nadd_material_node_plugin(\"Texture\", \"ImageTexture\")\nadd_material_node_plugin(\"Input\", \"RGB\")\nadd_material_node_plugin(\"Input\", \"SurfaceInteraction\")\nadd_material_node_plugin(\"Converter\", \"Calculate\")\nadd_material_node_plugin(\"Converter\", \"VectorCalculate\")\nadd_material_node_plugin(\"Converter\", \"VectorMerge\")\nadd_material_node_plugin(\"Converter\", \"VectorSplit\")\nadd_material_node_plugin(\"Converter\", \"SRGBToLinear\")\nadd_material_node_plugin(\"BSDF\", \"DiffuseMaterial\")\nadd_material_node_plugin(\"BSDF\", \"DielectricMaterial\")\nadd_material_node_plugin(\"BSDF\", \"ConductorMaterial\")\nadd_material_node_plugin(\"BSDF\", \"ThinDielectricMaterial\")\nadd_material_node_plugin(\"BSDF\", \"DisneyMaterial\")\nadd_material_node_plugin(\"BSDF\", \"MixMaterial\")\nadd_material_node_plugin(\"BSDF\", \"MaskedMaterial\")"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Buffer.cpp",
    "content": "#include \"Buffer.hpp\"\n\nnamespace Ilum::CUDA\n{\nBuffer::Buffer(RHIDevice *device, const BufferDesc &desc, HANDLE mem_handle) :\n    RHIBuffer(device, desc)\n{\n\tcudaExternalMemoryHandleDesc cuda_external_memory_handle_desc = {};\n\n#ifdef _WIN64\n\tcuda_external_memory_handle_desc.type                = cudaExternalMemoryHandleTypeOpaqueWin32;\n\tcuda_external_memory_handle_desc.handle.win32.handle = mem_handle;\n#else\n\tcuda_external_memory_handle_desc.type      = cudaExternalMemoryHandleTypeOpaqueFd;\n\tcuda_external_memory_handle_desc.handle.fd = mem_handle;\n#endif\n\tcuda_external_memory_handle_desc.size = desc.size;\n\n\tcudaImportExternalMemory(&m_memory, &cuda_external_memory_handle_desc);\n\n\tcudaExternalMemoryBufferDesc cuda_desc = {};\n\n\tcuda_desc.size = desc.size;\n\tcuda_desc.offset = 0;\n\tcuda_desc.flags  = 0;\n\n\tcudaExternalMemoryGetMappedBuffer((void **) &m_handle, m_memory, &cuda_desc);\n}\n\nBuffer::~Buffer()\n{\n\tcudaFree(m_handle);\n}\n\nvoid Buffer::CopyToDevice(const void *data, size_t size, size_t offset)\n{\n\tcudaMemcpy(m_handle, data, size, cudaMemcpyHostToDevice);\n}\n\nvoid Buffer::CopyToHost(void *data, size_t size, size_t offset)\n{\n\tcudaMemcpy(data, m_handle, size, cudaMemcpyDeviceToHost);\n}\n\nvoid *Buffer::Map()\n{\n\tif (m_desc.memory != RHIMemoryUsage::GPU_Only)\n\t{\n\t\treturn m_handle;\n\t}\n\treturn nullptr;\n}\n\nvoid Buffer::Unmap()\n{\n}\n\nvoid Buffer::Flush(size_t offset, size_t size)\n{\n}\n\nvoid *Buffer::GetHandle() const\n{\n\treturn m_handle;\n}\n\nuint64_t Buffer::GetDeviceAddress() const\n{\n\treturn (uint64_t) m_handle;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Buffer.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Buffer : public RHIBuffer\n{\n  public:\n\tBuffer(RHIDevice *device, const BufferDesc &desc, HANDLE mem_handle);\n\n\tvirtual ~Buffer() override;\n\n\tvirtual void CopyToDevice(const void *data, size_t size, size_t offset = 0) override;\n\n\tvirtual void CopyToHost(void *data, size_t size, size_t offset) override;\n\n\tvirtual void *Map() override;\n\n\tvirtual void Unmap() override;\n\n\tvirtual void Flush(size_t offset, size_t size) override;\n\n\tvoid *GetHandle() const;\n\n\tuint64_t GetDeviceAddress() const;\n\n  private:\n\tvoid *m_handle = nullptr;\n\tcudaExternalMemory_t m_memory = nullptr;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/CUDA.cpp",
    "content": "#include \"Fwd.hpp\"\n\n#include \"Buffer.hpp\"\n#include \"Command.hpp\"\n#include \"Descriptor.hpp\"\n#include \"Device.hpp\"\n#include \"Frame.hpp\"\n#include \"PipelineState.hpp\"\n#include \"Profiler.hpp\"\n#include \"Queue.hpp\"\n#include \"Sampler.hpp\"\n#include \"Shader.hpp\"\n#include \"Synchronization.hpp\"\n#include \"Texture.hpp\"\n\nusing namespace Ilum;\nusing namespace Ilum::CUDA;\n\n#undef CreateSemaphore\n\nextern \"C\"\n{\n\tEXPORT_API RHIDevice *CreateDevice()\n\t{\n\t\treturn new Device;\n\t}\n\n\tEXPORT_API RHIFrame *CreateFrame(Device *device)\n\t{\n\t\treturn new Frame(device);\n\t}\n\n\tEXPORT_API RHIQueue *CreateQueue(Device *device)\n\t{\n\t\treturn new Queue(device);\n\t}\n\n\tEXPORT_API RHITexture *MapTextureVulkanToCUDA(Device *device, const TextureDesc &desc, HANDLE mem_handle, size_t memory_size)\n\t{\n\t\treturn new Texture(device, desc, mem_handle, memory_size);\n\t}\n\n\tEXPORT_API RHIBuffer *MapBufferVulkanToCUDA(Device *device, const BufferDesc &desc, HANDLE mem_handle)\n\t{\n\t\treturn new Buffer(device, desc, mem_handle);\n\t}\n\n\tEXPORT_API RHISemaphore *MapSemaphoreVulkanToCUDA(Device *device, HANDLE handle)\n\t{\n\t\treturn new Semaphore(device, handle);\n\t}\n\n\tEXPORT_API RHIDescriptor *CreateDescriptor(Device *device, const ShaderMeta &meta)\n\t{\n\t\treturn new Descriptor(device, meta);\n\t}\n}"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Command.cpp",
    "content": "#include \"Command.hpp\"\n#include \"Descriptor.hpp\"\n#include \"Device.hpp\"\n#include \"PipelineState.hpp\"\n#include \"Shader.hpp\"\n#include \"Texture.hpp\"\n\nnamespace Ilum::CUDA\n{\nCommand::Command(RHIDevice *device, RHIQueueFamily family) :\n    RHICommand(device, family)\n{\n}\n\nCommand::~Command()\n{\n\tm_calls.clear();\n\tp_descriptor     = nullptr;\n\tp_pipeline_state = nullptr;\n}\n\nvoid Command::SetName(const std::string &name)\n{\n}\n\nvoid Command::Begin()\n{\n\tm_state = CommandState::Recording;\n\tm_calls.clear();\n}\n\nvoid Command::End()\n{\n\tm_state = CommandState::Executable;\n}\n\nvoid Command::BeginMarker(const std::string &name, float r, float g, float b, float a)\n{\n}\n\nvoid Command::EndMarker()\n{\n}\n\nvoid Command::BeginRenderPass(RHIRenderTarget *render_target)\n{\n}\n\nvoid Command::EndRenderPass()\n{\n}\n\nvoid Command::BindVertexBuffer(uint32_t binding, RHIBuffer *vertex_buffer)\n{\n}\n\nvoid Command::BindIndexBuffer(RHIBuffer *index_buffer, bool is_short)\n{\n}\n\nvoid Command::BindDescriptor(RHIDescriptor *descriptor)\n{\n\tp_descriptor = descriptor;\n}\n\nvoid Command::BindPipelineState(RHIPipelineState *pipeline_state)\n{\n\tp_pipeline_state = pipeline_state;\n}\n\nvoid Command::SetViewport(float width, float height, float x, float y)\n{\n}\n\nvoid Command::SetScissor(uint32_t width, uint32_t height, int32_t offset_x, int32_t offset_y)\n{\n}\n\nvoid Command::Dispatch(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z)\n{\n\tassert(p_descriptor != nullptr && p_pipeline_state != nullptr);\n\n\tm_calls.emplace_back([=]() {\n\t\tfor (auto &[stage, shader] : p_pipeline_state->GetShaders())\n\t\t{\n\t\t\tif (stage & RHIShaderStage::Compute)\n\t\t\t{\n\t\t\t\tauto &param_data = static_cast<Descriptor *>(p_descriptor)->GetParamData();\n\t\t\t\tif (shader)\n\t\t\t\t{\n\t\t\t\t\tauto *cuda_kernal     = static_cast<const Shader *>(shader);\n\t\t\t\t\tauto  kernal_function = cuda_kernal->GetFunction();\n\t\t\t\t\tauto  global_param    = cuda_kernal->GetGlobalParam();\n\n\t\t\t\t\tcuMemcpyHtoD(global_param, param_data.data(), param_data.size());\n\n\t\t\t\t\tcuLaunchKernel(\n\t\t\t\t\t    kernal_function,\n\t\t\t\t\t    (thread_x + block_x - 1) / block_x,\n\t\t\t\t\t    (thread_y + block_y - 1) / block_y,\n\t\t\t\t\t    (thread_z + block_z - 1) / block_z,\n\t\t\t\t\t    block_x, block_y, block_z, 0,\n\t\t\t\t\t    static_cast<Device *>(p_device)->GetSteam(), nullptr, nullptr);\n\n\t\t\t\t\tcuMemcpyDtoH(param_data.data(), global_param, param_data.size());\n\n\t\t\t\t\tcudaDeviceSynchronize();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n}\n\nvoid Command::DispatchIndirect(RHIBuffer *buffer, size_t offset)\n{\n}\n\nvoid Command::Draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance)\n{\n}\n\nvoid Command::DrawIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)\n{\n}\n\nvoid Command::DrawIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride)\n{\n}\n\nvoid Command::DrawIndexed(uint32_t index_count, uint32_t instance_count, uint32_t first_index, uint32_t vertex_offset, uint32_t first_instance)\n{\n}\n\nvoid Command::DrawIndexedIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)\n{\n}\n\nvoid Command::DrawIndexedIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride)\n{\n}\n\nvoid Command::DrawMeshTask(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z)\n{\n}\n\nvoid Command::DrawMeshTasksIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)\n{\n}\n\nvoid Command::DrawMeshTasksIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride)\n{\n}\n\nvoid Command::TraceRay(uint32_t width, uint32_t height, uint32_t depth)\n{\n}\n\nvoid Command::CopyBufferToTexture(RHIBuffer *src_buffer, RHITexture *dst_texture, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count)\n{\n}\n\nvoid Command::CopyTextureToBuffer(RHITexture *src_texture, RHIBuffer *dst_buffer, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count)\n{\n}\n\nvoid Command::CopyBufferToBuffer(RHIBuffer *src_buffer, RHIBuffer *dst_buffer, size_t size, size_t src_offset, size_t dst_offset)\n{\n}\n\nvoid Command::GenerateMipmaps(RHITexture *texture, RHIResourceState initial_state, RHIFilter filter)\n{\n}\n\nvoid Command::BlitTexture(RHITexture *src_texture, const TextureRange &src_range, const RHIResourceState &src_state, RHITexture *dst_texture, const TextureRange &dst_range, const RHIResourceState &dst_state, RHIFilter filter)\n{\n}\n\nvoid Command::FillBuffer(RHIBuffer *buffer, RHIResourceState state, size_t size, size_t offset, uint32_t data)\n{\n}\n\nvoid Command::FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, const glm::vec4 &color)\n{\n}\n\nvoid Command::FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, float depth)\n{\n}\n\nvoid Command::ResourceStateTransition(const std::vector<TextureStateTransition> &texture_transitions, const std::vector<BufferStateTransition> &buffer_transitions)\n{\n}\n\nvoid Command::Execute()\n{\n\tfor (auto &task : m_calls)\n\t{\n\t\ttask();\n\t}\n}\n\nvoid Command::Execute(std::function<void(void)> &&task)\n{\n\tm_calls.emplace_back(std::move(task));\n}\n\nvoid Command::EventRecord(cudaEvent_t &cuda_event)\n{\n\tm_calls.emplace_back([&]() {\n\t\tcudaEventRecord(cuda_event, static_cast<Device *>(p_device)->GetSteam());\n\t});\n}\n\nvoid Command::EventElapsedTime(cudaEvent_t begin, cudaEvent_t end, float &time)\n{\n\tm_calls.emplace_back([&]() {\n\t\tcudaEventSynchronize(end);\n\t\tauto error = cudaEventElapsedTime(&time, begin, end);\n\t});\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Command.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Command : public RHICommand\n{\n  public:\n\tCommand(RHIDevice *device, RHIQueueFamily family);\n\n\tvirtual ~Command();\n\n\tvirtual void SetName(const std::string &name);\n\n\tvirtual void Begin() override;\n\tvirtual void End() override;\n\n\tvirtual void BeginMarker(const std::string &name, float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) override;\n\tvirtual void EndMarker() override;\n\n\tvirtual void BeginRenderPass(RHIRenderTarget *render_target) override;\n\tvirtual void EndRenderPass() override;\n\n\tvirtual void BindVertexBuffer(uint32_t binding, RHIBuffer *vertex_buffer) override;\n\tvirtual void BindIndexBuffer(RHIBuffer *index_buffer, bool is_short = false) override;\n\n\tvirtual void BindDescriptor(RHIDescriptor *descriptor) override;\n\tvirtual void BindPipelineState(RHIPipelineState *pipeline_state) override;\n\n\tvirtual void SetViewport(float width, float height, float x = 0.f, float y = 0.f) override;\n\tvirtual void SetScissor(uint32_t width, uint32_t height, int32_t offset_x = 0, int32_t offset_y = 0) override;\n\n\t// Drawcall\n\tvirtual void Dispatch(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z) override;\n\tvirtual void DispatchIndirect(RHIBuffer *buffer, size_t offset) override;\n\n\tvirtual void Draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance) override;\n\tvirtual void DrawIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride) override;\n\tvirtual void DrawIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) override;\n\n\tvirtual void DrawIndexed(uint32_t index_count, uint32_t instance_count, uint32_t first_index, uint32_t vertex_offset, uint32_t first_instance) override;\n\tvirtual void DrawIndexedIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride) override;\n\tvirtual void DrawIndexedIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) override;\n\n\tvirtual void DrawMeshTask(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z) override;\n\tvirtual void DrawMeshTasksIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride) override;\n\tvirtual void DrawMeshTasksIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) override;\n\n\tvirtual void TraceRay(uint32_t width, uint32_t height, uint32_t depth) override;\n\n\t// Resource Copy\n\tvirtual void CopyBufferToTexture(RHIBuffer *src_buffer, RHITexture *dst_texture, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count) override;\n\tvirtual void CopyTextureToBuffer(RHITexture *src_texture, RHIBuffer *dst_buffer, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count) override;\n\tvirtual void CopyBufferToBuffer(RHIBuffer *src_buffer, RHIBuffer *dst_buffer, size_t size, size_t src_offset, size_t dst_offset) override;\n\n\tvirtual void GenerateMipmaps(RHITexture *texture, RHIResourceState initial_state, RHIFilter filter) override;\n\tvirtual void BlitTexture(RHITexture *src_texture, const TextureRange &src_range, const RHIResourceState &src_state, RHITexture *dst_texture, const TextureRange &dst_range, const RHIResourceState &dst_state, RHIFilter filter = RHIFilter::Linear) override;\n\n\tvirtual void FillBuffer(RHIBuffer *buffer, RHIResourceState state, size_t size, size_t offset, uint32_t data) override;\n\tvirtual void FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, const glm::vec4 &color) override;\n\tvirtual void FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, float depth) override;\n\n\t// Resource Barrier\n\tvirtual void ResourceStateTransition(const std::vector<TextureStateTransition> &texture_transitions, const std::vector<BufferStateTransition> &buffer_transitions) override;\n\n\tvoid Execute();\n\n\tvoid Execute(std::function<void(void)> &&task);\n\n\tvoid EventRecord(cudaEvent_t &cuda_event);\n\n\tvoid EventElapsedTime(cudaEvent_t begin, cudaEvent_t end, float &time);\n\n  private:\n\tRHIDescriptor    *p_descriptor     = nullptr;\n\tRHIPipelineState *p_pipeline_state = nullptr;\n\n\tstd::vector<std::function<void()>> m_calls;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Descriptor.cpp",
    "content": "#include \"Descriptor.hpp\"\n#include \"Buffer.hpp\"\n#include \"Texture.hpp\"\n\nnamespace Ilum::CUDA\n{\nDescriptor::Descriptor(RHIDevice *device, const ShaderMeta &meta) :\n    RHIDescriptor(device, meta)\n{\n\tstd::map<size_t, std::string> resource_orders;\n\n\tfor (auto &constant : meta.constants)\n\t{\n\t\tresource_orders[constant.spirv_id] = constant.name;\n\t\tm_resource_sizes[constant.name]    = constant.size;\n\t}\n\tfor (auto &descriptor : meta.descriptors)\n\t{\n\t\tresource_orders[descriptor.spirv_id] = descriptor.name;\n\t\tm_resource_sizes[descriptor.name]    = sizeof(void *);\n\t\tif (descriptor.type == DescriptorType::StructuredBuffer)\n\t\t{\n\t\t\tm_resource_sizes[descriptor.name] += sizeof(size_t);\n\t\t}\n\t\tm_resource_type[descriptor.name] = (size_t) descriptor.type;\n\t}\n\n\tsize_t offset = 0;\n\tfor (auto &[spirv_id, name] : resource_orders)\n\t{\n\t\tm_resource_offsets[name] = offset;\n\t\toffset += m_resource_sizes[name];\n\t}\n\n\tm_param_data.resize(offset);\n}\n\nRHIDescriptor &Descriptor::BindTexture(const std::string &name, RHITexture *texture, RHITextureDimension dimension)\n{\n\tif (m_resource_offsets.find(name) == m_resource_offsets.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t   offset         = m_resource_offsets[name];\n\tconst uint64_t* texture_handle = nullptr;\n\tif (m_resource_type[name] == (size_t) DescriptorType::TextureUAV)\n\t{\n\t\ttexture_handle = static_cast<Texture *>(texture)->GetSurfaceHostHandle().data();\n\t}\n\telse if (m_resource_type[name] == (size_t) DescriptorType::TextureSRV)\n\t{\n\t\ttexture_handle = static_cast<Texture *>(texture)->GetTextureHandle();\n\t}\n\n\tstd::memcpy(m_param_data.data() + offset, texture_handle, sizeof(uint64_t));\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindTexture(const std::string &name, RHITexture *texture, const TextureRange &range)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindTexture(const std::string &name, const std::vector<RHITexture *> &textures, RHITextureDimension dimension)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindSampler(const std::string &name, RHISampler *sampler)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindSampler(const std::string &name, const std::vector<RHISampler *> &samplers)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindBuffer(const std::string &name, RHIBuffer *buffer)\n{\n\tif (m_resource_offsets.find(name) == m_resource_offsets.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t offset        = m_resource_offsets[name];\n\tsize_t stride        = static_cast<Buffer *>(buffer)->GetDesc().stride;\n\tvoid  *buffer_handle = static_cast<Buffer *>(buffer)->GetHandle();\n\tstd::memcpy(m_param_data.data() + offset, &buffer_handle, sizeof(buffer_handle));\n\tif (m_resource_type[name] == (size_t) DescriptorType::StructuredBuffer)\n\t{\n\t\tstd::memcpy(m_param_data.data() + offset + sizeof(buffer_handle), &stride, sizeof(stride));\n\t}\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindBuffer(const std::string &name, RHIBuffer *buffer, size_t offset, size_t range)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindBuffer(const std::string &name, const std::vector<RHIBuffer *> &buffers)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindConstant(const std::string &name, const void *constant)\n{\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindAccelerationStructure(const std::string &name, RHIAccelerationStructure *acceleration_structure)\n{\n\treturn *this;\n}\n\nstd::vector<uint8_t> &Descriptor::GetParamData()\n{\n\treturn m_param_data;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Descriptor.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Descriptor : public RHIDescriptor\n{\n  public:\n\tDescriptor(RHIDevice *device, const ShaderMeta &meta);\n\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, RHITexture *texture, RHITextureDimension dimension) override;\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, RHITexture *texture, const TextureRange &range) override;\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, const std::vector<RHITexture *> &textures, RHITextureDimension dimension) override;\n\n\tvirtual RHIDescriptor &BindSampler(const std::string &name, RHISampler *sampler) override;\n\tvirtual RHIDescriptor &BindSampler(const std::string &name, const std::vector<RHISampler *> &samplers) override;\n\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, RHIBuffer *buffer) override;\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, RHIBuffer *buffer, size_t offset, size_t range) override;\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, const std::vector<RHIBuffer *> &buffers) override;\n\n\tvirtual RHIDescriptor &BindConstant(const std::string &name, const void *constant) override;\n\n\tvirtual RHIDescriptor &BindAccelerationStructure(const std::string &name, RHIAccelerationStructure *acceleration_structure) override;\n\n\tstd::vector<uint8_t> &GetParamData();\n\n  private:\n\tstd::map<std::string, size_t> m_resource_type;\n\tstd::map<std::string, size_t> m_resource_offsets;\n\tstd::map<std::string, size_t> m_resource_sizes;\n\tstd::vector<uint8_t>          m_param_data;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Device.cpp",
    "content": "#include \"Device.hpp\"\n\n#include <cuda_runtime.h>\n\nnamespace Ilum::CUDA\n{\nDevice::Device() :\n    RHIDevice(\"CUDA\")\n{\n\tLOG_INFO(\"Initializing RHI backend CUDA...\");\n\n\tcudaDeviceProp prop;\n\tcudaGetDeviceProperties(&prop, 0);\n\tm_name = prop.name;\n\n\tcuInit(0);\n\tcuDeviceGet(&m_device, 0);\n\tcuCtxCreate(&m_context, 0, m_device);\n\tcudaStreamCreate(&m_steam);\n}\n\nDevice::~Device()\n{\n\tcuCtxDestroy(m_context);\n}\n\nvoid Device::WaitIdle()\n{\n\tcudaStreamSynchronize(m_steam);\n}\n\nbool Device::IsFeatureSupport(RHIFeature feature)\n{\n\treturn false;\n}\n\ncudaStream_t Device::GetSteam() const\n{\n\treturn m_steam;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Device.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Device : public RHIDevice\n{\n  public:\n\tDevice();\n\n\t~Device();\n\n\tvirtual void WaitIdle() override;\n\n\tvirtual bool IsFeatureSupport(RHIFeature feature) override;\n\n\tcudaStream_t GetSteam() const;\n\n  private:\n\tCUcontext m_context;\n\tCUdevice  m_device;\n\tcudaStream_t m_steam;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Frame.cpp",
    "content": "#include \"Frame.hpp\"\n#include \"Command.hpp\"\n\nnamespace Ilum::CUDA\n{\nFrame::Frame(RHIDevice *device):\n    RHIFrame(device)\n{\n}\n\nRHIFence *Frame::AllocateFence()\n{\n\treturn nullptr;\n}\n\nRHISemaphore *Frame::AllocateSemaphore()\n{\n\treturn nullptr;\n}\n\nRHICommand *Frame::AllocateCommand(RHIQueueFamily family)\n{\n\twhile (m_current_cmd >= m_cmds.size())\n\t{\n\t\tm_cmds.emplace_back(std::make_unique<Command>(p_device, family));\n\t}\n\n\treturn m_cmds[m_current_cmd++].get();\n}\n\nvoid Frame::Reset()\n{\n\tm_current_cmd = 0;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Frame.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Command;\n\nclass Frame : public RHIFrame\n{\n  public:\n\tFrame(RHIDevice *device);\n\n\t~Frame() = default;\n\n\tvirtual RHIFence *AllocateFence() override;\n\n\tvirtual RHISemaphore *AllocateSemaphore() override;\n\n\tvirtual RHICommand *AllocateCommand(RHIQueueFamily family) override;\n\n\tvirtual RHIDescriptor* AllocateDescriptor(const ShaderMeta& meta) override\n\t{\n\t\treturn nullptr;\n\t}\n\n\tvoid Reset();\n\n  private:\n\tstd::vector<std::unique_ptr<Command>> m_cmds;\n\tuint32_t                              m_current_cmd = 0;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Fwd.hpp",
    "content": "#pragma once\n\n#include <array>\n#include <map>\n#include <memory>\n#include <optional>\n#include <vector>\n\n#include <volk.h>\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#include <Core/Core.hpp>\n\n#include <RHI/RHIAccelerationStructure.hpp>\n#include <RHI/RHIBuffer.hpp>\n#include <RHI/RHICommand.hpp>\n#include <RHI/RHIDefinitions.hpp>\n#include <RHI/RHIDescriptor.hpp>\n#include <RHI/RHIDevice.hpp>\n#include <RHI/RHIFrame.hpp>\n#include <RHI/RHIPipelineState.hpp>\n#include <RHI/RHIProfiler.hpp>\n#include <RHI/RHIQueue.hpp>\n#include <RHI/RHIRenderTarget.hpp>\n#include <RHI/RHISampler.hpp>\n#include <RHI/RHIShader.hpp>\n#include <RHI/RHISwapchain.hpp>\n#include <RHI/RHISynchronization.hpp>\n#include <RHI/RHITexture.hpp>\n\n#ifdef _WIN64\n#\tinclude <Windows.h>\n#endif        // _WIN64\n\nnamespace Ilum\n{\nnamespace CUDA\n{\nclass Buffer;\nclass Command;\nclass Descriptor;\nclass Device;\nclass Frame;\nclass PipelineState;\nclass Profiler;\nclass Queue;\nclass Sampler;\nclass Shader;\nclass Fence;\nclass Semaphore;\nclass Texture;\n}        // namespace CUDA\n}        // namespace Ilum"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/PipelineState.cpp",
    "content": "#include \"PipelineState.hpp\"\n\nnamespace Ilum::CUDA\n{\nPipelineState::PipelineState(RHIDevice *device) :\n    RHIPipelineState(device)\n{\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/PipelineState.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass PipelineState : public RHIPipelineState\n{\n  public:\n\tPipelineState(RHIDevice *device);\n\n\t~PipelineState() = default;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Profiler.cpp",
    "content": "#include \"Profiler.hpp\"\n#include \"Device.hpp\"\n#include \"Command.hpp\"\n\nnamespace Ilum::CUDA\n{\nProfiler::Profiler(RHIDevice *device, uint32_t frame_count) :\n    RHIProfiler(device, frame_count)\n{\n\tm_start_events.resize(frame_count);\n\tm_end_events.resize(frame_count);\n\n\tfor (uint32_t i = 0; i < frame_count; i++)\n\t{\n\t\tcudaEventCreate(&m_start_events[i]);\n\t\tcudaEventCreate(&m_end_events[i]);\n\t}\n}\n\nProfiler::~Profiler()\n{\n\tfor (uint32_t i = 0; i < m_frame_count; i++)\n\t{\n\t\tcudaEventDestroy(m_start_events[i]);\n\t\tcudaEventDestroy(m_end_events[i]);\n\t}\n}\n\nvoid Profiler::Begin(RHICommand *cmd_buffer, uint32_t frame_index)\n{\n\tm_current_index = frame_index;\n\n\tm_state.thread_id = std::this_thread::get_id();\n\n\tcudaEventSynchronize(m_end_events[m_current_index]);\n\tcudaEventElapsedTime(&m_state.gpu_time, m_start_events[m_current_index], m_end_events[m_current_index]);\n\n\tstatic_cast<Command *>(cmd_buffer)->EventRecord(m_start_events[m_current_index]);\n\tm_state.cpu_time = std::chrono::duration<float, std::milli>(m_state.cpu_end - m_state.cpu_start).count();\n\n\tm_state.cpu_start = std::chrono::high_resolution_clock::now();\n}\n\nvoid Profiler::End(RHICommand *cmd_buffer)\n{\n\tstatic_cast<Command *>(cmd_buffer)->EventRecord(m_end_events[m_current_index]);\n\n\tm_state.cpu_end = std::chrono::high_resolution_clock::now();\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Profiler.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Profiler : public RHIProfiler\n{\n  public:\n\tProfiler(RHIDevice *device, uint32_t frame_count);\n\n\tvirtual ~Profiler() override;\n\n\tvirtual void Begin(RHICommand *cmd_buffer, uint32_t frame_index) override;\n\n\tvirtual void End(RHICommand *cmd_buffer) override;\n\n  private:\n\tstd::vector<cudaEvent_t> m_start_events;\n\tstd::vector<cudaEvent_t> m_end_events;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Queue.cpp",
    "content": "#include \"Queue.hpp\"\n#include \"Command.hpp\"\n#include \"Synchronization.hpp\"\n\nnamespace Ilum::CUDA\n{\nQueue::Queue(RHIDevice *device) :\n    RHIQueue(device)\n{\n}\n\nvoid Queue::Wait()\n{\n\tcudaDeviceSynchronize();\n}\n\nvoid Queue::Execute(RHIQueueFamily family, const std::vector<SubmitInfo> &submit_infos, RHIFence *fence)\n{\n\tfor (auto &submit_info : submit_infos)\n\t{\n\t\tfor (auto &wait_semaphore : submit_info.wait_semaphores)\n\t\t{\n\t\t\tstatic_cast<Semaphore *>(wait_semaphore)->Wait();\n\t\t}\n\t\tfor (auto &cmd_buffer : submit_info.cmd_buffers)\n\t\t{\n\t\t\tstatic_cast<Command *>(cmd_buffer)->Execute();\n\t\t}\n\t\tfor (auto &signal_semaphore : submit_info.signal_semaphores)\n\t\t{\n\t\t\tstatic_cast<Semaphore *>(signal_semaphore)->Signal();\n\t\t}\n\t}\n}\n\nvoid Queue::Execute(RHICommand *cmd_buffer)\n{\n\tstatic_cast<Command *>(cmd_buffer)->Execute();\n\tcudaDeviceSynchronize();\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Queue.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Queue : public RHIQueue\n{\n  public:\n\tQueue(RHIDevice *device);\n\n\t~Queue() = default;\n\n\tvirtual void Execute(RHIQueueFamily family, const std::vector<SubmitInfo> &submit_infos, RHIFence *fence) override;\n\n\t// Immediate execution\n\tvirtual void Execute(RHICommand *cmd_buffer) override;\n\n\tvirtual void Wait() override;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Sampler.cpp",
    "content": "#include \"Sampler.hpp\"\n\nnamespace Ilum::CUDA\n{\nSampler::Sampler(RHIDevice *device, const SamplerDesc &desc):\n    RHISampler(device, desc)\n{\n}\n\nvoid *Sampler::GetHandle() const\n{\n\treturn nullptr;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Sampler.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Sampler : public RHISampler\n{\n  public:\n\tSampler(RHIDevice *device, const SamplerDesc &desc);\n\n\tvirtual ~Sampler() = default;\n\n\tvoid *GetHandle() const;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Shader.cpp",
    "content": "#include \"Shader.hpp\"\n\nnamespace Ilum::CUDA\n{\nShader::Shader(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source):\n    RHIShader(device, entry_point, source)\n{\n\tstd::string ptx;\n\tptx.resize(source.size());\n\tstd::memcpy(ptx.data(), source.data(), source.size());\n\n\tcuModuleLoadData(&m_module, ptx.c_str());\n\tcuModuleGetFunction(&m_function, m_module, entry_point.c_str());\n\tcuModuleGetGlobal(&m_global_param, NULL, m_module, \"SLANG_globalParams\");\n}\n\nShader::~Shader()\n{\n\tcuModuleUnload(m_module);\n}\n\nCUfunction Shader::GetFunction() const\n{\n\treturn m_function;\n}\n\nCUdeviceptr Shader::GetGlobalParam() const\n{\n\treturn m_global_param;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Shader.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Shader: public RHIShader\n{\n  public:\n\tShader(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source);\n\n\t~Shader();\n\n\tCUfunction GetFunction() const;\n\n\tCUdeviceptr GetGlobalParam() const;\n\n  private:\n\tCUmodule    m_module       = {};\n\tCUfunction  m_function     = {};\n\tCUdeviceptr m_global_param = {};\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Synchronization.cpp",
    "content": "#include \"Synchronization.hpp\"\n#include \"Device.hpp\"\n\nnamespace Ilum::CUDA\n{\n\nSemaphore::Semaphore(RHIDevice *device, HANDLE handle) :\n    RHISemaphore(device)\n{\n\tcudaExternalSemaphoreHandleDesc external_semaphore_handle_desc = {};\n\n#ifdef _WIN64\n\texternal_semaphore_handle_desc.type = cudaExternalSemaphoreHandleTypeOpaqueWin32;\n\n\texternal_semaphore_handle_desc.handle.win32.handle = handle;\n#else\n\texternal_semaphore_handle_desc.type      = cudaExternalSemaphoreHandleTypeOpaqueFd;\n\texternal_semaphore_handle_desc.handle.fd = handle;\n#endif\n\texternal_semaphore_handle_desc.flags = 0;\n\n\tcudaImportExternalSemaphore(&m_handle, &external_semaphore_handle_desc);\n}\n\nSemaphore::~Semaphore()\n{\n\tcudaDestroyExternalSemaphore(m_handle);\n}\n\nvoid Semaphore::SetName(const std::string &name)\n{\n}\n\nvoid Semaphore::Signal()\n{\n\tcudaExternalSemaphoreSignalParams params = {};\n\n\tparams.params.fence.value = 0;\n\tparams.flags              = 0;\n\n\tcudaSignalExternalSemaphoresAsync(&m_handle, &params, 1, static_cast<Device*>(p_device)->GetSteam());\n}\n\nvoid Semaphore::Wait()\n{\n\tcudaExternalSemaphoreWaitParams params = {};\n\n\tparams.params.fence.value = 0;\n\tparams.flags              = 0;\n\n\tcudaWaitExternalSemaphoresAsync(&m_handle, &params, 1, static_cast<Device *>(p_device)->GetSteam());\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Synchronization.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Semaphore : public RHISemaphore\n{\n  public:\n\tSemaphore(RHIDevice *device, HANDLE handle);\n\n\t~Semaphore();\n\n\tvirtual void SetName(const std::string &name) override;\n\n\tvoid Signal();\n\n\tvoid Wait();\n\n  private:\n\tcudaExternalSemaphore_t m_handle = nullptr;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Texture.cpp",
    "content": "#include \"Texture.hpp\"\n\nnamespace Ilum::CUDA\n{\ncudaChannelFormatDesc GetCUDAChannelFormatDesc(RHIFormat format)\n{\n\tcudaChannelFormatDesc desc = {};\n\n\tswitch (format)\n\t{\n\t\tcase RHIFormat::Undefined:\n\t\t\tdesc = cudaChannelFormatDesc{0, 0, 0, 0, cudaChannelFormatKindNone};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 0, 0, 0, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 0, 0, 0, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 0, 0, 0, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::R8G8B8A8_UNORM:\n\t\t\tdesc = cudaChannelFormatDesc{8, 8, 8, 8, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::B8G8R8A8_UNORM:\n\t\t\tdesc = cudaChannelFormatDesc{8, 8, 8, 8, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 0, 0, 0, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 0, 0, 0, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 0, 0, 0, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::D32_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 0, 0, 0, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16G16_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 16, 0, 0, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16G16_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 16, 0, 0, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16G16_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 16, 0, 0, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16G16B16A16_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 16, 16, 16, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16G16B16A16_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 16, 16, 16, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R16G16B16A16_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{16, 16, 16, 16, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 0, 0, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 0, 0, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 0, 0, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32B32_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 32, 0, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32B32_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 32, 0, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32B32_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 32, 0, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32B32A32_UINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 32, 32, cudaChannelFormatKindUnsigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32B32A32_SINT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 32, 32, cudaChannelFormatKindSigned};\n\t\t\tbreak;\n\t\tcase RHIFormat::R32G32B32A32_FLOAT:\n\t\t\tdesc = cudaChannelFormatDesc{32, 32, 32, 32, cudaChannelFormatKindFloat};\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn desc;\n}\n\nTexture::Texture(RHIDevice *device, const TextureDesc &desc, HANDLE mem_handle, size_t memory_size) :\n    RHITexture(device, desc), m_memory_size(memory_size)\n{\n\tcudaExternalMemoryHandleDesc cuda_external_memory_handle_desc = {};\n\n#ifdef _WIN64\n\tcuda_external_memory_handle_desc.type                = cudaExternalMemoryHandleTypeOpaqueWin32;\n\tcuda_external_memory_handle_desc.handle.win32.handle = mem_handle;\n#else\n\tcuda_external_memory_handle_desc.type      = cudaExternalMemoryHandleTypeOpaqueFd;\n\tcuda_external_memory_handle_desc.handle.fd = mem_handle;\n#endif\n\tcuda_external_memory_handle_desc.size = memory_size;\n\n\tcudaImportExternalMemory(&m_external_memory, &cuda_external_memory_handle_desc);\n\n\tcudaExtent            extent = {desc.width, desc.height, desc.depth - 1};\n\tcudaChannelFormatDesc format = GetCUDAChannelFormatDesc(desc.format);\n\n\tcudaExternalMemoryMipmappedArrayDesc cuda_external_memory_mipmapped_array_desc = {};\n\n\tcuda_external_memory_mipmapped_array_desc.offset     = 0;\n\tcuda_external_memory_mipmapped_array_desc.formatDesc = format;\n\tcuda_external_memory_mipmapped_array_desc.extent     = extent;\n\tcuda_external_memory_mipmapped_array_desc.flags      = 0;\n\tcuda_external_memory_mipmapped_array_desc.numLevels  = desc.mips;\n\n\tcudaExternalMemoryGetMappedMipmappedArray(&m_mipmapped_array, m_external_memory, &cuda_external_memory_mipmapped_array_desc);\n\n\tfor (uint32_t mip_level = 0; mip_level < desc.mips; mip_level++)\n\t{\n\t\tcudaArray_t cuda_mip_level_array = {}, cuda_mip_level_array_orig = {};\n\n\t\tcudaResourceDesc resource_desc = {};\n\n\t\tcudaGetMipmappedArrayLevel(&cuda_mip_level_array, m_mipmapped_array, mip_level);\n\n\t\tuint32_t width  = (desc.width >> mip_level) ? (desc.width >> mip_level) : 1;\n\t\tuint32_t height = (desc.height >> mip_level) ? (desc.height >> mip_level) : 1;\n\t\tcudaMemcpy2DArrayToArray(cuda_mip_level_array_orig, 0, 0, cuda_mip_level_array, 0, 0, width * static_cast<size_t>(format.x + format.y + format.z + format.w) / 8ull, height, cudaMemcpyDeviceToDevice);\n\n\t\tresource_desc.resType         = cudaResourceTypeArray;\n\t\tresource_desc.res.array.array = cuda_mip_level_array;\n\n\t\tcudaSurfaceObject_t surface = {};\n\t\tcudaCreateSurfaceObject(&surface, &resource_desc);\n\n\t\tm_surfaces.push_back(surface);\n\t}\n\n\tcudaResourceDesc cuda_resource_desc = {};\n\n\tcuda_resource_desc.resType           = cudaResourceTypeMipmappedArray;\n\tcuda_resource_desc.res.mipmap.mipmap = m_mipmapped_array;\n\n\tcudaTextureDesc cuda_texture_desc = {};\n\n\tcuda_texture_desc.normalizedCoords    = true;\n\tcuda_texture_desc.filterMode          = cudaFilterModeLinear;\n\tcuda_texture_desc.mipmapFilterMode    = cudaFilterModeLinear;\n\tcuda_texture_desc.addressMode[0]      = cudaAddressModeClamp;\n\tcuda_texture_desc.addressMode[1]      = cudaAddressModeClamp;\n\tcuda_texture_desc.maxMipmapLevelClamp = static_cast<float>(m_desc.mips) - 1.f;\n\tcuda_texture_desc.readMode            = cudaReadModeElementType;\n\n\tcudaCreateTextureObject(&m_texture_handle, &cuda_resource_desc, &cuda_texture_desc, nullptr);\n\n\tcudaMalloc((void **) &m_surface_list, sizeof(cudaSurfaceObject_t) * m_desc.mips);\n\tcudaMemcpy(m_surface_list, m_surfaces.data(), sizeof(cudaSurfaceObject_t) * m_desc.mips, cudaMemcpyHostToDevice);\n}\n\nTexture::~Texture()\n{\n\tp_device->WaitIdle();\n\n\tcudaDestroyTextureObject(m_texture_handle);\n\n\tfor (auto &surface : m_surfaces)\n\t{\n\t\tcudaDestroySurfaceObject(surface);\n\t}\n\tm_surfaces.clear();\n\n\tif (m_surface_list)\n\t{\n\t\tcudaFree(m_surface_list);\n\t}\n\n\tif (m_external_memory)\n\t{\n\t\tcudaFreeMipmappedArray(m_mipmapped_array);\n\t\tcudaDestroyExternalMemory(m_external_memory);\n\t}\n}\n\n size_t Texture::GetMemorySize() const\n{\n\t return m_memory_size;\n }\n\nconst cudaSurfaceObject_t *Texture::GetSurfaceDeviceHandle() const\n{\n\treturn m_surface_list;\n}\n\nconst std::vector<cudaSurfaceObject_t> &Texture::GetSurfaceHostHandle() const\n{\n\treturn m_surfaces;\n}\n\nconst cudaTextureObject_t *Texture::GetTextureHandle() const\n{\n\treturn &m_texture_handle;\n}\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/CUDA/Texture.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::CUDA\n{\nclass Texture : public RHITexture\n{\n  public:\n\tTexture(RHIDevice *device, const TextureDesc &desc, HANDLE mem_handle, size_t memory_size);\n\n\tvirtual ~Texture() override;\n\n\tvirtual size_t GetMemorySize() const override;\n\n\tconst cudaSurfaceObject_t *GetSurfaceDeviceHandle() const;\n\n\tconst std::vector<cudaSurfaceObject_t> &GetSurfaceHostHandle() const;\n\n\tconst cudaTextureObject_t *GetTextureHandle() const;\n\n  private:\n\tcudaTextureObject_t m_texture_handle;\n\n\tstd::vector<cudaSurfaceObject_t> m_surfaces;\n\tcudaSurfaceObject_t             *m_surface_list = nullptr;\n\n\tcudaExternalMemory_t m_external_memory      = nullptr;\n\tcudaMipmappedArray_t m_mipmapped_array      = nullptr;\n\n\tsize_t m_memory_size = 0;\n\n\tbool m_is_backbuffer = false;\n};\n}        // namespace Ilum::CUDA"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/AccelerationStructure.cpp",
    "content": "#include \"AccelerationStructure.hpp\"\n#include \"Buffer.hpp\"\n#include \"Command.hpp\"\n#include \"Device.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstatic inline size_t Align(size_t x, size_t alignment)\n{\n\treturn (x + (alignment - 1)) & ~(alignment - 1);\n}\n\nAccelerationStructure::AccelerationStructure(RHIDevice *device) :\n    RHIAccelerationStructure(device)\n{\n}\n\nAccelerationStructure ::~AccelerationStructure()\n{\n\tif (m_handle)\n\t{\n\t\tp_device->WaitIdle();\n\t\tvkDestroyAccelerationStructureKHR(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t\tm_handle = VK_NULL_HANDLE;\n\t}\n}\n\nvoid AccelerationStructure::Update(RHICommand *cmd_buffer, const TLASDesc &desc)\n{\n\tstd::vector<VkAccelerationStructureInstanceKHR> instances;\n\tinstances.reserve(desc.instances.size());\n\n\tfor (auto &instance : desc.instances)\n\t{\n\t\tVkAccelerationStructureInstanceKHR vk_instance = {};\n\n\t\tauto transform = glm::mat3x4(glm::transpose(instance.transform));\n\n\t\tstd::memcpy(&vk_instance.transform, &transform, sizeof(VkTransformMatrixKHR));\n\t\tvk_instance.instanceCustomIndex                    = 0;\n\t\tvk_instance.mask                                   = 0xFF;\n\t\tvk_instance.instanceShaderBindingTableRecordOffset = instance.material_id;\n\t\tvk_instance.flags                                  = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;\n\t\tvk_instance.accelerationStructureReference         = static_cast<AccelerationStructure *>(instance.blas)->GetDeviceAddress();\n\n\t\tinstances.emplace_back(std::move(vk_instance));\n\t}\n\n\tif (!m_instance_buffer || m_instance_buffer->GetDesc().size < instances.size() * sizeof(VkAccelerationStructureInstanceKHR))\n\t{\n\t\tm_instance_buffer = std::make_unique<Buffer>(\n\t\t    p_device,\n\t\t    BufferDesc{\n\t\t        \"TLAS Instance Buffer\",\n\t\t        RHIBufferUsage::AccelerationStructure | RHIBufferUsage::Transfer,\n\t\t        RHIMemoryUsage::CPU_TO_GPU,\n\t\t        instances.size() * sizeof(VkAccelerationStructureInstanceKHR)});\n\t}\n\n\tm_instance_buffer->CopyToDevice(instances.data(), instances.size() * sizeof(VkAccelerationStructureInstanceKHR), 0);\n\n\tVkAccelerationStructureGeometryKHR as_geometry    = {};\n\tas_geometry.sType                                 = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;\n\tas_geometry.geometryType                          = VK_GEOMETRY_TYPE_INSTANCES_KHR;\n\tas_geometry.flags                                 = VK_GEOMETRY_OPAQUE_BIT_KHR;\n\tas_geometry.geometry.instances.sType              = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;\n\tas_geometry.geometry.instances.arrayOfPointers    = VK_FALSE;\n\tas_geometry.geometry.instances.data.deviceAddress = m_instance_buffer->GetDeviceAddress();\n\n\tVkAccelerationStructureBuildRangeInfoKHR range_info = {};\n\trange_info.primitiveCount                           = static_cast<uint32_t>(desc.instances.size());\n\n\tUpdate(cmd_buffer, as_geometry, range_info, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR);\n\n\tif (!desc.name.empty())\n\t{\n\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\tinfo.pObjectName                   = desc.name.c_str();\n\t\tinfo.objectHandle                  = (uint64_t) m_handle;\n\t\tinfo.objectType                    = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR;\n\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t}\n}\n\nvoid AccelerationStructure::Update(RHICommand *cmd_buffer, const BLASDesc &desc)\n{\n\tVkAccelerationStructureGeometryKHR as_geometry             = {};\n\tas_geometry.sType                                          = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;\n\tas_geometry.flags                                          = VK_GEOMETRY_OPAQUE_BIT_KHR;\n\tas_geometry.geometryType                                   = VK_GEOMETRY_TYPE_TRIANGLES_KHR;\n\tas_geometry.geometry.triangles.sType                       = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;\n\tas_geometry.geometry.triangles.vertexFormat                = VK_FORMAT_R32G32B32_SFLOAT;\n\tas_geometry.geometry.triangles.vertexData.deviceAddress    = static_cast<Buffer *>(desc.vertex_buffer)->GetDeviceAddress();\n\tas_geometry.geometry.triangles.maxVertex                   = desc.vertices_count;\n\tas_geometry.geometry.triangles.vertexStride                = 64;        // 4 x vec4\n\tas_geometry.geometry.triangles.indexType                   = VK_INDEX_TYPE_UINT32;\n\tas_geometry.geometry.triangles.indexData.deviceAddress     = static_cast<Buffer *>(desc.index_buffer)->GetDeviceAddress();\n\tas_geometry.geometry.triangles.transformData.deviceAddress = 0;\n\tas_geometry.geometry.triangles.transformData.hostAddress   = nullptr;\n\n\tVkAccelerationStructureBuildRangeInfoKHR range_info = {};\n\n\trange_info.primitiveCount  = desc.indices_count / 3;\n\trange_info.primitiveOffset = desc.indices_offset * sizeof(uint32_t);\n\trange_info.firstVertex     = desc.vertices_offset;\n\trange_info.transformOffset = 0;\n\n\tUpdate(cmd_buffer, as_geometry, range_info, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR);\n\n\tif (!desc.name.empty())\n\t{\n\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\tinfo.pObjectName                   = desc.name.c_str();\n\t\tinfo.objectHandle                  = (uint64_t) m_handle;\n\t\tinfo.objectType                    = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR;\n\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t}\n}\n\nVkAccelerationStructureKHR AccelerationStructure::GetHandle() const\n{\n\treturn m_handle;\n}\n\nuint64_t AccelerationStructure::GetDeviceAddress() const\n{\n\treturn m_device_address;\n}\n\nvoid AccelerationStructure::Update(RHICommand *cmd_buffer, const VkAccelerationStructureGeometryKHR &geometry, const VkAccelerationStructureBuildRangeInfoKHR &range_info, VkAccelerationStructureTypeKHR type)\n{\n\tVkAccelerationStructureBuildGeometryInfoKHR build_geometry_info = {};\n\n\tbuild_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;\n\tbuild_geometry_info.type  = type;\n\tbuild_geometry_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;\n\n\tif (m_handle)\n\t{\n\t\tbuild_geometry_info.mode                     = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR;\n\t\tbuild_geometry_info.srcAccelerationStructure = m_handle;\n\t}\n\telse\n\t{\n\t\tbuild_geometry_info.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;\n\t}\n\n\tbuild_geometry_info.geometryCount = 1;\n\tbuild_geometry_info.pGeometries   = &geometry;\n\n\t// Get required build sizes\n\tVkAccelerationStructureBuildSizesInfoKHR build_sizes_info = {};\n\tbuild_sizes_info.sType                                    = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;\n\tvkGetAccelerationStructureBuildSizesKHR(\n\t    static_cast<Device *>(p_device)->GetDevice(),\n\t    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,\n\t    &build_geometry_info,\n\t    &range_info.primitiveCount,\n\t    &build_sizes_info);\n\n\t// Create a buffer for the acceleration structure\n\tif (!m_buffer || m_buffer->GetDesc().size != build_sizes_info.accelerationStructureSize)\n\t{\n\t\tm_buffer = std::make_unique<Buffer>(\n\t\t    p_device,\n\t\t    BufferDesc{\n\t\t        \"AS Buffer\",\n\t\t        RHIBufferUsage::AccelerationStructure,\n\t\t        RHIMemoryUsage::GPU_Only,\n\t\t        build_sizes_info.accelerationStructureSize});\n\n\t\tif (m_handle)\n\t\t{\n\t\t\tp_device->WaitIdle();\n\t\t\tvkDestroyAccelerationStructureKHR(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t\t}\n\n\t\tVkAccelerationStructureCreateInfoKHR acceleration_structure_create_info = {};\n\t\tacceleration_structure_create_info.sType                                = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;\n\t\tacceleration_structure_create_info.buffer                               = m_buffer->GetHandle();\n\t\tacceleration_structure_create_info.size                                 = build_sizes_info.accelerationStructureSize;\n\t\tacceleration_structure_create_info.type                                 = type;\n\t\tvkCreateAccelerationStructureKHR(static_cast<Device *>(p_device)->GetDevice(), &acceleration_structure_create_info, nullptr, &m_handle);\n\n\t\tbuild_geometry_info.mode                     = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;\n\t\tbuild_geometry_info.srcAccelerationStructure = VK_NULL_HANDLE;\n\t}\n\n\t// Get the acceleration structure's handle\n\tVkAccelerationStructureDeviceAddressInfoKHR acceleration_device_address_info = {};\n\tacceleration_device_address_info.sType                                       = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;\n\tacceleration_device_address_info.accelerationStructure                       = m_handle;\n\tm_device_address                                                             = vkGetAccelerationStructureDeviceAddressKHR(static_cast<Device *>(p_device)->GetDevice(), &acceleration_device_address_info);\n\n\tif (!m_scratch_buffer || m_scratch_buffer->GetDesc().size != build_sizes_info.buildScratchSize)\n\t{\n\t\tm_scratch_buffer = std::make_unique<Buffer>(\n\t\t    p_device,\n\t\t    BufferDesc{\n\t\t        \"AS Scratch Buffer\",\n\t\t        RHIBufferUsage::UnorderedAccess,\n\t\t        RHIMemoryUsage::GPU_Only,\n\t\t        build_sizes_info.buildScratchSize});\n\t}\n\n\tVkPhysicalDeviceAccelerationStructurePropertiesKHR properties = {};\n\n\tproperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;\n\tproperties.pNext = NULL;\n\n\tVkPhysicalDeviceProperties2 dev_props2 = {};\n\n\tdev_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;\n\tdev_props2.pNext = &properties;\n\n\tvkGetPhysicalDeviceProperties2(static_cast<Device *>(p_device)->GetPhysicalDevice(), &dev_props2);\n\n\tbuild_geometry_info.scratchData.deviceAddress = Align(m_scratch_buffer->GetDeviceAddress(), properties.minAccelerationStructureScratchOffsetAlignment);\n\tbuild_geometry_info.dstAccelerationStructure  = m_handle;\n\n\tVkAccelerationStructureBuildRangeInfoKHR *as_build_range_infos = const_cast<VkAccelerationStructureBuildRangeInfoKHR *>(&range_info);\n\n\t// Submit build task\n\tvkCmdBuildAccelerationStructuresKHR(\n\t    static_cast<Command *>(cmd_buffer)->GetHandle(),\n\t    1,\n\t    &build_geometry_info,\n\t    &as_build_range_infos);\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/AccelerationStructure.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Buffer;\n\nclass AccelerationStructure : public RHIAccelerationStructure\n{\n  public:\n\tAccelerationStructure(RHIDevice *device);\n\n\tvirtual ~AccelerationStructure() override;\n\n\tvirtual void Update(RHICommand *cmd_buffer, const TLASDesc &desc) override;\n\n\tvirtual void Update(RHICommand *cmd_buffer, const BLASDesc &desc) override;\n\n\tVkAccelerationStructureKHR GetHandle() const;\n\n\tuint64_t GetDeviceAddress() const;\n\n  private:\n\tvoid Update(RHICommand *cmd_buffer, const VkAccelerationStructureGeometryKHR &geometry, const VkAccelerationStructureBuildRangeInfoKHR &range_info, VkAccelerationStructureTypeKHR type);\n  private:\n\tVkAccelerationStructureKHR m_handle = VK_NULL_HANDLE;\n\n\t// TLAS & BLAS\n\tstd::unique_ptr<Buffer> m_buffer         = nullptr;\n\tstd::unique_ptr<Buffer> m_scratch_buffer = nullptr;\n\n\t// Only TLAS\n\tstd::unique_ptr<Buffer> m_instance_buffer = nullptr;\n\n\tuint64_t m_device_address = 0;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Buffer.cpp",
    "content": "#include \"Buffer.hpp\"\n#include \"Command.hpp\"\n#include \"Device.hpp\"\n#include \"Queue.hpp\"\n#include \"Synchronization.hpp\"\n\n#include <dxgi1_2.h>\n\nnamespace Ilum::Vulkan\n{\nBufferState BufferState::Create(RHIResourceState state)\n{\n\tBufferState vk_state = {};\n\n\tswitch (state)\n\t{\n\t\tcase RHIResourceState::VertexBuffer:\n\t\t\tvk_state.access_mask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::IndexBuffer:\n\t\t\tvk_state.access_mask = VK_ACCESS_INDEX_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::IndirectBuffer:\n\t\t\tvk_state.access_mask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::TransferSource:\n\t\t\tvk_state.access_mask = VK_ACCESS_TRANSFER_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_TRANSFER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::TransferDest:\n\t\t\tvk_state.access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_TRANSFER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::AccelerationStructure:\n\t\t\tvk_state.access_mask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;\n\t\t\tbreak;\n\t\tcase RHIResourceState::ShaderResource:\n\t\t\tvk_state.access_mask = VK_ACCESS_SHADER_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::UnorderedAccess:\n\t\t\tvk_state.access_mask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::ConstantBuffer:\n\t\t\tvk_state.access_mask = VK_ACCESS_SHADER_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tvk_state.access_mask = VK_ACCESS_FLAG_BITS_MAX_ENUM;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM;\n\t\t\tbreak;\n\t}\n\treturn vk_state;\n}\n\nBuffer::Buffer(RHIDevice *device, const BufferDesc &desc) :\n    RHIBuffer(device, desc)\n{\n\tm_desc.size = m_desc.size == 0 ? m_desc.stride * m_desc.count : m_desc.size;\n\n\tVkBufferCreateInfo buffer_create_info = {};\n\tbuffer_create_info.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;\n\tbuffer_create_info.size               = desc.size;\n\tbuffer_create_info.usage              = ToVulkanBufferUsage(desc.usage);\n\tbuffer_create_info.sharingMode        = VK_SHARING_MODE_EXCLUSIVE;\n\n\tif (static_cast<Device *>(p_device)->IsFeatureSupport(RHIFeature::BufferDeviceAddress))\n\t{\n\t\tbuffer_create_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;\n\t}\n\n#ifdef CUDA_ENABLE\n\t// External memory\n\tVkExternalMemoryBufferCreateInfo external_create_info = {};\n\n\texternal_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;\n\texternal_create_info.pNext = nullptr;\n#\tifdef _WIN64\n\texternal_create_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#\telse\n\texternal_create_info.handleTypes        = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;\n#\tendif\n\tbuffer_create_info.pNext = &external_create_info;\n\n\tvkCreateBuffer(static_cast<Device *>(p_device)->GetDevice(), &buffer_create_info, nullptr, &m_handle);\n\n\tVkMemoryRequirements memory_req = {};\n\tvkGetBufferMemoryRequirements(static_cast<Device *>(p_device)->GetDevice(), m_handle, &memory_req);\n\n#\tifdef _WIN64\n\tWindowsSecurityAttributes winSecurityAttributes;\n\n\tVkExportMemoryWin32HandleInfoKHR vulkanExportMemoryWin32HandleInfoKHR = {};\n\tvulkanExportMemoryWin32HandleInfoKHR.sType =\n\t    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;\n\tvulkanExportMemoryWin32HandleInfoKHR.pNext       = NULL;\n\tvulkanExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;\n\tvulkanExportMemoryWin32HandleInfoKHR.dwAccess =\n\t    DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;\n\tvulkanExportMemoryWin32HandleInfoKHR.name = (LPCWSTR) NULL;\n#\tendif\n\tVkExportMemoryAllocateInfoKHR export_memory_allocate_info = {};\n\texport_memory_allocate_info.sType =\n\t    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;\n#\tifdef _WIN64\n\texport_memory_allocate_info.pNext       = &vulkanExportMemoryWin32HandleInfoKHR;\n\texport_memory_allocate_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#\telse\n\texport_memory_allocate_info.pNext       = NULL;\n\texport_memory_allocate_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;\n#\tendif\n\n\tVkMemoryAllocateFlagsInfo allocate_flags_info = {};\n\tallocate_flags_info.sType                     = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;\n\tif (static_cast<Device *>(p_device)->IsFeatureSupport(RHIFeature::BufferDeviceAddress))\n\t{\n\t\tallocate_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;\n\t}\n\n\tVkMemoryAllocateInfo allocate_info{};\n\tallocate_info.sType          = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;\n\tallocate_info.allocationSize = memory_req.size;\n\tallocate_info.pNext          = &allocate_flags_info;\n\tallocate_flags_info.pNext    = &export_memory_allocate_info;\n\n\tVkPhysicalDeviceMemoryProperties physical_device_properties = {};\n\tvkGetPhysicalDeviceMemoryProperties(static_cast<Device *>(p_device)->GetPhysicalDevice(), &physical_device_properties);\n\n\tVkMemoryPropertyFlags properties = {};\n\tswitch (desc.memory)\n\t{\n\t\tcase RHIMemoryUsage::CPU_TO_GPU:\n\t\t\tproperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;\n\t\t\tbreak;\n\t\tcase RHIMemoryUsage::GPU_Only:\n\t\t\tproperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n\t\t\tbreak;\n\t\tcase RHIMemoryUsage::GPU_TO_CPU:\n\t\t\tproperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tfor (uint32_t i = 0; i < physical_device_properties.memoryTypeCount; i++)\n\t{\n\t\tif ((memory_req.memoryTypeBits & (1 << i)) &&\n\t\t    (physical_device_properties.memoryTypes[i].propertyFlags & properties))\n\t\t{\n\t\t\tallocate_info.memoryTypeIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tvkAllocateMemory(static_cast<Device *>(p_device)->GetDevice(), &allocate_info, nullptr, &m_memory);\n\tvkBindBufferMemory(static_cast<Device *>(p_device)->GetDevice(), m_handle, m_memory, 0);\n#else\n\tVmaAllocationCreateInfo allocation_create_info = {};\n\tallocation_create_info.usage                   = ToVmaMemoryUsage[desc.memory];\n\n\tVmaAllocationInfo allocation_info = {};\n\tvmaCreateBuffer(static_cast<Device *>(p_device)->GetAllocator(), &buffer_create_info, &allocation_create_info, &m_handle, &m_allocation, &allocation_info);\n#endif\n\n\tif (static_cast<Device *>(p_device)->IsFeatureSupport(RHIFeature::BufferDeviceAddress))\n\t{\n\t\tVkBufferDeviceAddressInfoKHR buffer_device_address_info = {};\n\t\tbuffer_device_address_info.sType                        = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;\n\t\tbuffer_device_address_info.buffer                       = m_handle;\n\t\tm_device_address                                        = vkGetBufferDeviceAddress(static_cast<Device *>(p_device)->GetDevice(), &buffer_device_address_info);\n\t}\n\n\tif (!m_desc.name.empty())\n\t{\n\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\tinfo.pObjectName                   = m_desc.name.c_str();\n\t\tinfo.objectHandle                  = (uint64_t) m_handle;\n\t\tinfo.objectType                    = VK_OBJECT_TYPE_BUFFER;\n\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t}\n}\n\nBuffer::~Buffer()\n{\n\tvkDeviceWaitIdle(static_cast<Device *>(p_device)->GetDevice());\n\n\tUnmap();\n\n\tif (m_allocation)\n\t{\n\t\tvmaFreeMemory(static_cast<Device *>(p_device)->GetAllocator(), m_allocation);\n\t\tm_allocation = VK_NULL_HANDLE;\n\t}\n\n\tif (m_handle)\n\t{\n\t\tvkDestroyBuffer(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t\tm_handle = nullptr;\n\t}\n\n\tif (m_memory)\n\t{\n\t\tvkFreeMemory(static_cast<Device *>(p_device)->GetDevice(), m_memory, nullptr);\n\t\tm_memory = VK_NULL_HANDLE;\n\t}\n}\n\nvoid Buffer::CopyToDevice(const void *data, size_t size, size_t offset)\n{\n\tif (m_desc.memory == RHIMemoryUsage::CPU_TO_GPU)\n\t{\n\t\tvoid *mapped = Map();\n\t\tstd::memcpy((uint8_t *) mapped + offset, data, size);\n\t\tFlush(offset, size);\n\t\tUnmap();\n\t}\n\telse\n\t{\n\t\tauto    fence = std::make_unique<Fence>(p_device);\n\t\tVkQueue queue = VK_NULL_HANDLE;\n\t\tvkGetDeviceQueue(static_cast<Device *>(p_device)->GetDevice(), static_cast<Device *>(p_device)->GetQueueFamily(RHIQueueFamily::Transfer), 0, &queue);\n\t\tauto staging_buffer = std::make_unique<Buffer>(p_device, BufferDesc{\"\", RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU, size});\n\n\t\t{\n\t\t\tstd::memcpy((uint8_t *) staging_buffer->Map(), data, size);\n\t\t\tauto cmd_buffer = std::make_unique<Command>(p_device, RHIQueueFamily::Transfer);\n\t\t\tcmd_buffer->Init();\n\t\t\tcmd_buffer->Begin();\n\t\t\tcmd_buffer->CopyBufferToBuffer(staging_buffer.get(), this, size, 0, offset);\n\t\t\tcmd_buffer->End();\n\n\t\t\tauto vk_cmd_buffer = cmd_buffer->GetHandle();\n\n\t\t\tVkSubmitInfo submit_info         = {};\n\t\t\tsubmit_info.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;\n\t\t\tsubmit_info.commandBufferCount   = 1;\n\t\t\tsubmit_info.pCommandBuffers      = &vk_cmd_buffer;\n\t\t\tsubmit_info.signalSemaphoreCount = 0;\n\t\t\tsubmit_info.pSignalSemaphores    = nullptr;\n\t\t\tsubmit_info.waitSemaphoreCount   = 0;\n\t\t\tsubmit_info.pWaitSemaphores      = nullptr;\n\t\t\tsubmit_info.pWaitDstStageMask    = nullptr;\n\n\t\t\tvkQueueSubmit(queue, 1, &submit_info, fence ? fence->GetHandle() : nullptr);\n\t\t\tfence->Wait();\n\t\t}\n\t}\n}\n\nvoid Buffer::CopyToHost(void *data, size_t size, size_t offset)\n{\n\tif (m_desc.memory == RHIMemoryUsage::GPU_TO_CPU)\n\t{\n\t\tvoid *mapped = Map();\n\t\tstd::memcpy(data, (uint8_t *) mapped + offset, size);\n\t\tFlush(offset, size);\n\t\tUnmap();\n\t}\n\telse\n\t{\n\t\tauto    fence = std::make_unique<Fence>(p_device);\n\t\tVkQueue queue = VK_NULL_HANDLE;\n\t\tvkGetDeviceQueue(static_cast<Device *>(p_device)->GetDevice(), static_cast<Device *>(p_device)->GetQueueFamily(RHIQueueFamily::Transfer), 0, &queue);\n\t\tauto staging_buffer = std::make_unique<Buffer>(p_device, BufferDesc{\"\", RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_TO_CPU, size});\n\n\t\t{\n\t\t\tauto cmd_buffer = std::make_unique<Command>(p_device, RHIQueueFamily::Transfer);\n\t\t\tcmd_buffer->Init();\n\t\t\tcmd_buffer->Begin();\n\t\t\tcmd_buffer->CopyBufferToBuffer(this, staging_buffer.get(), size, 0, offset);\n\t\t\tcmd_buffer->End();\n\n\t\t\tauto vk_cmd_buffer = cmd_buffer->GetHandle();\n\n\t\t\tVkSubmitInfo submit_info         = {};\n\t\t\tsubmit_info.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;\n\t\t\tsubmit_info.commandBufferCount   = 1;\n\t\t\tsubmit_info.pCommandBuffers      = &vk_cmd_buffer;\n\t\t\tsubmit_info.signalSemaphoreCount = 0;\n\t\t\tsubmit_info.pSignalSemaphores    = nullptr;\n\t\t\tsubmit_info.waitSemaphoreCount   = 0;\n\t\t\tsubmit_info.pWaitSemaphores      = nullptr;\n\t\t\tsubmit_info.pWaitDstStageMask    = nullptr;\n\n\t\t\tvkQueueSubmit(queue, 1, &submit_info, fence->GetHandle());\n\t\t\tfence->Wait();\n\n\t\t\tstd::memcpy(data, (uint8_t *) staging_buffer->Map(), size);\n\t\t}\n\t}\n}\n\nvoid *Buffer::Map()\n{\n\tif (!m_mapped)\n\t{\n\t\tif (m_allocation)\n\t\t{\n\t\t\tvmaMapMemory(static_cast<Device *>(p_device)->GetAllocator(), m_allocation, reinterpret_cast<void **>(&m_mapped));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvkMapMemory(static_cast<Device *>(p_device)->GetDevice(), m_memory, 0, VK_WHOLE_SIZE, 0, &m_mapped);\n\t\t}\n\t}\n\treturn m_mapped;\n}\n\nvoid Buffer::Unmap()\n{\n\tif (m_mapped)\n\t{\n\t\tif (m_allocation)\n\t\t{\n\t\t\tvmaUnmapMemory(static_cast<Device *>(p_device)->GetAllocator(), m_allocation);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvkUnmapMemory(static_cast<Device *>(p_device)->GetDevice(), m_memory);\n\t\t}\n\n\t\tm_mapped = nullptr;\n\t}\n}\n\nvoid Buffer::Flush(size_t offset, size_t size)\n{\n\tif (m_allocation)\n\t{\n\t\tvmaFlushAllocation(static_cast<Device *>(p_device)->GetAllocator(), m_allocation, 0, m_desc.size);\n\t}\n\telse\n\t{\n\t\tVkMappedMemoryRange range = {};\n\n\t\trange.memory = m_memory;\n\t\trange.sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;\n\t\trange.offset = 0;\n\t\trange.size   = VK_WHOLE_SIZE;\n\t\trange.pNext  = nullptr;\n\n\t\tvkFlushMappedMemoryRanges(static_cast<Device *>(p_device)->GetDevice(), 1, &range);\n\t}\n}\n\nVkBuffer Buffer::GetHandle() const\n{\n\treturn m_handle;\n}\n\nVkDeviceMemory Buffer::GetMemory() const\n{\n\tif (m_memory)\n\t{\n\t\treturn m_memory;\n\t}\n\n\tVmaAllocationInfo info = {};\n\tvmaGetAllocationInfo(static_cast<Device *>(p_device)->GetAllocator(), m_allocation, &info);\n\treturn info.deviceMemory;\n}\n\nuint64_t Buffer::GetDeviceAddress() const\n{\n\treturn m_device_address;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Buffer.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstruct BufferState\n{\n\tVkAccessFlags        access_mask = VK_ACCESS_NONE;\n\tVkPipelineStageFlags stage       = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;\n\n\tinline bool operator==(const BufferState &other)\n\t{\n\t\treturn access_mask == other.access_mask &&\n\t\t       stage == other.stage;\n\t}\n\n\tstatic BufferState Create(RHIResourceState state);\n};\n\nclass Buffer : public RHIBuffer\n{\n  public:\n\tBuffer(RHIDevice *device, const BufferDesc &desc);\n\n\tvirtual ~Buffer() override;\n\n\tvirtual void CopyToDevice(const void *data, size_t size, size_t offset = 0) override;\n\n\tvirtual void CopyToHost(void *data, size_t size, size_t offset) override;\n\n\tvirtual void *Map() override;\n\n\tvirtual void Unmap() override;\n\n\tvirtual void Flush(size_t offset, size_t size) override;\n\n\tVkBuffer GetHandle() const;\n\n\tVkDeviceMemory GetMemory() const;\n\n\tuint64_t GetDeviceAddress() const;\n\n  private:\n\tVkBuffer      m_handle     = VK_NULL_HANDLE;\n\tVmaAllocation m_allocation = VK_NULL_HANDLE;\n\tVkDeviceMemory m_memory     = VK_NULL_HANDLE;\n\n\tuint64_t m_device_address = 0;\n\n\tvoid *m_mapped = nullptr;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Command.cpp",
    "content": "#include \"Command.hpp\"\n#include \"Buffer.hpp\"\n#include \"Descriptor.hpp\"\n#include \"Device.hpp\"\n#include \"PipelineState.hpp\"\n#include \"RenderTarget.hpp\"\n#include \"Texture.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstatic std::unordered_map<size_t, VkCommandPool>          CommandPools;\nstatic std::unordered_map<size_t, std::vector<Command *>> CommandBuffers;\n\nstatic std::atomic<uint32_t> CommandCount = 0;\n\nCommand::Command(RHIDevice *device, RHIQueueFamily family) :\n    RHICommand(device, family)\n{\n\tstd::lock_guard<std::mutex> lock(m_mutex);\n\tCommandCount.fetch_add(1);\n\n\t// Register Command Buffer\n\tsize_t hash = 0;\n\tHashCombine(hash, family, std::this_thread::get_id());\n\tCommandBuffers[hash].push_back(this);\n\n\t// Check Command Pool\n\tif (CommandPools.find(hash) == CommandPools.end())\n\t{\n\t\tVkCommandPoolCreateInfo create_info = {};\n\t\tcreate_info.sType                   = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;\n\t\tcreate_info.flags                   = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;\n\t\tcreate_info.queueFamilyIndex        = static_cast<Device *>(p_device)->GetQueueFamily(family);\n\n\t\tVkCommandPool pool = VK_NULL_HANDLE;\n\t\tvkCreateCommandPool(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &pool);\n\t\tCommandPools[hash] = pool;\n\t}\n\tm_pool = CommandPools[hash];\n\n\t// Create Command Buffer\n\tVkCommandBufferAllocateInfo allocate_info = {};\n\tallocate_info.sType                       = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;\n\tallocate_info.commandPool                 = m_pool;\n\tallocate_info.level                       = VK_COMMAND_BUFFER_LEVEL_PRIMARY;\n\tallocate_info.commandBufferCount          = 1;\n\tvkAllocateCommandBuffers(static_cast<Device *>(p_device)->GetDevice(), &allocate_info, &m_handle);\n}\n\nCommand::Command(RHIDevice *device, VkCommandPool pool, RHIQueueFamily family) :\n    RHICommand(device, family), m_pool(pool)\n{\n\tCommandCount.fetch_add(1);\n\n\tVkCommandBufferAllocateInfo allocate_info = {};\n\tallocate_info.sType                       = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;\n\tallocate_info.commandPool                 = pool;\n\tallocate_info.level                       = VK_COMMAND_BUFFER_LEVEL_PRIMARY;\n\tallocate_info.commandBufferCount          = 1;\n\tvkAllocateCommandBuffers(static_cast<Device *>(p_device)->GetDevice(), &allocate_info, &m_handle);\n}\n\nCommand::~Command()\n{\n\tstd::lock_guard<std::mutex> lock(m_mutex);\n\n\tCommandCount.fetch_sub(1);\n\n\tif (m_handle)\n\t{\n\t\tvkFreeCommandBuffers(static_cast<Device *>(p_device)->GetDevice(), m_pool, 1, &m_handle);\n\t}\n\n\tif (CommandCount == 0)\n\t{\n\t\tfor (auto &[hash, pool] : CommandPools)\n\t\t{\n\t\t\tvkDestroyCommandPool(static_cast<Device *>(p_device)->GetDevice(), pool, nullptr);\n\t\t}\n\t\tCommandPools.clear();\n\t}\n\n\tfor (auto &[hash, cmds] : CommandBuffers)\n\t{\n\t\tfor (auto iter = cmds.begin(); iter != cmds.end(); iter++)\n\t\t{\n\t\t\tif (*iter == this)\n\t\t\t{\n\t\t\t\tcmds.erase(iter);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Command::SetState(CommandState state)\n{\n\tm_state = state;\n}\n\nVkCommandBuffer Command::GetHandle() const\n{\n\treturn m_handle;\n}\n\nvoid Command::SetName(const std::string &name)\n{\n\tVkDebugUtilsObjectNameInfoEXT info = {};\n\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\tinfo.pObjectName                   = name.c_str();\n\tinfo.objectHandle                  = (uint64_t) m_handle;\n\tinfo.objectType                    = VK_OBJECT_TYPE_COMMAND_BUFFER;\n\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n}\n\nvoid Command::Begin()\n{\n\tassert(m_state == CommandState::Initial);\n\n\tVkCommandBufferBeginInfo begin_info = {};\n\tbegin_info.sType                    = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;\n\tbegin_info.flags                    = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;\n\tbegin_info.pInheritanceInfo         = nullptr;\n\n\tvkBeginCommandBuffer(m_handle, &begin_info);\n\n\tm_state = CommandState::Recording;\n}\n\nvoid Command::End()\n{\n\tassert(m_state == CommandState::Recording);\n\tvkEndCommandBuffer(m_handle);\n\tm_state = CommandState::Executable;\n\n\tp_descriptor = nullptr;\n}\n\nvoid Command::BeginMarker(const std::string &name, float r, float g, float b, float a)\n{\n\tVkDebugUtilsLabelEXT label = {};\n\tlabel.sType                = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;\n\tlabel.pLabelName           = name.c_str();\n\tlabel.color[0]             = r;\n\tlabel.color[1]             = g;\n\tlabel.color[2]             = b;\n\tlabel.color[3]             = a;\n\n\tstatic_cast<Device *>(p_device)->BeginDebugUtilsLabel(m_handle, label);\n}\n\nvoid Command::EndMarker()\n{\n\tstatic_cast<Device *>(p_device)->EndDebugUtilsLabel(m_handle);\n}\n\nvoid Command::BeginRenderPass(RHIRenderTarget *render_target)\n{\n\tif (static_cast<Device *>(p_device)->IsFeatureSupport(VulkanFeature::DynamicRendering))\n\t{\n\t\tVkRenderingInfo rendering_info = {};\n\t\trendering_info.sType           = VK_STRUCTURE_TYPE_RENDERING_INFO;\n\t\trendering_info.renderArea      = {0, 0, render_target->GetWidth(), render_target->GetHeight()};\n\t\trendering_info.layerCount      = render_target->GetLayers();\n\n\t\tRenderTarget *vk_render_target = static_cast<RenderTarget *>(render_target);\n\n\t\trendering_info.colorAttachmentCount = static_cast<uint32_t>(vk_render_target->GetColorAttachments().size());\n\t\trendering_info.pColorAttachments    = vk_render_target->GetColorAttachments().data();\n\t\trendering_info.pDepthAttachment     = vk_render_target->GetDepthAttachment().has_value() ? &vk_render_target->GetDepthAttachment().value() : nullptr;\n\t\trendering_info.pStencilAttachment   = vk_render_target->GetStencilAttachment().has_value() ? &vk_render_target->GetStencilAttachment().value() : nullptr;\n\n\t\tvkCmdBeginRendering(m_handle, &rendering_info);\n\t}\n\telse\n\t{\n\t\tRenderTarget *vk_render_target = static_cast<RenderTarget *>(render_target);\n\n\t\tauto clear_values = vk_render_target->GetClearValue();\n\n\t\tVkRenderPassBeginInfo begin_info = {};\n\t\tbegin_info.sType                 = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;\n\t\tbegin_info.framebuffer           = vk_render_target->GetFramebuffer();\n\t\tbegin_info.pClearValues          = clear_values.data();\n\t\tbegin_info.clearValueCount       = static_cast<uint32_t>(clear_values.size());\n\t\tbegin_info.renderPass            = vk_render_target->GetRenderPass();\n\t\tbegin_info.renderArea            = vk_render_target->GetRenderArea();\n\n\t\tvkCmdBeginRenderPass(m_handle, &begin_info, VK_SUBPASS_CONTENTS_INLINE);\n\t}\n\n\tp_render_target = static_cast<RenderTarget *>(render_target);\n}\n\nvoid Command::EndRenderPass()\n{\n\tif (static_cast<Device *>(p_device)->IsFeatureSupport(VulkanFeature::DynamicRendering))\n\t{\n\t\tvkCmdEndRendering(m_handle);\n\t}\n\telse\n\t{\n\t\tvkCmdEndRenderPass(m_handle);\n\t}\n\n\tp_render_target = nullptr;\n}\n\nvoid Command::BindVertexBuffer(uint32_t binding, RHIBuffer *vertex_buffer)\n{\n\tBuffer  *vk_vertex_buffer = static_cast<Buffer *>(vertex_buffer);\n\tsize_t   offset           = 0;\n\tVkBuffer handle           = vk_vertex_buffer->GetHandle();\n\tvkCmdBindVertexBuffers(m_handle, binding, 1, &handle, &offset);\n}\n\nvoid Command::BindIndexBuffer(RHIBuffer *index_buffer, bool is_short)\n{\n\tvkCmdBindIndexBuffer(m_handle, static_cast<Buffer *>(index_buffer)->GetHandle(), 0, is_short ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);\n}\n\nvoid Command::BindDescriptor(RHIDescriptor *descriptor)\n{\n\tp_descriptor = static_cast<Descriptor *>(descriptor);\n}\n\nvoid Command::BindPipelineState(RHIPipelineState *pipeline_state)\n{\n\tassert(p_descriptor != nullptr);\n\tp_pipeline_state = static_cast<PipelineState *>(pipeline_state);\n\tvkCmdBindPipeline(m_handle, p_pipeline_state->GetPipelineBindPoint(), p_pipeline_state->GetPipeline(p_descriptor, p_render_target));\n\tfor (auto &[set, descriptor_set] : p_descriptor->GetDescriptorSet())\n\t{\n\t\tvkCmdBindDescriptorSets(m_handle, p_pipeline_state->GetPipelineBindPoint(), p_pipeline_state->GetPipelineLayout(p_descriptor), set, 1, &descriptor_set, 0, nullptr);\n\t}\n\tfor (auto &[name, constant] : static_cast<Descriptor *>(p_descriptor)->GetConstantResolve())\n\t{\n\t\tvkCmdPushConstants(m_handle, p_pipeline_state->GetPipelineLayout(p_descriptor), constant.stage, static_cast<uint32_t>(constant.offset), static_cast<uint32_t>(constant.data.size()), constant.data.data());\n\t}\n}\n\nvoid Command::SetViewport(float width, float height, float x, float y)\n{\n\t// Flip y\n\tVkViewport viewport = {x, y + height, width, -height, 0.f, 1.f};\n\tvkCmdSetViewport(m_handle, 0, 1, &viewport);\n}\n\nvoid Command::SetScissor(uint32_t width, uint32_t height, int32_t offset_x, int32_t offset_y)\n{\n\tVkRect2D rect = {VkOffset2D{offset_x, offset_y}, VkExtent2D{width, height}};\n\tvkCmdSetScissor(m_handle, 0, 1, &rect);\n}\n\nvoid Command::Dispatch(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z)\n{\n\tvkCmdDispatch(m_handle, (thread_x + block_x - 1) / block_x, (thread_y + block_y - 1) / block_y, (thread_z + block_z - 1) / block_z);\n}\n\nvoid Command::DispatchIndirect(RHIBuffer *buffer, size_t offset)\n{\n\tvkCmdDispatchIndirect(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset);\n}\n\nvoid Command::Draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance)\n{\n\tvkCmdDraw(m_handle, vertex_count, instance_count, first_vertex, first_instance);\n}\n\nvoid Command::DrawIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)\n{\n\tvkCmdDrawIndirect(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, draw_count, stride);\n}\n\nvoid Command::DrawIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride)\n{\n\tvkCmdDrawIndirectCount(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, static_cast<Buffer *>(count_buffer)->GetHandle(), count_buffer_offset, max_draw_count, stride);\n}\n\nvoid Command::DrawIndexed(uint32_t index_count, uint32_t instance_count, uint32_t first_index, uint32_t vertex_offset, uint32_t first_instance)\n{\n\tvkCmdDrawIndexed(m_handle, index_count, instance_count, first_index, vertex_offset, first_instance);\n}\n\nvoid Command::DrawIndexedIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)\n{\n\tvkCmdDrawIndexedIndirect(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, draw_count, stride);\n}\n\nvoid Command::DrawIndexedIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride)\n{\n\tvkCmdDrawIndexedIndirectCount(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, static_cast<Buffer *>(count_buffer)->GetHandle(), count_buffer_offset, max_draw_count, stride);\n}\n\nvoid Command::DrawMeshTask(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z)\n{\n\tvkCmdDrawMeshTasksEXT(m_handle, (thread_x + block_x - 1) / block_x, (thread_y + block_y - 1) / block_y, (thread_z + block_z - 1) / block_z);\n}\n\nvoid Command::DrawMeshTasksIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)\n{\n\tvkCmdDrawMeshTasksIndirectEXT(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, draw_count, stride);\n}\n\nvoid Command::DrawMeshTasksIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride)\n{\n\tvkCmdDrawMeshTasksIndirectCountEXT(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, static_cast<Buffer *>(count_buffer)->GetHandle(), count_buffer_offset, max_draw_count, stride);\n}\n\nvoid Command::TraceRay(uint32_t width, uint32_t height, uint32_t depth)\n{\n\tauto sbt = p_pipeline_state->GetShaderBindingTable(p_pipeline_state->GetPipeline(p_descriptor, p_render_target));\n\tvkCmdTraceRaysKHR(\n\t    m_handle,\n\t    sbt.raygen, sbt.miss, sbt.hit, sbt.callable,\n\t    width, height, depth);\n}\n\nvoid Command::CopyBufferToTexture(RHIBuffer *src_buffer, RHITexture *dst_texture, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count)\n{\n\tVkImageSubresourceLayers subresource = {};\n\tsubresource.aspectMask               = IsDepthFormat(dst_texture->GetDesc().format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;\n\tsubresource.baseArrayLayer           = base_layer;\n\tsubresource.mipLevel                 = mip_level;\n\tsubresource.layerCount               = layer_count;\n\n\tuint32_t width  = std::max(dst_texture->GetDesc().width, 1u << mip_level) >> mip_level;\n\tuint32_t height = std::max(dst_texture->GetDesc().height, 1u << mip_level) >> mip_level;\n\n\tVkBufferImageCopy copy_info = {};\n\tcopy_info.bufferOffset      = 0;\n\tcopy_info.bufferImageHeight = 0;\n\tcopy_info.bufferRowLength   = 0;\n\tcopy_info.imageSubresource  = subresource;\n\tcopy_info.imageOffset       = {0, 0, 0};\n\tcopy_info.imageExtent       = {width, height, 1};\n\n\tvkCmdCopyBufferToImage(m_handle, static_cast<Buffer *>(src_buffer)->GetHandle(), static_cast<Texture *>(dst_texture)->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_info);\n}\n\nvoid Command::CopyTextureToBuffer(RHITexture *src_texture, RHIBuffer *dst_buffer, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count)\n{\n\tVkImageSubresourceLayers subresource = {};\n\tsubresource.aspectMask               = IsDepthFormat(src_texture->GetDesc().format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;\n\tsubresource.baseArrayLayer           = base_layer;\n\tsubresource.mipLevel                 = mip_level;\n\tsubresource.layerCount               = layer_count;\n\n\tuint32_t width  = std::max(src_texture->GetDesc().width, 1u << mip_level) >> mip_level;\n\tuint32_t height = std::max(src_texture->GetDesc().height, 1u << mip_level) >> mip_level;\n\n\tVkBufferImageCopy copy_info = {};\n\tcopy_info.bufferOffset      = 0;\n\tcopy_info.imageSubresource  = subresource;\n\tcopy_info.imageOffset       = {0, 0, 0};\n\tcopy_info.imageExtent       = {width, height, 1};\n\n\tvkCmdCopyImageToBuffer(m_handle, static_cast<Texture *>(src_texture)->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, static_cast<Buffer *>(dst_buffer)->GetHandle(), 1, &copy_info);\n}\n\nvoid Command::CopyBufferToBuffer(RHIBuffer *src_buffer, RHIBuffer *dst_buffer, size_t size, size_t src_offset, size_t dst_offset)\n{\n\tVkBufferCopy buffer_copy = {};\n\tbuffer_copy.size         = size;\n\tbuffer_copy.srcOffset    = src_offset;\n\tbuffer_copy.dstOffset    = dst_offset;\n\n\tvkCmdCopyBuffer(m_handle, static_cast<Buffer *>(src_buffer)->GetHandle(), static_cast<Buffer *>(dst_buffer)->GetHandle(), 1, &buffer_copy);\n}\n\nvoid Command::GenerateMipmaps(RHITexture *texture, RHIResourceState initial_state, RHIFilter filter)\n{\n\tif (initial_state != RHIResourceState::TransferDest)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{texture, initial_state, RHIResourceState::TransferDest, TextureRange{RHITextureDimension::Texture2D, 0, texture->GetDesc().mips, 0, texture->GetDesc().layers}}}, {});\n\t}\n\n\tif (texture->GetDesc().mips == 1)\n\t{\n\t\treturn;\n\t}\n\n\tTextureRange             src_range  = {RHITextureDimension::Texture2D, 0, texture->GetDesc().mips, 0, texture->GetDesc().layers};\n\tTextureRange             dst_range  = {RHITextureDimension::Texture2D, 0, texture->GetDesc().mips, 0, texture->GetDesc().layers};\n\tVkImageSubresourceLayers src_layers = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, texture->GetDesc().layers};\n\tVkImageSubresourceLayers dst_layers = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, texture->GetDesc().layers};\n\tRHIResourceState         src_state  = RHIResourceState::TransferDest;\n\n\tuint32_t src_width  = texture->GetDesc().width;\n\tuint32_t src_height = texture->GetDesc().height;\n\tuint32_t dst_width  = texture->GetDesc().width;\n\tuint32_t dst_height = texture->GetDesc().height;\n\n\tfor (uint32_t i = 1; i < texture->GetDesc().mips; i++)\n\t{\n\t\tsrc_width  = dst_width;\n\t\tsrc_height = dst_height;\n\n\t\tdst_width  = std::max(src_width / 2, 1u);\n\t\tdst_height = std::max(src_height / 2, 1u);\n\n\t\tsrc_layers.mipLevel = i - 1;\n\t\tsrc_range.base_mip  = i - 1;\n\t\tsrc_range.mip_count = 1;\n\n\t\tdst_layers.mipLevel = i;\n\t\tdst_range.base_mip  = i;\n\t\tdst_range.mip_count = 1;\n\n\t\tstd::vector<TextureStateTransition> transitions(2);\n\t\ttransitions[0].texture = texture;\n\t\ttransitions[0].src     = src_state;\n\t\ttransitions[0].dst     = RHIResourceState::TransferSource;\n\t\ttransitions[0].range   = src_range;\n\t\ttransitions[1].texture = texture;\n\t\ttransitions[1].src     = RHIResourceState::Undefined;\n\t\ttransitions[1].dst     = RHIResourceState::TransferDest;\n\t\ttransitions[1].range   = dst_range;\n\t\tResourceStateTransition(transitions, {});\n\n\t\tsrc_state = RHIResourceState::TransferDest;\n\n\t\tVkImageBlit blit_info    = {};\n\t\tblit_info.srcOffsets[0]  = {0, 0, 0};\n\t\tblit_info.srcOffsets[1]  = {static_cast<int32_t>(src_width), static_cast<int32_t>(src_height), 1};\n\t\tblit_info.dstOffsets[0]  = {0, 0, 0};\n\t\tblit_info.dstOffsets[1]  = {static_cast<int32_t>(dst_width), static_cast<int32_t>(dst_height), 1};\n\t\tblit_info.srcSubresource = src_layers;\n\t\tblit_info.dstSubresource = dst_layers;\n\n\t\tvkCmdBlitImage(m_handle, static_cast<Texture *>(texture)->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, static_cast<Texture *>(texture)->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_info, ToVulkanFilter[filter]);\n\t}\n\n\tTextureRange mip_level_range = {RHITextureDimension::Texture2D, 0, texture->GetDesc().mips, 0, texture->GetDesc().layers};\n\n\tmip_level_range.mip_count = mip_level_range.mip_count - 1;\n\tResourceStateTransition({TextureStateTransition{texture, RHIResourceState::TransferSource, RHIResourceState::TransferDest, mip_level_range}}, {});\n}\n\nvoid Command::BlitTexture(RHITexture *src_texture, const TextureRange &src_range, const RHIResourceState &src_state, RHITexture *dst_texture, const TextureRange &dst_range, const RHIResourceState &dst_state, RHIFilter filter)\n{\n\tif (src_state != RHIResourceState::TransferSource)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{src_texture, src_state, RHIResourceState::TransferSource, src_range}}, {});\n\t}\n\n\tif (dst_state != RHIResourceState::TransferDest)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{dst_texture, dst_state, RHIResourceState::TransferDest, dst_range}}, {});\n\t}\n\n\tVkImage       src_image  = static_cast<Texture *>(src_texture)->GetHandle();\n\tVkImage       dst_image  = static_cast<Texture *>(dst_texture)->GetHandle();\n\tVkImageLayout src_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;\n\tVkImageLayout dst_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;\n\n\tVkImageBlit region = {};\n\n\tregion.srcSubresource.aspectMask     = IsDepthFormat(src_texture->GetDesc().format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;\n\tregion.srcSubresource.baseArrayLayer = src_range.base_layer;\n\tregion.srcSubresource.layerCount     = src_range.layer_count;\n\tregion.srcSubresource.mipLevel       = src_range.base_mip;\n\n\tregion.dstSubresource.aspectMask     = IsDepthFormat(dst_texture->GetDesc().format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;\n\tregion.dstSubresource.baseArrayLayer = dst_range.base_layer;\n\tregion.dstSubresource.layerCount     = dst_range.layer_count;\n\tregion.dstSubresource.mipLevel       = dst_range.base_mip;\n\n\tregion.srcOffsets[1].x = src_texture->GetDesc().width;\n\tregion.srcOffsets[1].y = src_texture->GetDesc().height;\n\tregion.srcOffsets[1].z = 1;\n\n\tregion.dstOffsets[1].x = dst_texture->GetDesc().width;\n\tregion.dstOffsets[1].y = dst_texture->GetDesc().height;\n\tregion.dstOffsets[1].z = 1;\n\n\tvkCmdBlitImage(m_handle, src_image, src_layout, dst_image, dst_layout, 1, &region, ToVulkanFilter[filter]);\n\n\tif (src_state != RHIResourceState::TransferSource && src_state != RHIResourceState::Undefined)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{src_texture, RHIResourceState::TransferSource, src_state, src_range}}, {});\n\t}\n\n\tif (dst_state != RHIResourceState::TransferDest && dst_state != RHIResourceState::Undefined)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{dst_texture, RHIResourceState::TransferDest, dst_state, dst_range}}, {});\n\t}\n}\n\nvoid Command::FillBuffer(RHIBuffer *buffer, RHIResourceState state, size_t size, size_t offset, uint32_t data)\n{\n\tif (state != RHIResourceState::TransferDest)\n\t{\n\t\tResourceStateTransition(\n\t\t    {},\n\t\t    {BufferStateTransition{\n\t\t        buffer,\n\t\t        RHIResourceState::UnorderedAccess,\n\t\t        RHIResourceState::TransferDest}});\n\t}\n\n\tvkCmdFillBuffer(m_handle, static_cast<Buffer *>(buffer)->GetHandle(), offset, size, data);\n\n\tif (state != RHIResourceState::TransferDest)\n\t{\n\t\tResourceStateTransition(\n\t\t    {},\n\t\t    {BufferStateTransition{\n\t\t        buffer,\n\t\t        RHIResourceState::TransferDest,\n\t\t        RHIResourceState::UnorderedAccess}});\n\t}\n}\n\nvoid Command::FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, const glm::vec4 &color)\n{\n\tauto vk_state = TextureState::Create(state);\n\n\tVkClearColorValue clear_color = {};\n\tstd::memcpy(clear_color.float32, &color.x, sizeof(float) * 4);\n\n\tVkImageSubresourceRange vk_range = {};\n\tvk_range.aspectMask              = VK_IMAGE_ASPECT_COLOR_BIT;\n\tvk_range.baseArrayLayer          = range.base_layer;\n\tvk_range.baseMipLevel            = range.base_mip;\n\tvk_range.layerCount              = range.layer_count;\n\tvk_range.levelCount              = range.mip_count;\n\n\tif (state != RHIResourceState::TransferDest)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{\n\t\t                            texture,\n\t\t                            state,\n\t\t                            RHIResourceState::TransferDest}},\n\t\t                        {});\n\t}\n\n\tvkCmdClearColorImage(m_handle, static_cast<Texture *>(texture)->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &vk_range);\n\n\tif (state != RHIResourceState::TransferDest)\n\t{\n\t\tResourceStateTransition({TextureStateTransition{\n\t\t                            texture,\n\t\t                            RHIResourceState::TransferDest,\n\t\t                            state}},\n\t\t                        {});\n\t}\n}\n\nvoid Command::FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, float depth)\n{\n}\n\nvoid Command::ResourceStateTransition(const std::vector<TextureStateTransition> &texture_transitions, const std::vector<BufferStateTransition> &buffer_transitions)\n{\n\t// TODO:\n\t// + Pipeline Stage Mask\n\t// + Queue ownership transfer\n\tif (texture_transitions.empty() && buffer_transitions.empty())\n\t{\n\t\treturn;\n\t}\n\n\tstd::vector<VkBufferMemoryBarrier> buffer_barriers;\n\tbuffer_barriers.reserve(buffer_transitions.size());\n\n\tstd::vector<VkImageMemoryBarrier> image_barriers;\n\timage_barriers.reserve(texture_transitions.size());\n\n\tVkPipelineStageFlags src_stage = 0;\n\tVkPipelineStageFlags dst_stage = 0;\n\n\tfor (uint32_t i = 0; i < buffer_transitions.size(); i++)\n\t{\n\t\tBufferState vk_buffer_state_src = BufferState::Create(buffer_transitions[i].src);\n\t\tBufferState vk_buffer_state_dst = BufferState::Create(buffer_transitions[i].dst);\n\n\t\tVkBufferMemoryBarrier buffer_barrier = {};\n\n\t\tbuffer_barrier.sType               = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;\n\t\tbuffer_barrier.srcAccessMask       = vk_buffer_state_src.access_mask;\n\t\tbuffer_barrier.dstAccessMask       = vk_buffer_state_dst.access_mask;\n\t\tbuffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;\n\t\tbuffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;\n\t\tbuffer_barrier.buffer              = static_cast<Buffer *>(buffer_transitions[i].buffer)->GetHandle();\n\t\tbuffer_barrier.offset              = 0;\n\t\tbuffer_barrier.size                = buffer_transitions[i].buffer->GetDesc().size;\n\t\tbuffer_barriers.push_back(buffer_barrier);\n\t\tsrc_stage |= vk_buffer_state_src.stage;\n\t\tdst_stage |= vk_buffer_state_dst.stage;\n\t}\n\n\tfor (uint32_t i = 0; i < texture_transitions.size(); i++)\n\t{\n\t\tTextureState vk_texture_state_src = TextureState::Create(texture_transitions[i].src);\n\t\tTextureState vk_texture_state_dst = TextureState::Create(texture_transitions[i].dst);\n\n\t\tVkImageMemoryBarrier image_barrier = {};\n\n\t\tVkImageSubresourceRange range = {};\n\t\trange.aspectMask              = IsDepthFormat(texture_transitions[i].texture->GetDesc().format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;\n\t\trange.baseArrayLayer          = texture_transitions[i].range.base_layer;\n\t\trange.baseMipLevel            = texture_transitions[i].range.base_mip;\n\t\trange.layerCount              = texture_transitions[i].range.layer_count;\n\t\trange.levelCount              = texture_transitions[i].range.mip_count;\n\n\t\timage_barrier.sType         = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;\n\t\timage_barrier.srcAccessMask = vk_texture_state_src.access_mask;\n\t\timage_barrier.dstAccessMask = vk_texture_state_dst.access_mask;\n\t\timage_barrier.oldLayout     = vk_texture_state_src.layout;\n\t\timage_barrier.newLayout     = vk_texture_state_dst.layout;\n\n\t\t/*RHIQueueFamily src_family = RHIQueueFamily::Graphics;\n\t\tRHIQueueFamily dst_family = RHIQueueFamily::Graphics;\n\n\t\tswitch (texture_transitions[i].src)\n\t\t{\n\t\t    case RHIResourceState::TransferSource:\n\t\t    case RHIResourceState::TransferDest:\n\n\t\t    case RHIResourceState::ShaderResource:\n\t\t    case RHIResourceState::RenderTarget:\n\t\t    case RHIResourceState::DepthWrite:\n\t\t    case RHIResourceState::DepthRead:\n\t\t    case RHIResourceState::Present:\n\t\t        src_family = RHIQueueFamily::Graphics;\n\t\t        break;\n\t\t    case RHIResourceState::UnorderedAccess:\n\t\t        src_family = RHIQueueFamily::Compute;\n\t\t        break;\n\t\t    default:\n\t\t        break;\n\t\t}\n\n\t\tswitch (texture_transitions[i].dst)\n\t\t{\n\t\t    case RHIResourceState::TransferSource:\n\t\t    case RHIResourceState::TransferDest:\n\t\t    case RHIResourceState::ShaderResource:\n\t\t    case RHIResourceState::RenderTarget:\n\t\t    case RHIResourceState::DepthWrite:\n\t\t    case RHIResourceState::DepthRead:\n\t\t    case RHIResourceState::Present:\n\t\t        dst_family = RHIQueueFamily::Graphics;\n\t\t        break;\n\t\t    case RHIResourceState::UnorderedAccess:\n\t\t        dst_family = RHIQueueFamily::Compute;\n\t\t        break;\n\t\t    default:\n\t\t        break;\n\t\t}*/\n\t\t// if (texture_transitions[i].src_family == texture_transitions[i].dst_family)\n\t\t{\n\t\t\timage_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;\n\t\t\timage_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;\n\t\t}\n\t\t// else\n\t\t{\n\t\t\t// image_barrier.srcQueueFamilyIndex = static_cast<Device *>(p_device)->GetQueueFamily(texture_transitions[i].src_family);\n\t\t\t// image_barrier.dstQueueFamilyIndex = static_cast<Device *>(p_device)->GetQueueFamily(texture_transitions[i].dst_family);\n\t\t}\n\n\t\timage_barrier.image            = static_cast<Texture *>(texture_transitions[i].texture)->GetHandle();\n\t\timage_barrier.subresourceRange = range;\n\t\timage_barriers.push_back(image_barrier);\n\t\tsrc_stage |= vk_texture_state_src.stage;\n\t\tdst_stage |= vk_texture_state_dst.stage;\n\t}\n\n\tvkCmdPipelineBarrier(m_handle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, static_cast<uint32_t>(buffer_barriers.size()), buffer_barriers.data(), static_cast<uint32_t>(image_barriers.size()), image_barriers.data());\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Command.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Descriptor;\nclass RenderTarget;\nclass PipelineState;\n\nclass Command : public RHICommand\n{\n  public:\n\tCommand(RHIDevice *device, RHIQueueFamily family);\n\n\tCommand(RHIDevice *device, VkCommandPool pool, RHIQueueFamily family);\n\n\tvirtual ~Command() override;\n\n\tvoid SetState(CommandState state);\n\n\tVkCommandBuffer GetHandle() const;\n\n\tvirtual void SetName(const std::string &name) override;\n\n\tvirtual void Begin() override;\n\tvirtual void End() override;\n\n\tvirtual void BeginMarker(const std::string &name, float r, float g, float b, float a) override;\n\tvirtual void EndMarker() override;\n\n\tvirtual void BeginRenderPass(RHIRenderTarget *render_target) override;\n\tvirtual void EndRenderPass() override;\n\n\tvirtual void BindVertexBuffer(uint32_t binding, RHIBuffer *vertex_buffer) override;\n\tvirtual void BindIndexBuffer(RHIBuffer *index_buffer, bool is_short = false) override;\n\n\tvirtual void BindDescriptor(RHIDescriptor *descriptor) override;\n\tvirtual void BindPipelineState(RHIPipelineState *pipeline_state) override;\n\n\tvirtual void SetViewport(float width, float height, float x = 0.f, float y = 0.f) override;\n\tvirtual void SetScissor(uint32_t width, uint32_t height, int32_t offset_x = 0, int32_t offset_y = 0) override;\n\n\tvirtual void Dispatch(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z) override;\n\tvirtual void DispatchIndirect(RHIBuffer *buffer, size_t offset) override;\n\n\tvirtual void Draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance) override;\n\tvirtual void DrawIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride) override;\n\tvirtual void DrawIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) override;\n\n\tvirtual void DrawIndexed(uint32_t index_count, uint32_t instance_count, uint32_t first_index, uint32_t vertex_offset, uint32_t first_instance) override;\n\tvirtual void DrawIndexedIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride) override;\n\tvirtual void DrawIndexedIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) override;\n\n\tvirtual void DrawMeshTask(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z) override;\n\tvirtual void DrawMeshTasksIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride) override;\n\tvirtual void DrawMeshTasksIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) override;\n\n\tvirtual void TraceRay(uint32_t width, uint32_t height, uint32_t depth) override;\n\n\tvirtual void CopyBufferToTexture(RHIBuffer *src_buffer, RHITexture *dst_texture, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count) override;\n\tvirtual void CopyTextureToBuffer(RHITexture *src_texture, RHIBuffer *dst_buffer, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count) override;\n\tvirtual void CopyBufferToBuffer(RHIBuffer *src_buffer, RHIBuffer *dst_buffer, size_t size, size_t src_offset, size_t dst_offset) override;\n\n\tvirtual void GenerateMipmaps(RHITexture *texture, RHIResourceState initial_state, RHIFilter filter) override;\n\tvirtual void BlitTexture(RHITexture *src_texture, const TextureRange &src_range, const RHIResourceState &src_state, RHITexture *dst_texture, const TextureRange &dst_range, const RHIResourceState &dst_state, RHIFilter filter) override;\n\n\tvirtual void FillBuffer(RHIBuffer *buffer, RHIResourceState state, size_t size, size_t offset, uint32_t data) override;\n\tvirtual void FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, const glm::vec4 &color) override;\n\tvirtual void FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, float depth) override;\n\n\tvirtual void ResourceStateTransition(const std::vector<TextureStateTransition> &texture_transitions, const std::vector<BufferStateTransition> &buffer_transitions) override;\n\n  private:\n\tVkCommandBuffer m_handle = VK_NULL_HANDLE;\n\tVkCommandPool   m_pool   = VK_NULL_HANDLE;\n\n\tDescriptor    *p_descriptor     = nullptr;\n\tPipelineState *p_pipeline_state = nullptr;\n\tRenderTarget  *p_render_target  = nullptr;\n\n\tstd::mutex m_mutex;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Definitions.cpp",
    "content": "#include \"Definitions.hpp\"\n\n#ifdef _WIN64\n#\tinclude <aclapi.h>\n#\tinclude <dxgi1_6.h>\n#\tinclude <windows.h>\n#\tinclude <securitybaseapi.h>\n#endif\n\nnamespace Ilum::Vulkan\n{\n#ifdef CUDA_ENABLE\nWindowsSecurityAttributes::WindowsSecurityAttributes()\n{\n\tm_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR) calloc(1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **));\n\n\tPSID *ppSID = (PSID *) ((PBYTE) m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);\n\tPACL *ppACL = (PACL *) ((PBYTE) ppSID + sizeof(PSID *));\n\n\tInitializeSecurityDescriptor(m_winPSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);\n\n\tSID_IDENTIFIER_AUTHORITY sidIdentifierAuthority = SECURITY_WORLD_SID_AUTHORITY;\n\tAllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0, 0,\n\t                         0, 0, 0, 0, 0, ppSID);\n\n\tEXPLICIT_ACCESS explicitAccess;\n\tZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS));\n\texplicitAccess.grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;\n\texplicitAccess.grfAccessMode        = SET_ACCESS;\n\texplicitAccess.grfInheritance       = INHERIT_ONLY;\n\texplicitAccess.Trustee.TrusteeForm  = TRUSTEE_IS_SID;\n\texplicitAccess.Trustee.TrusteeType  = TRUSTEE_IS_WELL_KNOWN_GROUP;\n\texplicitAccess.Trustee.ptstrName    = (LPTSTR) *ppSID;\n\n\tSetEntriesInAcl(1, &explicitAccess, NULL, ppACL);\n\n\tSetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE);\n\n\tm_winSecurityAttributes.nLength              = sizeof(m_winSecurityAttributes);\n\tm_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;\n}\n\nSECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&()\n{\n\treturn &m_winSecurityAttributes;\n}\n\nWindowsSecurityAttributes::~WindowsSecurityAttributes()\n{\n\tPSID *ppSID =\n\t    (PSID *) ((PBYTE) m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);\n\tPACL *ppACL = (PACL *) ((PBYTE) ppSID + sizeof(PSID *));\n\n\tif (*ppSID)\n\t{\n\t\tFreeSid(*ppSID);\n\t}\n\tif (*ppACL)\n\t{\n\t\tLocalFree(*ppACL);\n\t}\n\tfree(m_winPSecurityDescriptor);\n}\n#endif\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Definitions.hpp",
    "content": "#pragma once\n\n#include \"RHI/RHIDefinitions.hpp\"\n\n#include <volk.h>\n\n#include \"vk_mem_alloc.h\"\n\n#include <unordered_map>\n\n#ifdef _WIN64\n#\tinclude <Windows.h>\n#endif        // _WIN64\n\nnamespace Ilum::Vulkan\n{\nenum class VulkanFeature\n{\n\tDynamicRendering\n};\n\ninline static std::unordered_map<RHIFormat, VkFormat> ToVulkanFormat = {\n    {RHIFormat::Undefined, VK_FORMAT_UNDEFINED},\n    {RHIFormat::R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM},\n    {RHIFormat::B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM},\n    {RHIFormat::R16_UINT, VK_FORMAT_R16_UINT},\n    {RHIFormat::R16_SINT, VK_FORMAT_R16_SINT},\n    {RHIFormat::R16_FLOAT, VK_FORMAT_R16_SFLOAT},\n    {RHIFormat::R16G16_UINT, VK_FORMAT_R16G16_UINT},\n    {RHIFormat::R16G16_SINT, VK_FORMAT_R16G16_SINT},\n    {RHIFormat::R16G16_FLOAT, VK_FORMAT_R16G16_SFLOAT},\n    {RHIFormat::R10G10B10A2_UNORM, VK_FORMAT_A2B10G10R10_UNORM_PACK32},\n    {RHIFormat::R10G10B10A2_UINT, VK_FORMAT_A2B10G10R10_UINT_PACK32},\n    {RHIFormat::R11G11B10_FLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32},\n    {RHIFormat::R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT},\n    {RHIFormat::R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT},\n    {RHIFormat::R16G16B16A16_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT},\n    {RHIFormat::R32_UINT, VK_FORMAT_R32_UINT},\n    {RHIFormat::R32_SINT, VK_FORMAT_R32_SINT},\n    {RHIFormat::R32_FLOAT, VK_FORMAT_R32_SFLOAT},\n    {RHIFormat::R32G32_UINT, VK_FORMAT_R32G32_UINT},\n    {RHIFormat::R32G32_SINT, VK_FORMAT_R32G32_SINT},\n    {RHIFormat::R32G32_FLOAT, VK_FORMAT_R32G32_SFLOAT},\n    {RHIFormat::R32G32B32_UINT, VK_FORMAT_R32G32B32_UINT},\n    {RHIFormat::R32G32B32_SINT, VK_FORMAT_R32G32B32_SINT},\n    {RHIFormat::R32G32B32_FLOAT, VK_FORMAT_R32G32B32_SFLOAT},\n    {RHIFormat::R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT},\n    {RHIFormat::R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT},\n    {RHIFormat::R32G32B32A32_FLOAT, VK_FORMAT_R32G32B32A32_SFLOAT},\n    {RHIFormat::D32_FLOAT, VK_FORMAT_D32_SFLOAT},\n    {RHIFormat::D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},\n};\n\ninline static std::unordered_map<uint32_t, VkSampleCountFlagBits> ToVulkanSampleCountFlag = {\n    {1, VK_SAMPLE_COUNT_1_BIT},\n    {2, VK_SAMPLE_COUNT_2_BIT},\n    {4, VK_SAMPLE_COUNT_4_BIT},\n    {8, VK_SAMPLE_COUNT_8_BIT},\n    {16, VK_SAMPLE_COUNT_16_BIT},\n    {32, VK_SAMPLE_COUNT_32_BIT},\n    {64, VK_SAMPLE_COUNT_64_BIT},\n};\n\ninline static std::unordered_map<RHITextureDimension, VkImageViewType> ToVulkanImageViewType = {\n    {RHITextureDimension::Texture1D, VK_IMAGE_VIEW_TYPE_1D},\n    {RHITextureDimension::Texture2D, VK_IMAGE_VIEW_TYPE_2D},\n    {RHITextureDimension::Texture3D, VK_IMAGE_VIEW_TYPE_3D},\n    {RHITextureDimension::TextureCube, VK_IMAGE_VIEW_TYPE_CUBE},\n    {RHITextureDimension::Texture1DArray, VK_IMAGE_VIEW_TYPE_1D_ARRAY},\n    {RHITextureDimension::Texture2DArray, VK_IMAGE_VIEW_TYPE_2D_ARRAY},\n    {RHITextureDimension::TextureCubeArray, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY},\n};\n\ninline static std::unordered_map<RHIMemoryUsage, VmaMemoryUsage> ToVmaMemoryUsage = {\n    {RHIMemoryUsage::GPU_Only, VMA_MEMORY_USAGE_GPU_ONLY},\n    {RHIMemoryUsage::CPU_TO_GPU, VMA_MEMORY_USAGE_CPU_TO_GPU},\n    {RHIMemoryUsage::GPU_TO_CPU, VMA_MEMORY_USAGE_GPU_TO_CPU},\n};\n\ninline static std::unordered_map<RHIFilter, VkFilter> ToVulkanFilter = {\n    {RHIFilter::Linear, VK_FILTER_LINEAR},\n    {RHIFilter::Nearest, VK_FILTER_NEAREST},\n};\n\ninline static std::unordered_map<RHIMipmapMode, VkSamplerMipmapMode> ToVulkanMipmapMode = {\n    {RHIMipmapMode::Linear, VK_SAMPLER_MIPMAP_MODE_LINEAR},\n    {RHIMipmapMode::Nearest, VK_SAMPLER_MIPMAP_MODE_NEAREST},\n};\n\ninline static std::unordered_map<RHIAddressMode, VkSamplerAddressMode> ToVulkanAddressMode = {\n    {RHIAddressMode::Repeat, VK_SAMPLER_ADDRESS_MODE_REPEAT},\n    {RHIAddressMode::Mirrored_Repeat, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT},\n    {RHIAddressMode::Clamp_To_Edge, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE},\n    {RHIAddressMode::Clamp_To_Border, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER},\n    {RHIAddressMode::Mirror_Clamp_To_Edge, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE},\n};\n\ninline static std::unordered_map<RHISamplerBorderColor, VkBorderColor> ToVulkanBorderColor = {\n    {RHISamplerBorderColor::Float_Transparent_Black, VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK},\n    {RHISamplerBorderColor::Int_Transparent_Black, VK_BORDER_COLOR_INT_TRANSPARENT_BLACK},\n    {RHISamplerBorderColor::Float_Opaque_Black, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK},\n    {RHISamplerBorderColor::Int_Opaque_Black, VK_BORDER_COLOR_INT_OPAQUE_BLACK},\n    {RHISamplerBorderColor::Float_Opaque_White, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE},\n    {RHISamplerBorderColor::Int_Opaque_White, VK_BORDER_COLOR_INT_OPAQUE_WHITE},\n};\n\ninline static std::unordered_map<RHIPrimitiveTopology, VkPrimitiveTopology> ToVulkanPrimitiveTopology = {\n    {RHIPrimitiveTopology::Point, VK_PRIMITIVE_TOPOLOGY_POINT_LIST},\n    {RHIPrimitiveTopology::Line, VK_PRIMITIVE_TOPOLOGY_LINE_LIST},\n    {RHIPrimitiveTopology::Triangle, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST},\n    {RHIPrimitiveTopology::Patch, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST},\n};\n\ninline static std::unordered_map<RHIPolygonMode, VkPolygonMode> ToVulkanPolygonMode = {\n    {RHIPolygonMode::Solid, VK_POLYGON_MODE_FILL},\n    {RHIPolygonMode::Wireframe, VK_POLYGON_MODE_LINE},\n};\n\ninline static std::unordered_map<RHIBlendFactor, VkBlendFactor> ToVulkanBlendFactor = {\n    {RHIBlendFactor::Zero, VK_BLEND_FACTOR_ZERO},\n    {RHIBlendFactor::One, VK_BLEND_FACTOR_ONE},\n    {RHIBlendFactor::Src_Color, VK_BLEND_FACTOR_SRC_COLOR},\n    {RHIBlendFactor::One_Minus_Src_Color, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR},\n    {RHIBlendFactor::Dst_Color, VK_BLEND_FACTOR_DST_COLOR},\n    {RHIBlendFactor::One_Minus_Dst_Color, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR},\n    {RHIBlendFactor::Src_Alpha, VK_BLEND_FACTOR_SRC_ALPHA},\n    {RHIBlendFactor::One_Minus_Src_Alpha, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA},\n    {RHIBlendFactor::Dst_Alpha, VK_BLEND_FACTOR_DST_ALPHA},\n    {RHIBlendFactor::One_Minus_Dst_Alpha, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA},\n    {RHIBlendFactor::Constant_Color, VK_BLEND_FACTOR_CONSTANT_COLOR},\n    {RHIBlendFactor::One_Minus_Constant_Color, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR},\n    {RHIBlendFactor::Constant_Alpha, VK_BLEND_FACTOR_CONSTANT_ALPHA},\n    {RHIBlendFactor::One_Minus_Constant_Alpha, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA},\n    {RHIBlendFactor::Src_Alpha_Saturate, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE},\n    {RHIBlendFactor::Src1_Color, VK_BLEND_FACTOR_SRC1_COLOR},\n    {RHIBlendFactor::One_Minus_Src1_Color, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR},\n    {RHIBlendFactor::Src1_Alpha, VK_BLEND_FACTOR_SRC1_ALPHA},\n    {RHIBlendFactor::One_Minus_Src1_Alpha, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA},\n};\n\ninline static std::unordered_map<RHIBlendOp, VkBlendOp> ToVulkanBlendOp = {\n    {RHIBlendOp::Add, VK_BLEND_OP_ADD},\n    {RHIBlendOp::Subtract, VK_BLEND_OP_SUBTRACT},\n    {RHIBlendOp::Reverse_Subtract, VK_BLEND_OP_REVERSE_SUBTRACT},\n    {RHIBlendOp::Min, VK_BLEND_OP_MIN},\n    {RHIBlendOp::Max, VK_BLEND_OP_MAX},\n};\n\ninline static std::unordered_map<RHILogicOp, VkLogicOp> ToVulkanLogicOp = {\n    {RHILogicOp::Clear, VK_LOGIC_OP_CLEAR},\n    {RHILogicOp::And, VK_LOGIC_OP_AND},\n    {RHILogicOp::And_Reverse, VK_LOGIC_OP_AND_REVERSE},\n    {RHILogicOp::Copy, VK_LOGIC_OP_COPY},\n    {RHILogicOp::And_Inverted, VK_LOGIC_OP_AND_INVERTED},\n    {RHILogicOp::No_Op, VK_LOGIC_OP_NO_OP},\n    {RHILogicOp::XOR, VK_LOGIC_OP_XOR},\n    {RHILogicOp::Or, VK_LOGIC_OP_OR},\n    {RHILogicOp::Nor, VK_LOGIC_OP_NOR},\n    {RHILogicOp::Equivalent, VK_LOGIC_OP_EQUIVALENT},\n    {RHILogicOp::Invert, VK_LOGIC_OP_INVERT},\n    {RHILogicOp::Or_Reverse, VK_LOGIC_OP_OR_REVERSE},\n    {RHILogicOp::Copy_Inverted, VK_LOGIC_OP_COPY_INVERTED},\n    {RHILogicOp::Or_Inverted, VK_LOGIC_OP_OR_INVERTED},\n    {RHILogicOp::Nand, VK_LOGIC_OP_NAND},\n    {RHILogicOp::Set, VK_LOGIC_OP_SET},\n};\n\ninline static std::unordered_map<RHICompareOp, VkCompareOp> ToVulkanCompareOp = {\n    {RHICompareOp::Never, VK_COMPARE_OP_NEVER},\n    {RHICompareOp::Less, VK_COMPARE_OP_LESS},\n    {RHICompareOp::Equal, VK_COMPARE_OP_EQUAL},\n    {RHICompareOp::Less_Or_Equal, VK_COMPARE_OP_LESS_OR_EQUAL},\n    {RHICompareOp::Greater, VK_COMPARE_OP_GREATER},\n    {RHICompareOp::Not_Equal, VK_COMPARE_OP_NOT_EQUAL},\n    {RHICompareOp::Greater_Or_Equal, VK_COMPARE_OP_GREATER_OR_EQUAL},\n    {RHICompareOp::Always, VK_COMPARE_OP_ALWAYS},\n};\n\ninline static std::unordered_map<RHICullMode, VkCullModeFlagBits> ToVulkanCullMode = {\n    {RHICullMode::None, VK_CULL_MODE_NONE},\n    {RHICullMode::Front, VK_CULL_MODE_FRONT_BIT},\n    {RHICullMode::Back, VK_CULL_MODE_BACK_BIT},\n};\n\ninline static std::unordered_map<RHIFrontFace, VkFrontFace> ToVulkanFrontFace = {\n    {RHIFrontFace::Clockwise, VK_FRONT_FACE_CLOCKWISE},\n    {RHIFrontFace::Clockwise, VK_FRONT_FACE_COUNTER_CLOCKWISE},\n};\n\ninline static std::unordered_map<uint32_t, VkSampleCountFlagBits> ToVulkanSampleCount = {\n    {1, VK_SAMPLE_COUNT_1_BIT},\n    {2, VK_SAMPLE_COUNT_2_BIT},\n    {4, VK_SAMPLE_COUNT_4_BIT},\n    {8, VK_SAMPLE_COUNT_8_BIT},\n    {16, VK_SAMPLE_COUNT_16_BIT},\n    {32, VK_SAMPLE_COUNT_32_BIT},\n    {64, VK_SAMPLE_COUNT_64_BIT},\n};\n\ninline static std::unordered_map<RHIShaderStage, VkShaderStageFlagBits> ToVulkanShaderStage = {\n    {RHIShaderStage::Vertex, VK_SHADER_STAGE_VERTEX_BIT},\n    {RHIShaderStage::TessellationControl, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT},\n    {RHIShaderStage::TessellationEvaluation, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT},\n    {RHIShaderStage::Geometry, VK_SHADER_STAGE_GEOMETRY_BIT},\n    {RHIShaderStage::Fragment, VK_SHADER_STAGE_FRAGMENT_BIT},\n    {RHIShaderStage::Compute, VK_SHADER_STAGE_COMPUTE_BIT},\n    {RHIShaderStage::RayGen, VK_SHADER_STAGE_RAYGEN_BIT_KHR},\n    {RHIShaderStage::AnyHit, VK_SHADER_STAGE_ANY_HIT_BIT_KHR},\n    {RHIShaderStage::ClosestHit, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR},\n    {RHIShaderStage::Miss, VK_SHADER_STAGE_MISS_BIT_KHR},\n    {RHIShaderStage::Intersection, VK_SHADER_STAGE_INTERSECTION_BIT_KHR},\n    {RHIShaderStage::Callable, VK_SHADER_STAGE_CALLABLE_BIT_KHR},\n    {RHIShaderStage::Mesh, VK_SHADER_STAGE_MESH_BIT_EXT},\n    {RHIShaderStage::Task, VK_SHADER_STAGE_TASK_BIT_EXT},\n};\n\ninline static std::unordered_map<RHIVertexInputRate, VkVertexInputRate> ToVulkanVertexInputRate = {\n    {RHIVertexInputRate::Instance, VK_VERTEX_INPUT_RATE_INSTANCE},\n    {RHIVertexInputRate::Vertex, VK_VERTEX_INPUT_RATE_VERTEX},\n};\n\ninline static std::unordered_map<RHILoadAction, VkAttachmentLoadOp> ToVulkanLoadOp = {\n    {RHILoadAction::DontCare, VK_ATTACHMENT_LOAD_OP_DONT_CARE},\n    {RHILoadAction::Clear, VK_ATTACHMENT_LOAD_OP_CLEAR},\n    {RHILoadAction::Load, VK_ATTACHMENT_LOAD_OP_LOAD},\n};\n\ninline static std::unordered_map<RHIStoreAction, VkAttachmentStoreOp> ToVulkanStoreOp = {\n    {RHIStoreAction::DontCare, VK_ATTACHMENT_STORE_OP_DONT_CARE},\n    {RHIStoreAction::Store, VK_ATTACHMENT_STORE_OP_STORE},\n};\n\ninline static VkImageUsageFlags ToVulkanImageUsage(RHITextureUsage usage)\n{\n\tVkImageUsageFlags vk_usage = 0;\n\n\tif (usage & RHITextureUsage::Transfer)\n\t{\n\t\tvk_usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;\n\t}\n\tif (usage & RHITextureUsage::ShaderResource)\n\t{\n\t\tvk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;\n\t}\n\tif (usage & RHITextureUsage::UnorderedAccess)\n\t{\n\t\tvk_usage |= VK_IMAGE_USAGE_STORAGE_BIT;\n\t}\n\n\treturn vk_usage;\n}\n\ninline static VkBufferUsageFlags ToVulkanBufferUsage(RHIBufferUsage usage)\n{\n\tVkBufferUsageFlags vk_usage = 0;\n\n\tif (usage & RHIBufferUsage::AccelerationStructure)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |\n\t\t            VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR;\n\t}\n\tif (usage & RHIBufferUsage::Index)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;\n\t}\n\tif (usage & RHIBufferUsage::Vertex)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;\n\t}\n\tif (usage & RHIBufferUsage::Indirect)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;\n\t}\n\tif (usage & RHIBufferUsage::Transfer)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT |\n\t\t            VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\t}\n\tif (usage & RHIBufferUsage::ConstantBuffer)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;\n\t}\n\tif (usage & RHIBufferUsage::UnorderedAccess)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |\n\t\t            VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;\n\t}\n\tif (usage & RHIBufferUsage::ShaderResource)\n\t{\n\t\tvk_usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;\n\t}\n\n\treturn vk_usage;\n}\n\ninline static VkShaderStageFlags ToVulkanShaderStages(RHIShaderStage stage)\n{\n\tVkShaderStageFlags flag = 0;\n\n\tif (stage & RHIShaderStage::Compute)\n\t{\n\t\tflag |= VK_SHADER_STAGE_COMPUTE_BIT;\n\t}\n\tif (stage & RHIShaderStage::Vertex)\n\t{\n\t\tflag |= VK_SHADER_STAGE_VERTEX_BIT;\n\t}\n\tif (stage & RHIShaderStage::Fragment)\n\t{\n\t\tflag |= VK_SHADER_STAGE_FRAGMENT_BIT;\n\t}\n\tif (stage & RHIShaderStage::TessellationControl)\n\t{\n\t\tflag |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;\n\t}\n\tif (stage & RHIShaderStage::TessellationEvaluation)\n\t{\n\t\tflag |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;\n\t}\n\tif (stage & RHIShaderStage::Geometry)\n\t{\n\t\tflag |= VK_SHADER_STAGE_GEOMETRY_BIT;\n\t}\n\tif (stage & RHIShaderStage::RayGen)\n\t{\n\t\tflag |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;\n\t}\n\tif (stage & RHIShaderStage::AnyHit)\n\t{\n\t\tflag |= VK_SHADER_STAGE_ANY_HIT_BIT_KHR;\n\t}\n\tif (stage & RHIShaderStage::ClosestHit)\n\t{\n\t\tflag |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;\n\t}\n\tif (stage & RHIShaderStage::Miss)\n\t{\n\t\tflag |= VK_SHADER_STAGE_MISS_BIT_KHR;\n\t}\n\tif (stage & RHIShaderStage::Intersection)\n\t{\n\t\tflag |= VK_SHADER_STAGE_INTERSECTION_BIT_KHR;\n\t}\n\tif (stage & RHIShaderStage::Callable)\n\t{\n\t\tflag |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;\n\t}\n\tif (stage & RHIShaderStage::Task)\n\t{\n\t\tflag |= VK_SHADER_STAGE_TASK_BIT_NV;\n\t}\n\tif (stage & RHIShaderStage::Mesh)\n\t{\n\t\tflag |= VK_SHADER_STAGE_MESH_BIT_NV;\n\t}\n\n\treturn flag;\n}\n\n#ifdef CUDA_ENABLE\nclass WindowsSecurityAttributes\n{\n  public:\n\tWindowsSecurityAttributes();\n\n\tSECURITY_ATTRIBUTES *operator&();\n\n\t~WindowsSecurityAttributes();\n\n  protected:\n\tSECURITY_ATTRIBUTES  m_winSecurityAttributes;\n\tPSECURITY_DESCRIPTOR m_winPSecurityDescriptor;\n};\n#endif\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Descriptor.cpp",
    "content": "#include \"Descriptor.hpp\"\n#include \"AccelerationStructure.hpp\"\n#include \"Buffer.hpp\"\n#include \"Definitions.hpp\"\n#include \"Device.hpp\"\n#include \"Sampler.hpp\"\n#include \"Texture.hpp\"\n\nnamespace Ilum::Vulkan\n{\ninline static std::unordered_map<std::thread::id, VkDescriptorPool> DescriptorPools;\ninline static std::unordered_map<size_t, VkDescriptorSetLayout>     DescriptorSetLayouts;\ninline static std::unordered_map<size_t, VkDescriptorSet>           DescriptorSet;\n\ninline static std::atomic<uint32_t> DescriptorCount    = 0;\ninline static uint32_t              MaxDescriptorCount = 16384ul;\n\ninline static std::unordered_map<DescriptorType, VkDescriptorType> DescriptorTypeMap = {\n    {DescriptorType::Sampler, VK_DESCRIPTOR_TYPE_SAMPLER},\n    {DescriptorType::TextureSRV, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE},\n    {DescriptorType::TextureUAV, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE},\n    {DescriptorType::ConstantBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER},\n    {DescriptorType::StructuredBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER},\n    {DescriptorType::AccelerationStructure, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR},\n};\n\nDescriptor::Descriptor(RHIDevice *device, const ShaderMeta &meta) :\n    RHIDescriptor(device, meta)\n{\n\tDescriptorCount.fetch_add(1);\n\n\tstd::unordered_map<uint32_t, ShaderMeta> set_meta;\n\tfor (auto &descriptor : m_meta.descriptors)\n\t{\n\t\tset_meta[descriptor.set].descriptors.emplace_back(descriptor);\n\t\tHashCombine(\n\t\t    set_meta[descriptor.set].hash,\n\t\t    descriptor.array_size,\n\t\t    descriptor.binding,\n\t\t    descriptor.name,\n\t\t    descriptor.set,\n\t\t    descriptor.stage,\n\t\t    descriptor.type);\n\n\t\tm_binding_hash[descriptor.name]      = 0;\n\t\tm_descriptor_lookup[descriptor.name] = std::make_pair(descriptor.set, descriptor.binding);\n\n\t\tswitch (descriptor.type)\n\t\t{\n\t\t\tcase DescriptorType::TextureSRV:\n\t\t\t\tm_texture_resolves.emplace(descriptor.name, TextureResolve{descriptor.set, descriptor.binding, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL});\n\t\t\t\tbreak;\n\t\t\tcase DescriptorType::TextureUAV:\n\t\t\t\tm_texture_resolves.emplace(descriptor.name, TextureResolve{descriptor.set, descriptor.binding, VK_IMAGE_LAYOUT_GENERAL});\n\t\t\t\tbreak;\n\t\t\tcase DescriptorType::Sampler:\n\t\t\t\tm_texture_resolves.emplace(descriptor.name, TextureResolve{descriptor.set, descriptor.binding});\n\t\t\t\tbreak;\n\t\t\tcase DescriptorType::ConstantBuffer:\n\t\t\tcase DescriptorType::StructuredBuffer:\n\t\t\t\tm_buffer_resolves.emplace(descriptor.name, BufferResolve{descriptor.set, descriptor.binding});\n\t\t\t\tbreak;\n\t\t\tcase DescriptorType::AccelerationStructure:\n\t\t\t\tm_acceleration_structure_resolves.emplace(descriptor.name, AccelerationStructureResolve{descriptor.set, descriptor.binding});\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tfor (auto &constant : m_meta.constants)\n\t{\n\t\tif (m_constant_resolves.find(constant.name) != m_constant_resolves.end())\n\t\t{\n\t\t\tm_constant_resolves[constant.name].stage |= ToVulkanShaderStages(constant.stage);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_constant_resolves.emplace(\n\t\t\t    constant.name,\n\t\t\t    ConstantResolve{\n\t\t\t        std::vector<uint8_t>(constant.size),\n\t\t\t        constant.offset,\n\t\t\t        ToVulkanShaderStages(constant.stage)});\n\t\t}\n\t}\n\n\tfor (auto &[set, meta] : set_meta)\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\t// Create descriptor set layout\n\t\tVkDescriptorSetLayout layout = VK_NULL_HANDLE;\n\t\tif (DescriptorSetLayouts.find(meta.hash) == DescriptorSetLayouts.end())\n\t\t{\n\t\t\tlayout = CreateDescriptorSetLayout(meta);\n\t\t\tDescriptorSetLayouts.emplace(meta.hash, layout);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlayout = DescriptorSetLayouts[meta.hash];\n\t\t}\n\t\tm_descriptor_set_layouts.emplace(set, layout);\n\n\t\tm_binding_dirty.emplace(set, false);\n\t}\n}\n\nDescriptor ::~Descriptor()\n{\n\tm_descriptor_set_layouts.clear();\n\tm_descriptor_sets.clear();\n\n\tDescriptorCount.fetch_sub(1);\n\n\tif (DescriptorCount == 0)\n\t{\n\t\tfor (auto &[thread_id, descriptor_pool] : DescriptorPools)\n\t\t{\n\t\t\tvkDestroyDescriptorPool(static_cast<Device *>(p_device)->GetDevice(), descriptor_pool, nullptr);\n\t\t\tdescriptor_pool = VK_NULL_HANDLE;\n\t\t}\n\t\tfor (auto &[hash, layout] : DescriptorSetLayouts)\n\t\t{\n\t\t\tvkDestroyDescriptorSetLayout(static_cast<Device *>(p_device)->GetDevice(), layout, nullptr);\n\t\t}\n\t\tDescriptorSetLayouts.clear();\n\t}\n}\n\nRHIDescriptor &Descriptor::BindTexture(const std::string &name, RHITexture *texture, RHITextureDimension dimension)\n{\n\tTextureRange range = {};\n\trange.dimension    = dimension;\n\trange.base_layer   = 0;\n\trange.layer_count  = texture->GetDesc().layers;\n\trange.base_mip     = 0;\n\trange.mip_count    = texture->GetDesc().mips;\n\n\treturn BindTexture(name, texture, range);\n}\n\nRHIDescriptor &Descriptor::BindTexture(const std::string &name, RHITexture *texture, const TextureRange &range)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t hash = 0;\n\tHashCombine(hash, texture, range.dimension, range.base_mip, range.mip_count, range.base_layer, range.layer_count);\n\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tVkImageView view = static_cast<Texture *>(texture)->GetView(range);\n\n\t\tm_texture_resolves[name].views = {view};\n\t\tm_binding_hash[name]           = hash;\n\n\t\tm_binding_dirty[m_descriptor_lookup[name].first] = true;\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindTexture(const std::string &name, const std::vector<RHITexture *> &textures, RHITextureDimension dimension)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t hash = 0;\n\tHashCombine(hash, textures, dimension);\n\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tm_texture_resolves[name].views.clear();\n\t\tm_texture_resolves[name].views.reserve(textures.size());\n\n\t\tfor (auto *texture : textures)\n\t\t{\n\t\t\tTextureRange range = {};\n\t\t\trange.dimension    = dimension;\n\t\t\trange.base_layer   = 0;\n\t\t\trange.base_mip     = 0;\n\t\t\trange.layer_count  = texture->GetDesc().layers;\n\t\t\trange.mip_count    = texture->GetDesc().mips;\n\t\t\tVkImageView view   = static_cast<Texture *>(texture)->GetView(range);\n\n\t\t\tm_texture_resolves[name].views.push_back(view);\n\t\t}\n\n\t\tm_binding_hash[name] = hash;\n\n\t\tm_binding_dirty[m_descriptor_lookup[name].first] = true;\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindSampler(const std::string &name, RHISampler *sampler)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t hash = 0;\n\tHashCombine(hash, sampler);\n\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tm_texture_resolves[name].samplers = {static_cast<Sampler *>(sampler)->GetHandle()};\n\n\t\tm_binding_hash[name] = hash;\n\n\t\tm_binding_dirty[m_descriptor_lookup[name].first] = true;\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindSampler(const std::string &name, const std::vector<RHISampler *> &samplers)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t hash = 0;\n\tHashCombine(hash, samplers);\n\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tm_texture_resolves[name].samplers.clear();\n\t\tm_texture_resolves[name].samplers.reserve(samplers.size());\n\n\t\tfor (auto *sampler : samplers)\n\t\t{\n\t\t\tm_texture_resolves[name].samplers.push_back(static_cast<Sampler *>(sampler)->GetHandle());\n\t\t}\n\n\t\tm_binding_hash[name] = hash;\n\n\t\tm_binding_dirty[m_descriptor_lookup[name].first] = true;\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindBuffer(const std::string &name, RHIBuffer *buffer)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tif (buffer)\n\t{\n\t\treturn BindBuffer(name, buffer, 0, buffer->GetDesc().size);\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindBuffer(const std::string &name, RHIBuffer *buffer, size_t offset, size_t range)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t   hash          = 0;\n\tVkBuffer buffer_handle = static_cast<Buffer *>(buffer)->GetHandle();\n\tHashCombine(hash, buffer_handle, offset, range);\n\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tm_buffer_resolves[name].buffers = {buffer_handle};\n\t\tm_buffer_resolves[name].ranges  = {range};\n\t\tm_buffer_resolves[name].offsets = {offset};\n\n\t\tm_binding_hash[name] = hash;\n\n\t\tm_binding_dirty[m_descriptor_lookup[name].first] = true;\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindBuffer(const std::string &name, const std::vector<RHIBuffer *> &buffers)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t hash = 0;\n\tHashCombine(hash, buffers);\n\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tm_buffer_resolves[name].buffers.clear();\n\t\tm_buffer_resolves[name].buffers.reserve(buffers.size());\n\t\tm_buffer_resolves[name].ranges.clear();\n\t\tm_buffer_resolves[name].ranges.reserve(buffers.size());\n\t\tm_buffer_resolves[name].offsets.clear();\n\t\tm_buffer_resolves[name].offsets.reserve(buffers.size());\n\n\t\tfor (auto *buffer : buffers)\n\t\t{\n\t\t\tm_buffer_resolves[name].buffers.push_back(static_cast<Buffer *>(buffer)->GetHandle());\n\t\t\tm_buffer_resolves[name].ranges.push_back(buffer->GetDesc().size);\n\t\t\tm_buffer_resolves[name].offsets.push_back(0);\n\t\t}\n\n\t\tm_binding_hash[name] = hash;\n\n\t\tm_binding_dirty[m_descriptor_lookup[name].first] = true;\n\t}\n\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindConstant(const std::string &name, const void *constant)\n{\n\tstd::memcpy(m_constant_resolves[name].data.data(), constant, m_constant_resolves[name].data.size());\n\treturn *this;\n}\n\nRHIDescriptor &Descriptor::BindAccelerationStructure(const std::string &name, RHIAccelerationStructure *acceleration_structure)\n{\n\tif (m_binding_hash.find(name) == m_binding_hash.end())\n\t{\n\t\treturn *this;\n\t}\n\n\tsize_t hash = Hash(static_cast<AccelerationStructure *>(acceleration_structure)->GetHandle());\n\tif (m_binding_hash[name] != hash)\n\t{\n\t\tm_acceleration_structure_resolves[name].acceleration_structures = {static_cast<AccelerationStructure *>(acceleration_structure)->GetHandle()};\n\t\tm_binding_hash[name]                                            = hash;\n\t\tm_binding_dirty[m_descriptor_lookup[name].first]                = true;\n\t}\n\n\treturn *this;\n}\n\nconst std::unordered_map<uint32_t, VkDescriptorSet> &Descriptor::GetDescriptorSet()\n{\n\t// Check update\n\tfor (auto &[set, dirty] : m_binding_dirty)\n\t{\n\t\tsize_t hash = Hash(m_descriptor_set_layouts.at(set), std::this_thread::get_id());\n\t\tfor (auto &[name, binding_hash] : m_binding_hash)\n\t\t{\n\t\t\tif (m_descriptor_lookup[name].first == set)\n\t\t\t{\n\t\t\t\tHashCombine(hash, binding_hash);\n\t\t\t}\n\t\t}\n\n\t\tif (DescriptorSet.find(hash) != DescriptorSet.end())\n\t\t{\n\t\t\tVkDescriptorSet descriptor_set = DescriptorSet[hash];\n\t\t\tm_descriptor_sets[set]         = descriptor_set;\n\t\t\treturn m_descriptor_sets;\n\t\t}\n\n\t\tif (DescriptorSet.size() >= MaxDescriptorCount)\n\t\t{\n\t\t\tp_device->WaitIdle();\n\t\t\tvkResetDescriptorPool(static_cast<Device *>(p_device)->GetDevice(), CreateDescriptorPool(std::this_thread::get_id()), 0);\n\t\t\tDescriptorSet.clear();\n\t\t}\n\n\t\t// Allocate descriptor set\n\t\tVkDescriptorSetAllocateInfo allocate_info = {};\n\t\tallocate_info.sType                       = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;\n\t\tallocate_info.descriptorPool              = CreateDescriptorPool(std::this_thread::get_id());\n\t\tallocate_info.descriptorSetCount          = 1;\n\t\tallocate_info.pSetLayouts                 = &m_descriptor_set_layouts.at(set);\n\n\t\tVkDescriptorSet descriptor_set = VK_NULL_HANDLE;\n\t\tvkAllocateDescriptorSets(static_cast<Device *>(p_device)->GetDevice(), &allocate_info, &descriptor_set);\n\n\t\t{\n\t\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\t\tDescriptorSet.emplace(hash, descriptor_set);\n\t\t\tm_descriptor_sets[set] = descriptor_set;\n\t\t}\n\n\t\tstd::vector<VkWriteDescriptorSet>                         write_sets;\n\t\tstd::vector<std::vector<VkDescriptorImageInfo>>           image_infos                                  = {};\n\t\tstd::vector<std::vector<VkDescriptorBufferInfo>>          buffer_infos                                 = {};\n\t\tstd::vector<VkWriteDescriptorSetAccelerationStructureKHR> write_descriptor_set_acceleration_structures = {};\n\t\tfor (auto &descriptor : m_meta.descriptors)\n\t\t{\n\t\t\tif (descriptor.set == set)\n\t\t\t{\n\t\t\t\tbool     is_texture       = false;\n\t\t\t\tbool     is_buffer        = false;\n\t\t\t\tbool     is_as            = false;\n\t\t\t\tuint32_t descriptor_count = 0;\n\n\t\t\t\timage_infos.push_back({});\n\t\t\t\tbuffer_infos.push_back({});\n\n\t\t\t\t// Handle Texture\n\t\t\t\tif (descriptor.type == DescriptorType::TextureSRV ||\n\t\t\t\t    descriptor.type == DescriptorType::TextureUAV)\n\t\t\t\t{\n\t\t\t\t\tis_texture = true;\n\t\t\t\t\tfor (auto &view : m_texture_resolves[descriptor.name].views)\n\t\t\t\t\t{\n\t\t\t\t\t\timage_infos.back().push_back(VkDescriptorImageInfo{\n\t\t\t\t\t\t    VK_NULL_HANDLE,\n\t\t\t\t\t\t    view,\n\t\t\t\t\t\t    m_texture_resolves[descriptor.name].layout});\n\t\t\t\t\t}\n\t\t\t\t\tdescriptor_count = static_cast<uint32_t>(image_infos.back().size());\n\t\t\t\t}\n\n\t\t\t\t// Handle Sampler\n\t\t\t\tif (descriptor.type == DescriptorType::Sampler)\n\t\t\t\t{\n\t\t\t\t\tis_texture = true;\n\t\t\t\t\tfor (auto &sampler : m_texture_resolves[descriptor.name].samplers)\n\t\t\t\t\t{\n\t\t\t\t\t\timage_infos.back().push_back(VkDescriptorImageInfo{\n\t\t\t\t\t\t    sampler,\n\t\t\t\t\t\t    VK_NULL_HANDLE,\n\t\t\t\t\t\t    VK_IMAGE_LAYOUT_UNDEFINED});\n\t\t\t\t\t}\n\t\t\t\t\tdescriptor_count = static_cast<uint32_t>(image_infos.back().size());\n\t\t\t\t}\n\n\t\t\t\t// Handle Buffer\n\t\t\t\tif (descriptor.type == DescriptorType::ConstantBuffer ||\n\t\t\t\t    descriptor.type == DescriptorType::StructuredBuffer)\n\t\t\t\t{\n\t\t\t\t\tis_buffer = true;\n\t\t\t\t\tfor (uint32_t i = 0; i < m_buffer_resolves[descriptor.name].buffers.size(); i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tbuffer_infos.back().push_back(VkDescriptorBufferInfo{\n\t\t\t\t\t\t    m_buffer_resolves[descriptor.name].buffers[i],\n\t\t\t\t\t\t    m_buffer_resolves[descriptor.name].offsets[i],\n\t\t\t\t\t\t    m_buffer_resolves[descriptor.name].ranges[i]});\n\t\t\t\t\t}\n\t\t\t\t\tdescriptor_count = static_cast<uint32_t>(buffer_infos.back().size());\n\t\t\t\t}\n\n\t\t\t\t// Handle Acceleration Structure\n\t\t\t\tif (descriptor.type == DescriptorType::AccelerationStructure)\n\t\t\t\t{\n\t\t\t\t\tis_as = true;\n\n\t\t\t\t\tVkWriteDescriptorSetAccelerationStructureKHR write_set_as = {};\n\t\t\t\t\twrite_set_as.sType                                        = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;\n\t\t\t\t\twrite_set_as.accelerationStructureCount                   = static_cast<uint32_t>(m_acceleration_structure_resolves[descriptor.name].acceleration_structures.size());\n\t\t\t\t\twrite_set_as.pAccelerationStructures                      = m_acceleration_structure_resolves[descriptor.name].acceleration_structures.data();\n\t\t\t\t\twrite_descriptor_set_acceleration_structures.push_back(write_set_as);\n\n\t\t\t\t\tdescriptor_count = static_cast<uint32_t>(m_acceleration_structure_resolves[descriptor.name].acceleration_structures.size());\n\t\t\t\t}\n\n\t\t\t\tVkWriteDescriptorSet write_set = {};\n\t\t\t\twrite_set.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;\n\t\t\t\twrite_set.dstSet               = m_descriptor_sets[set];\n\t\t\t\twrite_set.dstBinding           = descriptor.binding;\n\t\t\t\twrite_set.dstArrayElement      = 0;\n\t\t\t\twrite_set.descriptorCount      = descriptor_count;\n\t\t\t\twrite_set.descriptorType       = DescriptorTypeMap[descriptor.type];\n\t\t\t\twrite_set.pImageInfo           = is_texture ? image_infos.back().data() : nullptr;\n\t\t\t\twrite_set.pBufferInfo          = is_buffer ? buffer_infos.back().data() : nullptr;\n\t\t\t\twrite_set.pTexelBufferView     = nullptr;\n\t\t\t\twrite_set.pNext                = is_as ? &write_descriptor_set_acceleration_structures.back() : nullptr;\n\t\t\t\twrite_sets.push_back(write_set);\n\t\t\t}\n\t\t}\n\n\t\tvkUpdateDescriptorSets(static_cast<Device *>(p_device)->GetDevice(), static_cast<uint32_t>(write_sets.size()), write_sets.data(), 0, nullptr);\n\t}\n\n\treturn m_descriptor_sets;\n}\n\nconst std::unordered_map<uint32_t, VkDescriptorSetLayout> &Descriptor::GetDescriptorSetLayout()\n{\n\treturn m_descriptor_set_layouts;\n}\n\nconst std::map<std::string, ConstantResolve> &Descriptor::GetConstantResolve() const\n{\n\treturn m_constant_resolves;\n}\n\nVkDescriptorPool Descriptor::CreateDescriptorPool(const std::thread::id &thread_id)\n{\n\tif (DescriptorPools.find(thread_id) != DescriptorPools.end())\n\t{\n\t\treturn DescriptorPools.at(thread_id);\n\t}\n\n\tVkPhysicalDeviceProperties properties = {};\n\tvkGetPhysicalDeviceProperties(static_cast<Device *>(p_device)->GetPhysicalDevice(), &properties);\n\n\tVkDescriptorPoolSize pool_sizes[] =\n\t    {\n\t        {VK_DESCRIPTOR_TYPE_SAMPLER, properties.limits.maxDescriptorSetSamplers},\n\t        {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, properties.limits.maxDescriptorSetSampledImages},\n\t        {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, properties.limits.maxDescriptorSetStorageImages},\n\t        {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, properties.limits.maxDescriptorSetUniformBuffers},\n\t        {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, properties.limits.maxDescriptorSetStorageBuffers},\n\t        {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1024},\n\t    };\n\t// Create descriptor pool\n\tVkDescriptorPoolCreateInfo descriptor_pool_create_info = {};\n\tdescriptor_pool_create_info.sType                      = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;\n\tdescriptor_pool_create_info.pPoolSizes                 = pool_sizes;\n\tdescriptor_pool_create_info.poolSizeCount              = 6;\n\tdescriptor_pool_create_info.maxSets                    = MaxDescriptorCount;\n\tdescriptor_pool_create_info.flags                      = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;\n\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\tDescriptorPools[thread_id] = VK_NULL_HANDLE;\n\t\tvkCreateDescriptorPool(static_cast<Device *>(p_device)->GetDevice(), &descriptor_pool_create_info, nullptr, &DescriptorPools[thread_id]);\n\t}\n\n\treturn DescriptorPools[thread_id];\n}\n\nVkDescriptorSetLayout Descriptor::CreateDescriptorSetLayout(const ShaderMeta &meta)\n{\n\tstd::vector<VkDescriptorBindingFlags>     descriptor_binding_flags       = {};\n\tstd::vector<VkDescriptorSetLayoutBinding> descriptor_set_layout_bindings = {};\n\n\tVkDescriptorBindingFlags binding_flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;\n\n\tfor (const auto &descriptor : meta.descriptors)\n\t{\n\t\tVkDescriptorSetLayoutBinding layout_binding = {};\n\t\tlayout_binding.binding                      = descriptor.binding;\n\t\tlayout_binding.descriptorType               = DescriptorTypeMap[descriptor.type];\n\t\tlayout_binding.stageFlags                   = ToVulkanShaderStages(descriptor.stage);\n\t\tlayout_binding.descriptorCount              = descriptor.array_size == 0 ? 16384 : descriptor.array_size;\n\t\tdescriptor_set_layout_bindings.push_back(layout_binding);\n\t\tif (descriptor.type != DescriptorType::AccelerationStructure)\n\t\t{\n\t\t\tdescriptor_binding_flags.push_back(binding_flags | (descriptor.array_size == 0 ? VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT : 0));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdescriptor_binding_flags.push_back(0);\n\t\t}\n\t}\n\n\tVkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = {};\n\tdescriptor_set_layout_create_info.sType                           = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;\n\tdescriptor_set_layout_create_info.bindingCount                    = static_cast<uint32_t>(descriptor_set_layout_bindings.size());\n\tdescriptor_set_layout_create_info.pBindings                       = descriptor_set_layout_bindings.data();\n\tdescriptor_set_layout_create_info.flags                           = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT;\n\n\tVkDescriptorSetLayoutBindingFlagsCreateInfo descriptor_set_layout_binding_flag_create_info = {};\n\tdescriptor_set_layout_binding_flag_create_info.sType                                       = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;\n\tdescriptor_set_layout_binding_flag_create_info.bindingCount                                = static_cast<uint32_t>(descriptor_binding_flags.size());\n\tdescriptor_set_layout_binding_flag_create_info.pBindingFlags                               = descriptor_binding_flags.data();\n\n\tdescriptor_set_layout_create_info.pNext = &descriptor_set_layout_binding_flag_create_info;\n\n\tVkDescriptorSetLayout layout = VK_NULL_HANDLE;\n\tvkCreateDescriptorSetLayout(static_cast<Device *>(p_device)->GetDevice(), &descriptor_set_layout_create_info, nullptr, &layout);\n\n\treturn layout;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Descriptor.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstruct TextureResolve\n{\n\tuint32_t      set     = 0;\n\tuint32_t      binding = 0;\n\tVkImageLayout layout  = VK_IMAGE_LAYOUT_UNDEFINED;\n\n\tstd::vector<VkImageView> views;\n\tstd::vector<VkSampler>   samplers;\n};\n\nstruct BufferResolve\n{\n\tuint32_t set     = 0;\n\tuint32_t binding = 0;\n\n\tstd::vector<VkBuffer> buffers;\n\tstd::vector<size_t>   ranges;\n\tstd::vector<size_t>   offsets;\n};\n\nstruct AccelerationStructureResolve\n{\n\tuint32_t set     = 0;\n\tuint32_t binding = 0;\n\n\tstd::vector<VkAccelerationStructureKHR> acceleration_structures;\n};\n\nstruct ConstantResolve\n{\n\tstd::vector<uint8_t> data;\n\tsize_t             offset = 0;\n\tVkShaderStageFlags stage;\n};\n\nclass Descriptor : public RHIDescriptor\n{\n  public:\n\tDescriptor(RHIDevice *device, const ShaderMeta &meta);\n\n\tvirtual ~Descriptor() override;\n\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, RHITexture *texture, RHITextureDimension dimension) override;\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, RHITexture *texture, const TextureRange &range) override;\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, const std::vector<RHITexture *> &textures, RHITextureDimension dimension) override;\n\n\tvirtual RHIDescriptor &BindSampler(const std::string &name, RHISampler *sampler) override;\n\tvirtual RHIDescriptor &BindSampler(const std::string &name, const std::vector<RHISampler *> &samplers) override;\n\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, RHIBuffer *buffer) override;\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, RHIBuffer *buffer, size_t offset, size_t range) override;\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, const std::vector<RHIBuffer *> &buffers) override;\n\n\tvirtual RHIDescriptor &BindConstant(const std::string &name, const void *constant) override;\n\n\tvirtual RHIDescriptor &BindAccelerationStructure(const std::string &name, RHIAccelerationStructure *acceleration_structure) override;\n\n\tconst std::unordered_map<uint32_t, VkDescriptorSet> &GetDescriptorSet();\n\n\tconst std::unordered_map<uint32_t, VkDescriptorSetLayout> &GetDescriptorSetLayout();\n\n\tconst std::map<std::string, ConstantResolve> &GetConstantResolve() const;\n\n  private:\n\tVkDescriptorPool CreateDescriptorPool(const std::thread::id &thread_id);\n\n\tVkDescriptorSetLayout CreateDescriptorSetLayout(const ShaderMeta &meta);\n\n  private:\n\tstd::unordered_map<uint32_t, VkDescriptorSetLayout> m_descriptor_set_layouts;\n\tstd::unordered_map<uint32_t, VkDescriptorSet>       m_descriptor_sets;\n\n\tstd::unordered_map<std::string, std::pair<uint32_t, uint32_t>> m_descriptor_lookup;\n\n\tstd::map<std::string, TextureResolve>               m_texture_resolves;\n\tstd::map<std::string, BufferResolve>                m_buffer_resolves;\n\tstd::map<std::string, AccelerationStructureResolve> m_acceleration_structure_resolves;\n\tstd::map<std::string, ConstantResolve>              m_constant_resolves;\n\n\tstd::unordered_map<std::string, size_t> m_binding_hash;\n\n\tstd::unordered_map<uint32_t, bool> m_binding_dirty;\n\n\tstd::mutex m_mutex;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Device.cpp",
    "content": "#include \"Device.hpp\"\n\nnamespace Ilum::Vulkan\n{\n// Extension Function\nstatic PFN_vkCreateDebugUtilsMessengerEXT  vkCreateDebugUtilsMessengerEXT;\nstatic VkDebugUtilsMessengerEXT            vkDebugUtilsMessengerEXT;\nstatic PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;\nPFN_vkSetDebugUtilsObjectTagEXT            vkSetDebugUtilsObjectTagEXT;\nPFN_vkSetDebugUtilsObjectNameEXT           vkSetDebugUtilsObjectNameEXT;\nPFN_vkCmdBeginDebugUtilsLabelEXT           vkCmdBeginDebugUtilsLabelEXT;\nPFN_vkCmdEndDebugUtilsLabelEXT             vkCmdEndDebugUtilsLabelEXT;\nPFN_vkGetSemaphoreWin32HandleKHR           vkGetSemaphoreWin32HandleKHR;\nPFN_vkGetMemoryWin32HandleKHR              vkGetMemoryWin32HandleKHR;\n\n// Vulkan Extension\nstatic const std::vector<const char *> InstanceExtensions =\n#ifdef DEBUG\n    {\"VK_KHR_surface\", \"VK_KHR_win32_surface\", \"VK_EXT_debug_report\", \"VK_EXT_debug_utils\"};\n#else\n    {\"VK_KHR_surface\", \"VK_KHR_win32_surface\"};\n#endif\n\nstatic const std::vector<const char *> ValidationLayers =\n#ifdef DEBUG\n    {\"VK_LAYER_KHRONOS_validation\"};\n#else\n    {};\n#endif        // DEBUG\n\nconst std::vector<VkValidationFeatureEnableEXT> ValidationExtensions =\n#ifdef DEBUG\n    {VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT};\n#else\n    {};\n#endif        // DEBUG\n\nstatic const std::vector<const char *> DeviceExtensions = {\n    VK_KHR_SWAPCHAIN_EXTENSION_NAME,\n    VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,\n    VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,\n    VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,\n    VK_KHR_RAY_QUERY_EXTENSION_NAME,\n    VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,\n    VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,\n    VK_EXT_MESH_SHADER_EXTENSION_NAME,\n    VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME,\n    VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,\n    VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,\n    VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,\n    VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME,\n#ifdef _WIN64\n    VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,\n    VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME\n#else\n    VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,\n    VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,\n#endif\n};\n\n// Utilities Function\ninline const std::vector<const char *> GetInstanceExtensionSupported(const std::vector<const char *> &extensions)\n{\n\tuint32_t extension_count = 0;\n\tvkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);\n\n\tstd::vector<VkExtensionProperties> device_extensions(extension_count);\n\tvkEnumerateInstanceExtensionProperties(nullptr, &extension_count, device_extensions.data());\n\n\tstd::vector<const char *> result;\n\n\tfor (const auto &extension : extensions)\n\t{\n\t\tbool found = false;\n\t\tfor (const auto &device_extension : device_extensions)\n\t\t{\n\t\t\tif (strcmp(extension, device_extension.extensionName) == 0)\n\t\t\t{\n\t\t\t\tresult.emplace_back(extension);\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\ninline bool CheckLayerSupported(const char *layer_name)\n{\n\tuint32_t layer_count;\n\tvkEnumerateInstanceLayerProperties(&layer_count, nullptr);\n\n\tstd::vector<VkLayerProperties> layers(layer_count);\n\tvkEnumerateInstanceLayerProperties(&layer_count, layers.data());\n\n\tfor (const auto &layer : layers)\n\t{\n\t\tif (strcmp(layer.layerName, layer_name) == 0)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\ninline uint32_t ScorePhysicalDevice(VkPhysicalDevice physical_device, const std::vector<const char *> &device_extensions, std::vector<const char *> &support_device_extensions)\n{\n\tuint32_t score = 0;\n\n\t// Check extensions\n\tuint32_t device_extension_properties_count = 0;\n\tvkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_properties_count, nullptr);\n\n\tstd::vector<VkExtensionProperties> extension_properties(device_extension_properties_count);\n\tvkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_properties_count, extension_properties.data());\n\n\tfor (auto &device_extension : device_extensions)\n\t{\n\t\tfor (auto &support_extension : extension_properties)\n\t\t{\n\t\t\tif (std::strcmp(device_extension, support_extension.extensionName) == 0)\n\t\t\t{\n\t\t\t\tsupport_device_extensions.push_back(device_extension);\n\t\t\t\tscore += 100;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tVkPhysicalDeviceProperties properties = {};\n\n\tvkGetPhysicalDeviceProperties(physical_device, &properties);\n\n\t// Score discrete gpu\n\tif (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)\n\t{\n\t\tscore += 1000;\n\t}\n\n\tscore += properties.limits.maxImageDimension2D;\n\treturn score;\n}\n\ninline VkPhysicalDevice SelectPhysicalDevice(const std::vector<VkPhysicalDevice> &physical_devices, const std::vector<const char *> &device_extensions, std::vector<const char *> &support_device_extensions)\n{\n\t// Score - GPU\n\tuint32_t         score  = 0;\n\tVkPhysicalDevice handle = VK_NULL_HANDLE;\n\tfor (auto &gpu : physical_devices)\n\t{\n\t\tstd::vector<const char *> support_extensions;\n\n\t\tuint32_t tmp_score = ScorePhysicalDevice(gpu, device_extensions, support_extensions);\n\t\tif (tmp_score > score)\n\t\t{\n\t\t\tscore  = tmp_score;\n\t\t\thandle = gpu;\n\n\t\t\tsupport_device_extensions = std::move(support_extensions);\n\t\t}\n\t}\n\n\treturn handle;\n}\n\ninline std::optional<uint32_t> GetQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> &queue_family_properties, VkQueueFlagBits queue_flag)\n{\n\t// Dedicated queue for compute\n\t// Try to find a queue family index that supports compute but not graphics\n\tif (queue_flag & VK_QUEUE_COMPUTE_BIT)\n\t{\n\t\tfor (uint32_t i = 0; i < static_cast<uint32_t>(queue_family_properties.size()); i++)\n\t\t{\n\t\t\tif ((queue_family_properties[i].queueFlags & queue_flag) && ((queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0))\n\t\t\t{\n\t\t\t\treturn i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Dedicated queue for transfer\n\t// Try to find a queue family index that supports transfer but not graphics and compute\n\tif (queue_flag & VK_QUEUE_TRANSFER_BIT)\n\t{\n\t\tfor (uint32_t i = 0; i < static_cast<uint32_t>(queue_family_properties.size()); i++)\n\t\t{\n\t\t\tif ((queue_family_properties[i].queueFlags & queue_flag) && ((queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) && ((queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0))\n\t\t\t{\n\t\t\t\treturn i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// For other queue types or if no separate compute queue is present, return the first one to support the requested flags\n\tfor (uint32_t i = 0; i < static_cast<uint32_t>(queue_family_properties.size()); i++)\n\t{\n\t\tif (queue_family_properties[i].queueFlags & queue_flag)\n\t\t{\n\t\t\treturn i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn std::optional<uint32_t>();\n}\n\ninline const std::vector<const char *> GetDeviceExtensionSupport(VkPhysicalDevice physical_device, const std::vector<const char *> &extensions)\n{\n\tstd::vector<const char *> result;\n\n\tuint32_t device_extension_properties_count = 0;\n\tvkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_properties_count, nullptr);\n\n\tstd::vector<VkExtensionProperties> extension_properties(device_extension_properties_count);\n\tvkEnumerateDeviceExtensionProperties(physical_device, nullptr, &device_extension_properties_count, extension_properties.data());\n\n\tfor (auto &device_extension : extensions)\n\t{\n\t\tbool enable = false;\n\t\tfor (auto &support_extension : extension_properties)\n\t\t{\n\t\t\tif (std::strcmp(device_extension, support_extension.extensionName) == 0)\n\t\t\t{\n\t\t\t\tresult.push_back(device_extension);\n\t\t\t\tenable = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\nstatic inline VKAPI_ATTR VkBool32 VKAPI_CALL ValidationCallback(VkDebugUtilsMessageSeverityFlagBitsEXT msg_severity, VkDebugUtilsMessageTypeFlagsEXT msg_type, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)\n{\n\tif (msg_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)\n\t{\n\t\tLOG_INFO(callback_data->pMessage);\n\t}\n\telse if (msg_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)\n\t{\n\t\tLOG_WARN(callback_data->pMessage);\n\t}\n\telse if (msg_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)\n\t{\n\t\tLOG_ERROR(callback_data->pMessage);\n\t}\n\n\treturn VK_FALSE;\n}\n\nvoid Device::CreateInstance()\n{\n\t// Initialize volk context\n\tvolkInitialize();\n\n\t// Config application info\n\tVkApplicationInfo app_info{VK_STRUCTURE_TYPE_APPLICATION_INFO};\n\n\tuint32_t sdk_version = VK_HEADER_VERSION_COMPLETE;\n\tuint32_t api_version = 0;\n\n\tPFN_vkEnumerateInstanceVersion enumerate_instance_version = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(vkGetInstanceProcAddr(nullptr, \"vkEnumerateInstanceVersion\"));\n\n\tif (enumerate_instance_version)\n\t{\n\t\tenumerate_instance_version(&api_version);\n\t}\n\telse\n\t{\n\t\tapi_version = VK_VERSION_1_0;\n\t}\n\n\tif (sdk_version > api_version)\n\t{\n\t\tstd::string sdk_version_str = std::to_string(VK_VERSION_MAJOR(sdk_version)) + \".\" + std::to_string(VK_VERSION_MINOR(sdk_version)) + \".\" + std::to_string(VK_VERSION_PATCH(sdk_version));\n\t\tstd::string api_version_str = std::to_string(VK_VERSION_MAJOR(api_version)) + \".\" + std::to_string(VK_VERSION_MINOR(api_version)) + \".\" + std::to_string(VK_VERSION_PATCH(api_version));\n\t\tLOG_WARN(\"Driver support version {} is higher than API version {}, upgrade your VulkanSDK!\", sdk_version_str, api_version_str);\n\t}\n\n\tapp_info.pApplicationName   = \"IlumEngine\";\n\tapp_info.pEngineName        = \"IlumEngine\";\n\tapp_info.engineVersion      = VK_MAKE_VERSION(0, 0, 1);\n\tapp_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);\n\tapp_info.apiVersion         = std::max(sdk_version, api_version);\n\n\t// Check out extensions support\n\tm_supported_instance_extensions = GetInstanceExtensionSupported(InstanceExtensions);\n\n\t// Config instance info\n\tVkInstanceCreateInfo create_info{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};\n\tcreate_info.pApplicationInfo        = &app_info;\n\tcreate_info.enabledExtensionCount   = static_cast<uint32_t>(m_supported_instance_extensions.size());\n\tcreate_info.ppEnabledExtensionNames = m_supported_instance_extensions.data();\n\tcreate_info.enabledLayerCount       = 0;\n\n\t// Enable validation layers\n#ifdef DEBUG\n\tVkValidationFeaturesEXT validation_features{VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT};\n\tvalidation_features.enabledValidationFeatureCount = static_cast<uint32_t>(ValidationExtensions.size());\n\tvalidation_features.pEnabledValidationFeatures    = ValidationExtensions.data();\n\n\t// Enable validation layer\n\tfor (auto &layer : ValidationLayers)\n\t{\n\t\tif (CheckLayerSupported(layer))\n\t\t{\n\t\t\tcreate_info.enabledLayerCount   = static_cast<uint32_t>(ValidationLayers.size());\n\t\t\tcreate_info.ppEnabledLayerNames = ValidationLayers.data();\n\t\t\tcreate_info.pNext               = &validation_features;\n\t\t\tbreak;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLOG_ERROR(\"Validation layer was required, but not avaliable, disabling debugging\");\n\t\t}\n\t}\n#endif        // DEBUG\n\n\t// Create instance\n\tif (vkCreateInstance(&create_info, nullptr, &m_instance) != VK_SUCCESS)\n\t{\n\t\tLOG_ERROR(\"Failed to create vulkan instance!\");\n\t\treturn;\n\t}\n\telse\n\t{\n\t\t// Config to volk\n\t\tvolkLoadInstance(m_instance);\n\t}\n\n\t// Initialize instance extension functions\n\tvkCreateDebugUtilsMessengerEXT  = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(m_instance, \"vkCreateDebugUtilsMessengerEXT\"));\n\tvkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(m_instance, \"vkDestroyDebugUtilsMessengerEXT\"));\n\tvkSetDebugUtilsObjectTagEXT     = reinterpret_cast<PFN_vkSetDebugUtilsObjectTagEXT>(vkGetInstanceProcAddr(m_instance, \"vkSetDebugUtilsObjectTagEXT\"));\n\tvkSetDebugUtilsObjectNameEXT    = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(vkGetInstanceProcAddr(m_instance, \"vkSetDebugUtilsObjectNameEXT\"));\n\tvkCmdBeginDebugUtilsLabelEXT    = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(vkGetInstanceProcAddr(m_instance, \"vkCmdBeginDebugUtilsLabelEXT\"));\n\tvkCmdEndDebugUtilsLabelEXT      = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(vkGetInstanceProcAddr(m_instance, \"vkCmdEndDebugUtilsLabelEXT\"));\n\tvkGetSemaphoreWin32HandleKHR    = reinterpret_cast<PFN_vkGetSemaphoreWin32HandleKHR>(vkGetInstanceProcAddr(m_instance, \"vkGetSemaphoreWin32HandleKHR\"));\n\tvkGetMemoryWin32HandleKHR       = reinterpret_cast<PFN_vkGetMemoryWin32HandleKHR>(vkGetInstanceProcAddr(m_instance, \"vkGetMemoryWin32HandleKHR\"));\n\n\t// Enable debugger\n#ifdef DEBUG\n\tif (vkCreateDebugUtilsMessengerEXT)\n\t{\n\t\tVkDebugUtilsMessengerCreateInfoEXT create_info{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};\n\t\tcreate_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;\n\t\tcreate_info.messageType     = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;\n\t\tcreate_info.pfnUserCallback = ValidationCallback;\n\n\t\tvkCreateDebugUtilsMessengerEXT(m_instance, &create_info, nullptr, &vkDebugUtilsMessengerEXT);\n\t}\n#endif        // DEBUG\n}\n\nvoid Device::CreatePhysicalDevice()\n{\n\tuint32_t physical_device_count = 0;\n\tvkEnumeratePhysicalDevices(m_instance, &physical_device_count, nullptr);\n\n\t// Get all physical devices\n\tstd::vector<VkPhysicalDevice> physical_devices(physical_device_count);\n\tvkEnumeratePhysicalDevices(m_instance, &physical_device_count, physical_devices.data());\n\n\t// Select suitable physical device\n\tm_physical_device = SelectPhysicalDevice(physical_devices, DeviceExtensions, m_supported_device_extensions);\n\n\tVkPhysicalDeviceProperties properties = {};\n\tvkGetPhysicalDeviceProperties(m_physical_device, &properties);\n\tm_name = properties.deviceName;\n}\n\nvoid Device::CreateLogicalDevice()\n{\n\t// Queue supporting\n\tuint32_t queue_family_property_count = 0;\n\tvkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &queue_family_property_count, nullptr);\n\tstd::vector<VkQueueFamilyProperties> queue_family_properties(queue_family_property_count);\n\tvkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &queue_family_property_count, queue_family_properties.data());\n\n\tstd::optional<uint32_t> graphics_family, compute_family, transfer_family, present_family;\n\n\tgraphics_family = GetQueueFamilyIndex(queue_family_properties, VK_QUEUE_GRAPHICS_BIT);\n\ttransfer_family = GetQueueFamilyIndex(queue_family_properties, VK_QUEUE_TRANSFER_BIT);\n\tcompute_family  = GetQueueFamilyIndex(queue_family_properties, VK_QUEUE_COMPUTE_BIT);\n\n\tVkQueueFlags support_queues = 0;\n\n\tif (graphics_family.has_value())\n\t{\n\t\tm_graphics_family = graphics_family.value();\n\t\tsupport_queues |= VK_QUEUE_GRAPHICS_BIT;\n\t}\n\n\tif (compute_family.has_value())\n\t{\n\t\tm_compute_family = compute_family.value();\n\t\tsupport_queues |= VK_QUEUE_COMPUTE_BIT;\n\t}\n\n\tif (transfer_family.has_value())\n\t{\n\t\tm_transfer_family = transfer_family.value();\n\t\tsupport_queues |= VK_QUEUE_TRANSFER_BIT;\n\t}\n\n\tif (!graphics_family)\n\t{\n\t\tthrow std::runtime_error(\"Failed to find queue graphics family support!\");\n\t}\n\n\t// Create device queue\n\tstd::vector<VkDeviceQueueCreateInfo> queue_create_infos;\n\n\tuint32_t max_count = 0;\n\tfor (auto &queue_family_property : queue_family_properties)\n\t{\n\t\tmax_count = max_count < queue_family_property.queueCount ? queue_family_property.queueCount : max_count;\n\t}\n\n\tstd::vector<float> queue_priorities(max_count, 1.f);\n\n\tif (support_queues & VK_QUEUE_GRAPHICS_BIT)\n\t{\n\t\tVkDeviceQueueCreateInfo graphics_queue_create_info = {};\n\t\tgraphics_queue_create_info.sType                   = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;\n\t\tgraphics_queue_create_info.queueFamilyIndex        = m_graphics_family;\n\t\tgraphics_queue_create_info.queueCount              = queue_family_properties[m_graphics_family].queueCount;\n\t\tgraphics_queue_create_info.pQueuePriorities        = queue_priorities.data();\n\t\tqueue_create_infos.emplace_back(graphics_queue_create_info);\n\t\tm_graphics_queue_count = queue_family_properties[m_graphics_family].queueCount;\n\t}\n\telse\n\t{\n\t\tm_graphics_family = 0;\n\t}\n\n\tif (support_queues & VK_QUEUE_COMPUTE_BIT && m_compute_family != m_graphics_family)\n\t{\n\t\tVkDeviceQueueCreateInfo compute_queue_create_info = {};\n\t\tcompute_queue_create_info.sType                   = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;\n\t\tcompute_queue_create_info.queueFamilyIndex        = m_compute_family;\n\t\tcompute_queue_create_info.queueCount              = queue_family_properties[m_compute_family].queueCount;\n\t\tcompute_queue_create_info.pQueuePriorities        = queue_priorities.data();\n\t\tqueue_create_infos.emplace_back(compute_queue_create_info);\n\t\tm_compute_queue_count = queue_family_properties[m_compute_family].queueCount;\n\t}\n\telse\n\t{\n\t\tm_compute_family      = m_graphics_family;\n\t\tm_compute_queue_count = m_graphics_queue_count;\n\t}\n\n\tif (support_queues & VK_QUEUE_TRANSFER_BIT && m_transfer_family != m_graphics_family && m_transfer_family != m_compute_family)\n\t{\n\t\tVkDeviceQueueCreateInfo transfer_queue_create_info = {};\n\t\ttransfer_queue_create_info.sType                   = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;\n\t\ttransfer_queue_create_info.queueFamilyIndex        = m_transfer_family;\n\t\ttransfer_queue_create_info.queueCount              = queue_family_properties[m_transfer_family].queueCount;\n\t\ttransfer_queue_create_info.pQueuePriorities        = queue_priorities.data();\n\t\tqueue_create_infos.emplace_back(transfer_queue_create_info);\n\t\tm_transfer_queue_count = queue_family_properties[m_transfer_family].queueCount;\n\t}\n\telse\n\t{\n\t\tm_transfer_family      = m_graphics_family;\n\t\tm_transfer_queue_count = m_graphics_queue_count;\n\t}\n\n\t// Enable logical device features\n\tVkPhysicalDeviceFeatures2        physical_device_features          = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};\n\tVkPhysicalDeviceVulkan12Features physical_device_vulkan12_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};\n\tVkPhysicalDeviceVulkan13Features physical_device_vulkan13_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES};\n\n\tphysical_device_features.pNext          = &physical_device_vulkan12_features;\n\tphysical_device_vulkan12_features.pNext = &physical_device_vulkan13_features;\n\n\tvkGetPhysicalDeviceFeatures2(m_physical_device, &physical_device_features);\n\n\tVkPhysicalDeviceFeatures2        physical_device_features_enable          = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};\n\tVkPhysicalDeviceVulkan12Features physical_device_vulkan12_features_enable = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};\n\tVkPhysicalDeviceVulkan13Features physical_device_vulkan13_features_enable = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES};\n\n#define ENABLE_DEVICE_FEATURE(device_feature, device_feature_enable, feature) \\\n\tif (device_feature.feature)                                               \\\n\t{                                                                         \\\n\t\tdevice_feature_enable.feature = VK_TRUE;                              \\\n\t\tm_supported_device_features.push_back(#feature);                      \\\n\t}                                                                         \\\n\telse                                                                      \\\n\t{                                                                         \\\n\t\tLOG_WARN(\"Device feature {} is not supported\", #feature);             \\\n\t}\n\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, sampleRateShading);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, fillModeNonSolid);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, wideLines);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, samplerAnisotropy);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, vertexPipelineStoresAndAtomics);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, fragmentStoresAndAtomics);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, shaderStorageImageExtendedFormats);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, shaderStorageImageWriteWithoutFormat);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, geometryShader);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, tessellationShader);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, multiViewport);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, imageCubeArray);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, robustBufferAccess);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, multiDrawIndirect);\n\tENABLE_DEVICE_FEATURE(physical_device_features.features, physical_device_features_enable.features, drawIndirectFirstInstance);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, drawIndirectCount);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderInputAttachmentArrayDynamicIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderUniformTexelBufferArrayDynamicIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderStorageTexelBufferArrayDynamicIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderUniformBufferArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderSampledImageArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderStorageBufferArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderStorageImageArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderInputAttachmentArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderUniformTexelBufferArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderStorageTexelBufferArrayNonUniformIndexing);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingUniformBufferUpdateAfterBind);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingSampledImageUpdateAfterBind);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingStorageImageUpdateAfterBind);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingStorageBufferUpdateAfterBind);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingUniformTexelBufferUpdateAfterBind);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingStorageTexelBufferUpdateAfterBind);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, descriptorBindingPartiallyBound);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, runtimeDescriptorArray);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, timelineSemaphore);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, bufferDeviceAddress);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderOutputViewportIndex);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan12_features, physical_device_vulkan12_features_enable, shaderOutputLayer);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan13_features, physical_device_vulkan13_features_enable, dynamicRendering);\n\tENABLE_DEVICE_FEATURE(physical_device_vulkan13_features, physical_device_vulkan13_features_enable, maintenance4);\n\n\tm_vulkan_feature_support[VulkanFeature::DynamicRendering] = physical_device_vulkan13_features_enable.dynamicRendering;\n\n\t// Get support extensions\n\tauto support_extensions = GetDeviceExtensionSupport(m_physical_device, DeviceExtensions);\n\n\t{\n\t\tm_feature_support[RHIFeature::RayTracing]       = true;\n\t\tstd::vector<const char *> raytracing_extensions = {\n\t\t    VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,\n\t\t    VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,\n\t\t    VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,\n\t\t    VK_KHR_RAY_QUERY_EXTENSION_NAME};\n\n\t\tfor (auto &raytracing_extension : raytracing_extensions)\n\t\t{\n\t\t\tbool found = false;\n\t\t\tfor (auto &extension : m_supported_device_extensions)\n\t\t\t{\n\t\t\t\tif (strcmp(raytracing_extension, extension) == 0)\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found)\n\t\t\t{\n\t\t\t\tm_feature_support[RHIFeature::RayTracing] = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n\t{\n\t\tm_feature_support[RHIFeature::MeshShading] = false;\n\t\tfor (auto &extension : m_supported_device_extensions)\n\t\t{\n\t\t\tif (strcmp(VK_EXT_MESH_SHADER_EXTENSION_NAME, extension) == 0)\n\t\t\t{\n\t\t\t\tm_feature_support[RHIFeature::MeshShading] = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t{\n\t\tm_feature_support[RHIFeature::BufferDeviceAddress] = false;\n\t\tfor (auto &feature : m_supported_device_features)\n\t\t{\n\t\t\tif (strcmp(\"bufferDeviceAddress\", feature) == 0)\n\t\t\t{\n\t\t\t\tm_feature_support[RHIFeature::BufferDeviceAddress] = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t{\n\t\tm_feature_support[RHIFeature::Bindless] = false;\n\t\tfor (auto &extension : m_supported_device_features)\n\t\t{\n\t\t\tif (strcmp(\"descriptorIndexing\", extension) == 0)\n\t\t\t{\n\t\t\t\tm_feature_support[RHIFeature::Bindless] = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tVkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR};\n\tVkPhysicalDeviceRayTracingPipelineFeaturesKHR    ray_tracing_pipeline_feature   = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR};\n\tVkPhysicalDeviceRayQueryFeaturesKHR              ray_query_features             = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR};\n\tVkPhysicalDeviceMeshShaderFeaturesEXT            mesh_shader_feature            = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT};\n\n\tvoid  *feature_ptr_head = nullptr;\n\tvoid **feature_ptr_tail = nullptr;\n\n\tif (IsFeatureSupport(RHIFeature::RayTracing))\n\t{\n\t\tacceleration_structure_feature.accelerationStructure = VK_TRUE;\n\t\tray_tracing_pipeline_feature.rayTracingPipeline      = VK_TRUE;\n\t\tray_query_features.rayQuery                          = VK_TRUE;\n\n\t\tacceleration_structure_feature.pNext = &ray_tracing_pipeline_feature;\n\t\tray_tracing_pipeline_feature.pNext   = &ray_query_features;\n\n\t\tfeature_ptr_head = &acceleration_structure_feature;\n\t\tfeature_ptr_tail = &ray_query_features.pNext;\n\t}\n\n\tif (IsFeatureSupport(RHIFeature::MeshShading))\n\t{\n\t\tmesh_shader_feature.meshShader          = VK_TRUE;\n\t\tmesh_shader_feature.taskShader          = VK_TRUE;\n\t\tmesh_shader_feature.multiviewMeshShader = VK_TRUE;\n\n\t\tif (!feature_ptr_head)\n\t\t{\n\t\t\tfeature_ptr_head = &mesh_shader_feature;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t*feature_ptr_tail = &mesh_shader_feature;\n\t\t}\n\t\tfeature_ptr_tail = &mesh_shader_feature.pNext;\n\t}\n\n\tphysical_device_vulkan12_features_enable.pNext = &physical_device_vulkan13_features_enable;\n\tphysical_device_vulkan13_features_enable.pNext = feature_ptr_head;\n\n\t// Create device\n\tVkDeviceCreateInfo device_create_info = {};\n\n\tdevice_create_info.sType                = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;\n\tdevice_create_info.queueCreateInfoCount = static_cast<uint32_t>(queue_create_infos.size());\n\tdevice_create_info.pQueueCreateInfos    = queue_create_infos.data();\n\tif (!ValidationLayers.empty())\n\t{\n\t\tdevice_create_info.enabledLayerCount   = static_cast<uint32_t>(ValidationLayers.size());\n\t\tdevice_create_info.ppEnabledLayerNames = ValidationLayers.data();\n\t}\n\tdevice_create_info.enabledExtensionCount   = static_cast<uint32_t>(support_extensions.size());\n\tdevice_create_info.ppEnabledExtensionNames = support_extensions.data();\n\tdevice_create_info.pEnabledFeatures        = &physical_device_features.features;\n\tdevice_create_info.pNext                   = &physical_device_vulkan12_features_enable;\n\n\tif (vkCreateDevice(m_physical_device, &device_create_info, nullptr, &m_logical_device) != VK_SUCCESS)\n\t{\n\t\tLOG_ERROR(\"Failed to create logical device!\");\n\t\treturn;\n\t}\n\n\t// Volk load context\n\tvolkLoadDevice(m_logical_device);\n\n\t// Create Vma allocator\n\tVmaVulkanFunctions vma_vulkan_func{};\n\tvma_vulkan_func.vkGetInstanceProcAddr               = vkGetInstanceProcAddr;\n\tvma_vulkan_func.vkGetDeviceProcAddr                 = vkGetDeviceProcAddr;\n\tvma_vulkan_func.vkAllocateMemory                    = vkAllocateMemory;\n\tvma_vulkan_func.vkBindBufferMemory                  = vkBindBufferMemory;\n\tvma_vulkan_func.vkBindImageMemory                   = vkBindImageMemory;\n\tvma_vulkan_func.vkCreateBuffer                      = vkCreateBuffer;\n\tvma_vulkan_func.vkCreateImage                       = vkCreateImage;\n\tvma_vulkan_func.vkDestroyBuffer                     = vkDestroyBuffer;\n\tvma_vulkan_func.vkDestroyImage                      = vkDestroyImage;\n\tvma_vulkan_func.vkFlushMappedMemoryRanges           = vkFlushMappedMemoryRanges;\n\tvma_vulkan_func.vkFreeMemory                        = vkFreeMemory;\n\tvma_vulkan_func.vkGetBufferMemoryRequirements       = vkGetBufferMemoryRequirements;\n\tvma_vulkan_func.vkGetImageMemoryRequirements        = vkGetImageMemoryRequirements;\n\tvma_vulkan_func.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;\n\tvma_vulkan_func.vkGetPhysicalDeviceProperties       = vkGetPhysicalDeviceProperties;\n\tvma_vulkan_func.vkInvalidateMappedMemoryRanges      = vkInvalidateMappedMemoryRanges;\n\tvma_vulkan_func.vkMapMemory                         = vkMapMemory;\n\tvma_vulkan_func.vkUnmapMemory                       = vkUnmapMemory;\n\tvma_vulkan_func.vkCmdCopyBuffer                     = vkCmdCopyBuffer;\n\n\tVmaAllocatorCreateInfo allocator_info = {};\n\tallocator_info.physicalDevice         = m_physical_device;\n\tallocator_info.device                 = m_logical_device;\n\tallocator_info.instance               = m_instance;\n\tallocator_info.vulkanApiVersion       = VK_API_VERSION_1_3;\n\tallocator_info.flags                  = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;\n\n\tVkPhysicalDeviceMemoryProperties memory_properties = {};\n\tvkGetPhysicalDeviceMemoryProperties(m_physical_device, &memory_properties);\n\n\tallocator_info.pVulkanFunctions = &vma_vulkan_func;\n\n\tif (vmaCreateAllocator(&allocator_info, &m_allocator) != VK_SUCCESS)\n\t{\n\t\tLOG_FATAL(\"Failed to create vulkan memory allocator\");\n\t}\n}\n\nDevice::Device() :\n    RHIDevice(\"Vulkan\")\n{\n\tLOG_INFO(\"Initializing RHI backend Vulkan...\");\n\n\tCreateInstance();\n\tCreatePhysicalDevice();\n\tCreateLogicalDevice();\n}\n\nDevice::~Device()\n{\n\tvkDeviceWaitIdle(m_logical_device);\n\n\tif (m_allocator)\n\t{\n\t\tvmaDestroyAllocator(m_allocator);\n\t}\n\n\tif (m_logical_device)\n\t{\n\t\tvkDestroyDevice(m_logical_device, nullptr);\n\t}\n\n\tif (vkDebugUtilsMessengerEXT)\n\t{\n\t\tvkDestroyDebugUtilsMessengerEXT(m_instance, vkDebugUtilsMessengerEXT, nullptr);\n\t}\n\n\tif (m_instance)\n\t{\n\t\tvkDestroyInstance(m_instance, nullptr);\n\t}\n}\n\nvoid Device::WaitIdle()\n{\n\tvkDeviceWaitIdle(m_logical_device);\n}\n\nbool Device::IsFeatureSupport(RHIFeature feature)\n{\n\treturn m_feature_support[feature];\n}\n\nbool Device::IsFeatureSupport(VulkanFeature feature)\n{\n\treturn m_vulkan_feature_support[feature];\n}\n\nVkInstance Device::GetInstance() const\n{\n\treturn m_instance;\n}\n\nVkPhysicalDevice Device::GetPhysicalDevice() const\n{\n\treturn m_physical_device;\n}\n\nVkDevice Device::GetDevice() const\n{\n\treturn m_logical_device;\n}\n\nVmaAllocator Device::GetAllocator() const\n{\n\treturn m_allocator;\n}\n\nuint32_t Device::GetQueueFamily(RHIQueueFamily family)\n{\n\tswitch (family)\n\t{\n\t\tcase Ilum::RHIQueueFamily::Graphics:\n\t\t\treturn m_graphics_family;\n\t\tcase Ilum::RHIQueueFamily::Compute:\n\t\t\treturn m_compute_family;\n\t\tcase Ilum::RHIQueueFamily::Transfer:\n\t\t\treturn m_transfer_family;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn m_graphics_family;\n}\n\nuint32_t Device::GetQueueCount(RHIQueueFamily family)\n{\n\tswitch (family)\n\t{\n\t\tcase Ilum::RHIQueueFamily::Graphics:\n\t\t\treturn m_graphics_queue_count;\n\t\tcase Ilum::RHIQueueFamily::Compute:\n\t\t\treturn m_compute_queue_count;\n\t\tcase Ilum::RHIQueueFamily::Transfer:\n\t\t\treturn m_transfer_queue_count;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn m_graphics_queue_count;\n}\n\nvoid Device::SetVulkanObjectName(const VkDebugUtilsObjectNameInfoEXT &info)\n{\n#ifdef DEBUG\n\tvkSetDebugUtilsObjectNameEXT(m_logical_device, &info);\n#endif        // DEBUG\n}\n\nvoid Device::BeginDebugUtilsLabel(VkCommandBuffer cmd_buffer, const VkDebugUtilsLabelEXT &label)\n{\n#ifdef DEBUG\n\tvkCmdBeginDebugUtilsLabelEXT(cmd_buffer, &label);\n#endif        // DEBUG\n}\n\nvoid Device::EndDebugUtilsLabel(VkCommandBuffer cmd_buffer)\n{\n#ifdef DEBUG\n\tvkCmdEndDebugUtilsLabelEXT(cmd_buffer);\n#endif        // DEBUG\n}\n\nvoid Device::GetSemaphoreWin32Handle(const VkSemaphoreGetWin32HandleInfoKHR *handle_info, HANDLE *handle)\n{\n\tvkGetSemaphoreWin32HandleKHR(m_logical_device, handle_info, handle);\n}\n\nvoid Device::GetMemoryWin32Handle(const VkMemoryGetWin32HandleInfoKHR *handle_info, HANDLE *handle)\n{\n\tvkGetMemoryWin32HandleKHR(m_logical_device, handle_info, handle);\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Device.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Device : public RHIDevice\n{\n  private:\n\tvoid CreateInstance();\n\tvoid CreatePhysicalDevice();\n\tvoid CreateLogicalDevice();\n\n  public:\n\tDevice();\n\n\tvirtual ~Device() override;\n\n\tvirtual void WaitIdle() override;\n\n\tvirtual bool IsFeatureSupport(RHIFeature feature) override;\n\n\tbool IsFeatureSupport(VulkanFeature feature);\n\n\tVkInstance       GetInstance() const;\n\tVkPhysicalDevice GetPhysicalDevice() const;\n\tVkDevice         GetDevice() const;\n\tVmaAllocator     GetAllocator() const;\n\n\tuint32_t GetQueueFamily(RHIQueueFamily family);\n\tuint32_t GetQueueCount(RHIQueueFamily family);\n\n\tvoid SetVulkanObjectName(const VkDebugUtilsObjectNameInfoEXT &info);\n\n\tvoid BeginDebugUtilsLabel(VkCommandBuffer cmd_buffer, const VkDebugUtilsLabelEXT &label);\n\tvoid EndDebugUtilsLabel(VkCommandBuffer cmd_buffer);\n\n\tvoid GetSemaphoreWin32Handle(const VkSemaphoreGetWin32HandleInfoKHR *handle_info, HANDLE *handle);\n\tvoid GetMemoryWin32Handle(const VkMemoryGetWin32HandleInfoKHR *handle_info, HANDLE *handle);\n\n  private:\n\t// Supported extensions\n\tstd::vector<const char *> m_supported_instance_extensions;\n\tstd::vector<const char *> m_supported_device_features;\n\tstd::vector<const char *> m_supported_device_extensions;\n\n\tstd::unordered_map<RHIFeature, bool>    m_feature_support;\n\tstd::unordered_map<VulkanFeature, bool> m_vulkan_feature_support;\n\n  private:\n\tVkInstance       m_instance        = VK_NULL_HANDLE;\n\tVkPhysicalDevice m_physical_device = VK_NULL_HANDLE;\n\tVkDevice         m_logical_device  = VK_NULL_HANDLE;\n\tVmaAllocator     m_allocator       = VK_NULL_HANDLE;\n\n\t// Queue Family\n\tuint32_t m_graphics_family = 0;\n\tuint32_t m_compute_family  = 0;\n\tuint32_t m_transfer_family = 0;\n\n\tuint32_t m_graphics_queue_count = 0;\n\tuint32_t m_compute_queue_count  = 0;\n\tuint32_t m_transfer_queue_count = 0;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Frame.cpp",
    "content": "#include \"Frame.hpp\"\n#include \"Command.hpp\"\n#include \"Device.hpp\"\n#include \"Synchronization.hpp\"\n#include \"Descriptor.hpp\"\n\nnamespace Ilum::Vulkan\n{\nFrame::Frame(RHIDevice *device) :\n    RHIFrame(device)\n{\n}\n\nFrame::~Frame()\n{\n\tp_device->WaitIdle();\n\n\tm_fences.clear();\n\tm_semaphores.clear();\n\tm_commands.clear();\n\n\tfor (auto &[hash, pool] : m_command_pools)\n\t{\n\t\tvkDestroyCommandPool(static_cast<Device *>(p_device)->GetDevice(), pool, nullptr);\n\t}\n\n\tm_command_pools.clear();\n}\n\nRHIFence *Frame::AllocateFence()\n{\n\tif (m_fences.size() > m_active_fence_index)\n\t{\n\t\treturn m_fences[m_active_fence_index++].get();\n\t}\n\n\twhile (m_fences.size() <= m_active_fence_index)\n\t{\n\t\tm_fences.emplace_back(std::make_unique<Fence>(p_device));\n\t}\n\n\tm_active_fence_index++;\n\n\treturn m_fences.back().get();\n}\n\nRHISemaphore *Frame::AllocateSemaphore()\n{\n\tif (m_semaphores.size() > m_active_semaphore_index)\n\t{\n\t\treturn m_semaphores[m_active_semaphore_index++].get();\n\t}\n\n\twhile (m_semaphores.size() <= m_active_semaphore_index)\n\t{\n\t\tm_semaphores.emplace_back(std::make_unique<Semaphore>(p_device));\n\t}\n\n\tm_active_semaphore_index++;\n\n\treturn m_semaphores.back().get();\n}\n\nRHICommand *Frame::AllocateCommand(RHIQueueFamily family)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, family, std::this_thread::get_id());\n\n\tif (m_command_pools.find(hash) == m_command_pools.end())\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\n\t\tVkCommandPoolCreateInfo create_info = {};\n\t\tcreate_info.sType                   = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;\n\t\tcreate_info.flags                   = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;\n\t\tcreate_info.queueFamilyIndex        = static_cast<Device *>(p_device)->GetQueueFamily(family);\n\n\t\tVkCommandPool pool = VK_NULL_HANDLE;\n\t\tvkCreateCommandPool(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &pool);\n\n\t\tm_command_pools.emplace(hash, pool);\n\t}\n\n\tif (m_commands.find(hash) == m_commands.end())\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\tm_commands.emplace(hash, std::vector<std::unique_ptr<Command>>{});\n\t\tm_active_cmd_index[hash] = 0;\n\t}\n\n\tif (m_commands.at(hash).size() > m_active_cmd_index.at(hash))\n\t{\n\t\tauto &cmd = m_commands.at(hash).at(m_active_cmd_index.at(hash));\n\t\tcmd->Init();\n\t\tm_active_cmd_index[hash]++;\n\t\treturn cmd.get();\n\t}\n\n\twhile (m_commands.at(hash).size() <= m_active_cmd_index.at(hash))\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\tm_commands[hash].emplace_back(std::make_unique<Command>(p_device, m_command_pools[hash], family));\n\t}\n\n\tm_active_cmd_index[hash]++;\n\n\tauto &cmd = m_commands[hash].back();\n\tcmd->Init();\n\treturn cmd.get();\n}\n\nRHIDescriptor *Frame::AllocateDescriptor(const ShaderMeta &meta)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, meta.hash, std::this_thread::get_id());\n\n\tif (m_descriptors.find(hash) == m_descriptors.end())\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\tm_descriptors.emplace(hash, std::vector<std::unique_ptr<Descriptor>>{});\n\t\tm_active_descriptor_index[hash] = 0;\n\t}\n\n\tif (m_descriptors[hash].size() > m_active_descriptor_index[hash])\n\t{\n\t\tauto &descriptor = m_descriptors[hash][m_active_descriptor_index[hash]];\n\t\tm_active_descriptor_index[hash]++;\n\t\treturn descriptor.get();\n\t}\n\n\twhile (m_descriptors[hash].size() <= m_active_descriptor_index[hash])\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\tm_descriptors[hash].emplace_back(std::make_unique<Descriptor>(p_device, meta));\n\t}\n\n\tm_active_descriptor_index[hash]++;\n\n\tauto &descriptor = m_descriptors[hash].back();\n\treturn descriptor.get();\n}\n\nvoid Frame::Reset()\n{\n\tstd::vector<VkFence> fences;\n\n\tfences.reserve(m_fences.size());\n\n\tfor (uint32_t i = 0; i < m_active_fence_index; i++)\n\t{\n\t\tfences.push_back(m_fences[i]->GetHandle());\n\t}\n\n\tif (!fences.empty())\n\t{\n\t\tvkWaitForFences(static_cast<Device *>(p_device)->GetDevice(), static_cast<uint32_t>(fences.size()), fences.data(), VK_TRUE, UINT64_MAX);\n\t\tvkResetFences(static_cast<Device *>(p_device)->GetDevice(), static_cast<uint32_t>(fences.size()), fences.data());\n\t}\n\n\tfor (auto &[hash, pool] : m_command_pools)\n\t{\n\t\tvkResetCommandPool(static_cast<Device *>(p_device)->GetDevice(), pool, 0);\n\t\tm_active_cmd_index[hash] = 0;\n\t\tfor (auto &cmd : m_commands[hash])\n\t\t{\n\t\t\tcmd->SetState(CommandState::Available);\n\t\t}\n\t}\n\n\tfor (auto& [hash, index] : m_active_descriptor_index)\n\t{\n\t\tindex = 0;\n\t}\n\n\tm_active_fence_index     = 0;\n\tm_active_semaphore_index = 0;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Frame.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Fence;\nclass Semaphore;\nclass Descriptor;\nclass Command;\n\nclass Frame : public RHIFrame\n{\n  public:\n\tFrame(RHIDevice *device);\n\n\tvirtual ~Frame() override;\n\n\tvirtual RHIFence *AllocateFence() override;\n\n\tvirtual RHISemaphore *AllocateSemaphore() override;\n\n\tvirtual RHICommand *AllocateCommand(RHIQueueFamily family) override;\n\n\tvirtual RHIDescriptor *AllocateDescriptor(const ShaderMeta &meta) override;\n\n\tvirtual void Reset() override;\n\n  private:\n\tstd::vector<std::unique_ptr<Fence>>     m_fences;\n\tstd::vector<std::unique_ptr<Semaphore>> m_semaphores;\n\n\tstd::unordered_map<size_t, std::vector<std::unique_ptr<Command>>>    m_commands;\n\tstd::unordered_map<size_t, std::vector<std::unique_ptr<Descriptor>>> m_descriptors;\n\n\tstd::unordered_map<size_t, VkCommandPool> m_command_pools;\n\n\tuint32_t m_active_fence_index     = 0;\n\tuint32_t m_active_semaphore_index = 0;\n\n\tstd::unordered_map<size_t, uint32_t> m_active_cmd_index;\n\tstd::unordered_map<size_t, uint32_t> m_active_descriptor_index;\n\n\tstd::mutex m_mutex;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Fwd.cpp",
    "content": "#define VOLK_IMPLEMENTATION\n#include \"volk.h\"\n\n#define VMA_IMPLEMENTATION\n#include \"vk_mem_alloc.h\""
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Fwd.hpp",
    "content": "#pragma once\n\n#include <array>\n#include <map>\n#include <memory>\n#include <optional>\n#include <vector>\n\n#include <volk.h>\n\n#include \"vk_mem_alloc.h\"\n\n#include <Core/Core.hpp>\n\n#include <RHI/RHIAccelerationStructure.hpp>\n#include <RHI/RHIBuffer.hpp>\n#include <RHI/RHICommand.hpp>\n#include <RHI/RHIDefinitions.hpp>\n#include <RHI/RHIDescriptor.hpp>\n#include <RHI/RHIDevice.hpp>\n#include <RHI/RHIFrame.hpp>\n#include <RHI/RHIPipelineState.hpp>\n#include <RHI/RHIProfiler.hpp>\n#include <RHI/RHIQueue.hpp>\n#include <RHI/RHIRenderTarget.hpp>\n#include <RHI/RHISampler.hpp>\n#include <RHI/RHIShader.hpp>\n#include <RHI/RHISwapchain.hpp>\n#include <RHI/RHISynchronization.hpp>\n#include <RHI/RHITexture.hpp>\n\n#include \"Definitions.hpp\"\n\n#ifdef _WIN64\n#\tinclude <Windows.h>\n#endif        // _WIN64\n\nnamespace Ilum\n{\nnamespace Vulkan\n{\nclass AccelerationStructure;\nclass Buffer;\nclass Command;\nclass Descriptor;\nclass Device;\nclass Frame;\nclass PipelineState;\nclass Profiler;\nclass Queue;\nclass RenderTarget;\nclass Sampler;\nclass Shader;\nclass Swapchain;\nclass Fence;\nclass Semaphore;\nclass Texture;\n}        // namespace Vulkan\n}        // namespace Ilum"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/PipelineState.cpp",
    "content": "#include \"PipelineState.hpp\"\n#include \"Definitions.hpp\"\n#include \"Descriptor.hpp\"\n#include \"Device.hpp\"\n#include \"RenderTarget.hpp\"\n#include \"Shader.hpp\"\n\n#include <volk.h>\n\nnamespace Ilum::Vulkan\n{\nclass ShaderBindingTableInfo\n{\n  public:\n\tShaderBindingTableInfo(Device *device, uint32_t handle_count) :\n\t    p_device(device)\n\t{\n\t\tif (handle_count == 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tVkPhysicalDeviceRayTracingPipelinePropertiesKHR raytracing_pipeline_properties = {};\n\t\traytracing_pipeline_properties.sType                                           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;\n\t\tVkPhysicalDeviceProperties2 deviceProperties2                                  = {};\n\t\tdeviceProperties2.sType                                                        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;\n\t\tdeviceProperties2.pNext                                                        = &raytracing_pipeline_properties;\n\t\tvkGetPhysicalDeviceProperties2(p_device->GetPhysicalDevice(), &deviceProperties2);\n\n\t\tuint32_t handle_size_aligned = (raytracing_pipeline_properties.shaderGroupHandleSize + raytracing_pipeline_properties.shaderGroupHandleAlignment - 1) &\n\t\t                               ~(raytracing_pipeline_properties.shaderGroupHandleAlignment - 1);\n\n\t\tVkBufferCreateInfo buffer_info = {};\n\t\tbuffer_info.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;\n\t\tbuffer_info.usage              = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;\n\t\tbuffer_info.size               = static_cast<size_t>(handle_count) * raytracing_pipeline_properties.shaderGroupHandleSize;\n\n\t\tVmaAllocationCreateInfo memory_info{};\n\t\tmemory_info.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\t\tmemory_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;\n\n\t\tVmaAllocationInfo allocation_info{};\n\t\tvmaCreateBuffer(p_device->GetAllocator(),\n\t\t                &buffer_info, &memory_info,\n\t\t                &m_buffer, &m_allocation,\n\t\t                &allocation_info);\n\n\t\tm_memory = allocation_info.deviceMemory;\n\n\t\tVkBufferDeviceAddressInfoKHR buffer_device_address_info{};\n\t\tbuffer_device_address_info.sType  = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;\n\t\tbuffer_device_address_info.buffer = m_buffer;\n\t\tm_handle.deviceAddress            = vkGetBufferDeviceAddress(p_device->GetDevice(), &buffer_device_address_info);\n\t\tm_handle.stride                   = handle_size_aligned;\n\t\tm_handle.size                     = handle_count * handle_size_aligned;\n\n\t\tm_mapped_data = static_cast<uint8_t *>(allocation_info.pMappedData);\n\t}\n\n\t~ShaderBindingTableInfo()\n\t{\n\t\tif (m_buffer && m_allocation)\n\t\t{\n\t\t\tvmaDestroyBuffer(p_device->GetAllocator(), m_buffer, m_allocation);\n\t\t}\n\t}\n\n\tuint8_t *GetData()\n\t{\n\t\treturn m_mapped_data;\n\t}\n\n\tconst VkStridedDeviceAddressRegionKHR *GetHandle() const\n\t{\n\t\treturn &m_handle;\n\t}\n\n  private:\n\tDevice *p_device = nullptr;\n\n\tuint32_t m_handle_count = 0;\n\tuint8_t *m_mapped_data  = nullptr;\n\n\tVkStridedDeviceAddressRegionKHR m_handle     = {};\n\tVkBuffer                        m_buffer     = VK_NULL_HANDLE;\n\tVmaAllocation                   m_allocation = VK_NULL_HANDLE;\n\tVkDeviceMemory                  m_memory     = VK_NULL_HANDLE;\n};\n\nstruct ShaderBindingTableInfos\n{\n\tstd::unique_ptr<ShaderBindingTableInfo> raygen   = nullptr;\n\tstd::unique_ptr<ShaderBindingTableInfo> miss     = nullptr;\n\tstd::unique_ptr<ShaderBindingTableInfo> hit      = nullptr;\n\tstd::unique_ptr<ShaderBindingTableInfo> callable = nullptr;\n};\n\nstatic std::unordered_map<std::thread::id, VkPipelineCache>                     PipelineCaches;\nstatic std::unordered_map<size_t, VkPipeline>                                   Pipelines;\nstatic std::unordered_map<size_t, VkPipelineLayout>                             PipelineLayouts;\nstatic std::unordered_map<VkPipeline, std::unique_ptr<ShaderBindingTableInfos>> ShaderBindingTables;\nstatic std::mutex                                                               Mutex;\n\nstatic std::atomic<uint32_t> PipelineCount = 0;\n\nPipelineState::PipelineState(RHIDevice *device) :\n    RHIPipelineState(device)\n{\n\tPipelineCount.fetch_add(1);\n}\n\nPipelineState ::~PipelineState()\n{\n\tPipelineCount.fetch_sub(1);\n\n\tif (PipelineCount == 0)\n\t{\n\t\tfor (auto &[hash, pipeline] : Pipelines)\n\t\t{\n\t\t\tvkDestroyPipeline(static_cast<Device *>(p_device)->GetDevice(), pipeline, nullptr);\n\t\t}\n\n\t\tfor (auto &[hash, layout] : PipelineLayouts)\n\t\t{\n\t\t\tvkDestroyPipelineLayout(static_cast<Device *>(p_device)->GetDevice(), layout, nullptr);\n\t\t}\n\n\t\tShaderBindingTables.clear();\n\t\tPipelines.clear();\n\t\tPipelineLayouts.clear();\n\n\t\tfor (auto &[thread_id, pipeline_cache] : PipelineCaches)\n\t\t{\n\t\t\tvkDestroyPipelineCache(static_cast<Device *>(p_device)->GetDevice(), pipeline_cache, nullptr);\n\t\t\tpipeline_cache = VK_NULL_HANDLE;\n\t\t}\n\t}\n}\n\nVkPipelineLayout PipelineState::GetPipelineLayout(Descriptor *descriptor)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, descriptor->GetShaderMeta().hash, GetHash());\n\n\tif (PipelineLayouts.find(hash) != PipelineLayouts.end())\n\t{\n\t\treturn PipelineLayouts[hash];\n\t}\n\n\treturn CreatePipelineLayout(descriptor);\n}\n\nVkPipeline PipelineState::GetPipeline(Descriptor *descriptor, RenderTarget *render_target)\n{\n\tfor (const auto &[stage, shader] : m_shaders)\n\t{\n\t\tif (stage & RHIShaderStage::Fragment)\n\t\t{\n\t\t\tassert(render_target != nullptr);\n\t\t\treturn CreateGraphicsPipeline(descriptor, render_target);\n\t\t}\n\t\telse if (stage & RHIShaderStage::Compute)\n\t\t{\n\t\t\treturn CreateComputePipeline(descriptor);\n\t\t}\n\t\telse if (stage & RHIShaderStage::RayGen)\n\t\t{\n\t\t\treturn CreateRayTracingPipeline(descriptor);\n\t\t}\n\t}\n\treturn VK_NULL_HANDLE;\n}\n\nShaderBindingTable PipelineState::GetShaderBindingTable(VkPipeline pipeline)\n{\n\tShaderBindingTable sbt;\n\tif (ShaderBindingTables.find(pipeline) != ShaderBindingTables.end())\n\t{\n\t\tauto &shader_binding_table_infos = ShaderBindingTables.at(pipeline);\n\n\t\tsbt.raygen   = shader_binding_table_infos->raygen->GetHandle();\n\t\tsbt.hit      = shader_binding_table_infos->hit->GetHandle();\n\t\tsbt.miss     = shader_binding_table_infos->miss->GetHandle();\n\t\tsbt.callable = shader_binding_table_infos->callable->GetHandle();\n\t}\n\treturn sbt;\n}\n\nVkPipelineBindPoint PipelineState::GetPipelineBindPoint() const\n{\n\tfor (const auto &[stage, shader] : m_shaders)\n\t{\n\t\tif (stage & RHIShaderStage::Fragment)\n\t\t{\n\t\t\treturn VK_PIPELINE_BIND_POINT_GRAPHICS;\n\t\t}\n\t\telse if (stage & RHIShaderStage::Compute)\n\t\t{\n\t\t\treturn VK_PIPELINE_BIND_POINT_COMPUTE;\n\t\t}\n\t\telse if (stage & RHIShaderStage::RayGen)\n\t\t{\n\t\t\treturn VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;\n\t\t}\n\t}\n\treturn VK_PIPELINE_BIND_POINT_GRAPHICS;\n}\n\nVkPipelineCache PipelineState::CreatePipelineCache(const std::thread::id &thread_id)\n{\n\tif (PipelineCaches.find(thread_id) == PipelineCaches.end())\n\t{\n\t\tstd::lock_guard<std::mutex> lock(Mutex);\n\t\tPipelineCaches[thread_id]             = VK_NULL_HANDLE;\n\t\tVkPipelineCacheCreateInfo create_info = {};\n\t\tcreate_info.sType                     = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;\n\t\tvkCreatePipelineCache(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &PipelineCaches[thread_id]);\n\t}\n\treturn PipelineCaches.at(thread_id);\n}\n\nVkPipelineLayout PipelineState::CreatePipelineLayout(Descriptor *descriptor)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, descriptor->GetShaderMeta().hash, GetHash());\n\n\t// Push constant merge range\n\tstd::unordered_map<size_t, VkPushConstantRange> push_constant_range_map;\n\tfor (auto &constant : descriptor->GetShaderMeta().constants)\n\t{\n\t\tsize_t hash = Hash(constant.size, constant.offset);\n\t\tif (push_constant_range_map.find(hash) != push_constant_range_map.end())\n\t\t{\n\t\t\tpush_constant_range_map[hash].stageFlags |= ToVulkanShaderStages(constant.stage);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tVkPushConstantRange push_constant_range = {};\n\t\t\tpush_constant_range.stageFlags          = ToVulkanShaderStages(constant.stage);\n\t\t\tpush_constant_range.size                = constant.size;\n\t\t\tpush_constant_range.offset              = constant.offset;\n\t\t\tpush_constant_range_map.emplace(hash, push_constant_range);\n\t\t}\n\t}\n\n\t// Push constant merge stage\n\tstd::unordered_map<VkShaderStageFlags, VkPushConstantRange> push_constant_map;\n\tfor (auto &[hash, constant] : push_constant_range_map)\n\t{\n\t\tif (push_constant_map.find(constant.stageFlags) == push_constant_map.end())\n\t\t{\n\t\t\tpush_constant_map[constant.stageFlags] = constant;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpush_constant_map[constant.stageFlags].offset = std::min(push_constant_map[constant.stageFlags].offset, constant.offset);\n\t\t\tpush_constant_map[constant.stageFlags].size += constant.size;\n\t\t}\n\t}\n\n\tstd::vector<VkPushConstantRange> push_constants;\n\tpush_constants.reserve(push_constant_map.size());\n\tfor (auto &[hash, constant] : push_constant_map)\n\t{\n\t\tpush_constants.push_back(std::move(constant));\n\t}\n\n\tstd::vector<VkDescriptorSetLayout> descriptor_set_layouts;\n\tfor (auto &[set, layout] : descriptor->GetDescriptorSetLayout())\n\t{\n\t\tdescriptor_set_layouts.push_back(layout);\n\t}\n\n\tVkPipelineLayoutCreateInfo pipeline_layout_create_info = {};\n\tpipeline_layout_create_info.sType                      = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;\n\tpipeline_layout_create_info.pushConstantRangeCount     = static_cast<uint32_t>(push_constants.size());\n\tpipeline_layout_create_info.pPushConstantRanges        = push_constants.data();\n\tpipeline_layout_create_info.setLayoutCount             = static_cast<uint32_t>(descriptor_set_layouts.size());\n\tpipeline_layout_create_info.pSetLayouts                = descriptor_set_layouts.data();\n\n\tVkPipelineLayout layout = VK_NULL_HANDLE;\n\tvkCreatePipelineLayout(static_cast<Device *>(p_device)->GetDevice(), &pipeline_layout_create_info, nullptr, &layout);\n\n\tPipelineLayouts.emplace(hash, layout);\n\n\treturn layout;\n}\n\nVkPipeline PipelineState::CreateGraphicsPipeline(Descriptor *descriptor, RenderTarget *render_target)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, descriptor->GetShaderMeta().hash, GetHash());\n\n\tbool dynamic_rendering = static_cast<Device *>(p_device)->IsFeatureSupport(VulkanFeature::DynamicRendering);\n\n\tif (render_target)\n\t{\n\t\tif (dynamic_rendering)\n\t\t{\n\t\t\tHashCombine(hash, render_target->GetFormatHash());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tHashCombine(hash, render_target->GetRenderPass());\n\t\t}\n\t}\n\n\tif (Pipelines.find(hash) != Pipelines.end())\n\t{\n\t\treturn Pipelines[hash];\n\t}\n\n\t// Input Assembly State\n\tVkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = {};\n\tinput_assembly_state_create_info.sType                                  = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;\n\tinput_assembly_state_create_info.topology                               = ToVulkanPrimitiveTopology[m_input_assembly_state.topology];\n\tinput_assembly_state_create_info.flags                                  = 0;\n\tinput_assembly_state_create_info.primitiveRestartEnable                 = VK_FALSE;\n\n\t// Rasterization State\n\tVkPipelineRasterizationStateCreateInfo rasterization_state_create_info = {};\n\trasterization_state_create_info.sType                                  = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;\n\trasterization_state_create_info.polygonMode                            = ToVulkanPolygonMode[m_rasterization_state.polygon_mode];\n\trasterization_state_create_info.cullMode                               = ToVulkanCullMode[m_rasterization_state.cull_mode];\n\trasterization_state_create_info.frontFace                              = ToVulkanFrontFace[m_rasterization_state.front_face];\n\trasterization_state_create_info.lineWidth                              = m_rasterization_state.line_width;\n\trasterization_state_create_info.depthBiasEnable                        = m_rasterization_state.depth_bias_enable;\n\trasterization_state_create_info.depthClampEnable                       = m_rasterization_state.depth_clamp_enable;\n\trasterization_state_create_info.depthBiasConstantFactor                = m_rasterization_state.depth_bias;\n\trasterization_state_create_info.depthBiasSlopeFactor                   = m_rasterization_state.depth_bias_slope;\n\trasterization_state_create_info.depthBiasClamp                         = m_rasterization_state.depth_bias_clamp;\n\trasterization_state_create_info.flags                                  = 0;\n\n\t// Color Blend State\n\tstd::vector<VkPipelineColorBlendAttachmentState> color_blend_attachment_states(m_blend_state.attachment_states.size());\n\n\tfor (uint32_t i = 0; i < color_blend_attachment_states.size(); i++)\n\t{\n\t\tcolor_blend_attachment_states[i].blendEnable         = m_blend_state.attachment_states[i].blend_enable;\n\t\tcolor_blend_attachment_states[i].srcColorBlendFactor = ToVulkanBlendFactor[m_blend_state.attachment_states[i].src_color_blend];\n\t\tcolor_blend_attachment_states[i].dstColorBlendFactor = ToVulkanBlendFactor[m_blend_state.attachment_states[i].dst_color_blend];\n\t\tcolor_blend_attachment_states[i].colorBlendOp        = ToVulkanBlendOp[m_blend_state.attachment_states[i].color_blend_op];\n\t\tcolor_blend_attachment_states[i].srcAlphaBlendFactor = ToVulkanBlendFactor[m_blend_state.attachment_states[i].src_alpha_blend];\n\t\tcolor_blend_attachment_states[i].dstAlphaBlendFactor = ToVulkanBlendFactor[m_blend_state.attachment_states[i].dst_alpha_blend];\n\t\tcolor_blend_attachment_states[i].alphaBlendOp        = ToVulkanBlendOp[m_blend_state.attachment_states[i].alpha_blend_op];\n\t\tcolor_blend_attachment_states[i].colorWriteMask      = m_blend_state.attachment_states[i].color_write_mask;\n\t}\n\n\tVkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {};\n\tcolor_blend_state_create_info.sType                               = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;\n\tcolor_blend_state_create_info.logicOpEnable                       = m_blend_state.enable;\n\tcolor_blend_state_create_info.logicOp                             = ToVulkanLogicOp[m_blend_state.logic_op];\n\tcolor_blend_state_create_info.attachmentCount                     = static_cast<uint32_t>(color_blend_attachment_states.size());\n\tcolor_blend_state_create_info.pAttachments                        = color_blend_attachment_states.data();\n\tcolor_blend_state_create_info.blendConstants[0]                   = m_blend_state.blend_constants[0];\n\tcolor_blend_state_create_info.blendConstants[1]                   = m_blend_state.blend_constants[1];\n\tcolor_blend_state_create_info.blendConstants[2]                   = m_blend_state.blend_constants[2];\n\tcolor_blend_state_create_info.blendConstants[3]                   = m_blend_state.blend_constants[3];\n\n\t// Depth Stencil State\n\tVkPipelineDepthStencilStateCreateInfo depth_stencil_state_create_info = {};\n\tdepth_stencil_state_create_info.sType                                 = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;\n\tdepth_stencil_state_create_info.depthTestEnable                       = m_depth_stencil_state.depth_test_enable;\n\tdepth_stencil_state_create_info.depthWriteEnable                      = m_depth_stencil_state.depth_write_enable;\n\tdepth_stencil_state_create_info.depthCompareOp                        = ToVulkanCompareOp[m_depth_stencil_state.compare];\n\t// TODO: stencil test\n\tdepth_stencil_state_create_info.back              = VkStencilOpState{};\n\tdepth_stencil_state_create_info.front             = VkStencilOpState{};\n\tdepth_stencil_state_create_info.stencilTestEnable = VK_FALSE;\n\n\t// Viewport State\n\tVkPipelineViewportStateCreateInfo viewport_state_create_info = {};\n\tviewport_state_create_info.sType                             = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;\n\tviewport_state_create_info.viewportCount                     = 1;\n\tviewport_state_create_info.scissorCount                      = 1;\n\tviewport_state_create_info.flags                             = 0;\n\n\t// Multisample State\n\tVkPipelineMultisampleStateCreateInfo multisample_state_create_info = {};\n\tmultisample_state_create_info.sType                                = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;\n\tmultisample_state_create_info.rasterizationSamples                 = ToVulkanSampleCount[m_multisample_state.samples];\n\tmultisample_state_create_info.sampleShadingEnable                  = m_multisample_state.enable;\n\tmultisample_state_create_info.pSampleMask                          = m_multisample_state.enable ? &m_multisample_state.sample_mask : nullptr;\n\tmultisample_state_create_info.flags                                = 0;\n\n\t// Dynamic State\n\tstd::vector<VkDynamicState>      dynamic_states            = {VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_VIEWPORT};\n\tVkPipelineDynamicStateCreateInfo dynamic_state_create_info = {};\n\tdynamic_state_create_info.sType                            = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;\n\tdynamic_state_create_info.pDynamicStates                   = dynamic_states.data();\n\tdynamic_state_create_info.dynamicStateCount                = static_cast<uint32_t>(dynamic_states.size());\n\tdynamic_state_create_info.flags                            = 0;\n\n\t// Vertex Input State\n\tstd::vector<VkVertexInputAttributeDescription> attribute_descriptions = {};\n\tstd::vector<VkVertexInputBindingDescription>   binding_descriptions   = {};\n\n\tfor (auto &attribute : m_vertex_input_state.input_attributes)\n\t{\n\t\tattribute_descriptions.push_back(VkVertexInputAttributeDescription{\n\t\t    attribute.location,\n\t\t    attribute.binding,\n\t\t    ToVulkanFormat[attribute.format],\n\t\t    attribute.offset});\n\t}\n\n\tfor (auto &binding : m_vertex_input_state.input_bindings)\n\t{\n\t\tbinding_descriptions.push_back(VkVertexInputBindingDescription{\n\t\t    binding.binding,\n\t\t    binding.stride,\n\t\t    ToVulkanVertexInputRate[binding.rate]});\n\t}\n\n\tVkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = {};\n\tvertex_input_state_create_info.sType                                = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;\n\tvertex_input_state_create_info.vertexAttributeDescriptionCount      = static_cast<uint32_t>(attribute_descriptions.size());\n\tvertex_input_state_create_info.pVertexAttributeDescriptions         = attribute_descriptions.data();\n\tvertex_input_state_create_info.vertexBindingDescriptionCount        = static_cast<uint32_t>(binding_descriptions.size());\n\tvertex_input_state_create_info.pVertexBindingDescriptions           = binding_descriptions.data();\n\n\t// Shader Stage State\n\tstd::vector<VkPipelineShaderStageCreateInfo> pipeline_shader_stage_create_infos;\n\tfor (auto &[stage, shader] : m_shaders)\n\t{\n\t\tVkPipelineShaderStageCreateInfo shader_stage_create_info = {};\n\n\t\tshader_stage_create_info.sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\tshader_stage_create_info.stage  = ToVulkanShaderStage[stage];\n\t\tshader_stage_create_info.module = static_cast<Shader *>(shader)->GetHandle();\n\t\tshader_stage_create_info.pName  = shader->GetEntryPoint().c_str();\n\t\tpipeline_shader_stage_create_infos.push_back(shader_stage_create_info);\n\t}\n\n\tVkGraphicsPipelineCreateInfo graphics_pipeline_create_info = {};\n\tgraphics_pipeline_create_info.sType                        = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;\n\tgraphics_pipeline_create_info.stageCount                   = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size());\n\tgraphics_pipeline_create_info.pStages                      = pipeline_shader_stage_create_infos.data();\n\n\tgraphics_pipeline_create_info.pInputAssemblyState = &input_assembly_state_create_info;\n\tgraphics_pipeline_create_info.pRasterizationState = &rasterization_state_create_info;\n\tgraphics_pipeline_create_info.pColorBlendState    = &color_blend_state_create_info;\n\tgraphics_pipeline_create_info.pViewportState      = &viewport_state_create_info;\n\tgraphics_pipeline_create_info.pMultisampleState   = &multisample_state_create_info;\n\tgraphics_pipeline_create_info.pDynamicState       = &dynamic_state_create_info;\n\tgraphics_pipeline_create_info.pVertexInputState   = &vertex_input_state_create_info;\n\tgraphics_pipeline_create_info.pDepthStencilState  = &depth_stencil_state_create_info;\n\n\tgraphics_pipeline_create_info.layout             = GetPipelineLayout(descriptor);\n\tgraphics_pipeline_create_info.renderPass         = VK_NULL_HANDLE;\n\tgraphics_pipeline_create_info.subpass            = 0;\n\tgraphics_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;\n\tgraphics_pipeline_create_info.basePipelineIndex  = -1;\n\n\tif (dynamic_rendering)\n\t{\n\t\tVkPipelineRenderingCreateInfo pipeline_rendering_create_info = {};\n\t\tpipeline_rendering_create_info.sType                         = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;\n\t\tpipeline_rendering_create_info.colorAttachmentCount          = static_cast<uint32_t>(render_target->GetColorFormats().size());\n\t\tpipeline_rendering_create_info.pColorAttachmentFormats       = render_target->GetColorFormats().data();\n\t\tpipeline_rendering_create_info.depthAttachmentFormat         = render_target->GetDepthFormat().has_value() ? render_target->GetDepthFormat().value() : VK_FORMAT_UNDEFINED;\n\t\tpipeline_rendering_create_info.stencilAttachmentFormat       = render_target->GetStencilFormat().has_value() ? render_target->GetStencilFormat().value() : VK_FORMAT_UNDEFINED;\n\t\tgraphics_pipeline_create_info.pNext                          = &pipeline_rendering_create_info;\n\t}\n\telse\n\t{\n\t\tif (render_target)\n\t\t{\n\t\t\tgraphics_pipeline_create_info.renderPass = render_target->GetRenderPass();\n\t\t}\n\t}\n\n\tVkPipeline pipeline = VK_NULL_HANDLE;\n\tvkCreateGraphicsPipelines(static_cast<Device *>(p_device)->GetDevice(), CreatePipelineCache(std::this_thread::get_id()), 1, &graphics_pipeline_create_info, nullptr, &pipeline);\n\n\t{\n\t\tstd::lock_guard<std::mutex> lock(Mutex);\n\t\tPipelines.emplace(hash, pipeline);\n\t}\n\n\treturn pipeline;\n}\n\nVkPipeline PipelineState::CreateComputePipeline(Descriptor *descriptor)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, descriptor->GetShaderMeta().hash, GetHash());\n\n\tif (Pipelines.find(hash) != Pipelines.end())\n\t{\n\t\treturn Pipelines[hash];\n\t}\n\n\tVkPipelineShaderStageCreateInfo shader_stage_create_info = {};\n\tfor (const auto &[stage, shader] : m_shaders)\n\t{\n\t\tif (stage & RHIShaderStage::Compute)\n\t\t{\n\t\t\tshader_stage_create_info.sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\tshader_stage_create_info.stage  = VK_SHADER_STAGE_COMPUTE_BIT;\n\t\t\tshader_stage_create_info.module = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\tshader_stage_create_info.pName  = shader->GetEntryPoint().c_str();\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tVkComputePipelineCreateInfo compute_pipeline_create_info = {};\n\tcompute_pipeline_create_info.sType                       = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;\n\tcompute_pipeline_create_info.stage                       = shader_stage_create_info;\n\tcompute_pipeline_create_info.layout                      = GetPipelineLayout(descriptor);\n\tcompute_pipeline_create_info.basePipelineIndex           = 0;\n\tcompute_pipeline_create_info.basePipelineHandle          = VK_NULL_HANDLE;\n\n\tVkPipeline pipeline = VK_NULL_HANDLE;\n\tvkCreateComputePipelines(static_cast<Device *>(p_device)->GetDevice(), CreatePipelineCache(std::this_thread::get_id()), 1, &compute_pipeline_create_info, nullptr, &pipeline);\n\n\t{\n\t\tstd::lock_guard<std::mutex> lock(Mutex);\n\t\tPipelines.emplace(hash, pipeline);\n\t}\n\n\treturn pipeline;\n}\n\nVkPipeline PipelineState::CreateRayTracingPipeline(Descriptor *descriptor)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, descriptor->GetShaderMeta().hash, GetHash());\n\n\tif (Pipelines.find(hash) != Pipelines.end())\n\t{\n\t\treturn Pipelines[hash];\n\t}\n\n\tVkPipeline pipeline = VK_NULL_HANDLE;\n\n\tstd::vector<VkRayTracingShaderGroupCreateInfoKHR> shader_group_create_infos;\n\tstd::vector<VkPipelineShaderStageCreateInfo>      pipeline_shader_stage_create_infos;\n\n\tuint32_t raygen_count   = 0;\n\tuint32_t raymiss_count  = 0;\n\tuint32_t rayhit_count   = 0;\n\tuint32_t callable_count = 0;\n\n\t// Ray Generation Group\n\t{\n\t\tfor (const auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tif (stage & RHIShaderStage::RayGen)\n\t\t\t{\n\t\t\t\tVkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info = {};\n\t\t\t\tpipeline_shader_stage_create_info.sType                           = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\t\tpipeline_shader_stage_create_info.stage                           = VK_SHADER_STAGE_RAYGEN_BIT_KHR;\n\t\t\t\tpipeline_shader_stage_create_info.module                          = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\t\tpipeline_shader_stage_create_info.pName                           = shader->GetEntryPoint().c_str();\n\t\t\t\tpipeline_shader_stage_create_infos.push_back(pipeline_shader_stage_create_info);\n\n\t\t\t\tVkRayTracingShaderGroupCreateInfoKHR shader_group = {};\n\t\t\t\tshader_group.sType                                = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;\n\t\t\t\tshader_group.type                                 = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;\n\t\t\t\tshader_group.generalShader                        = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size()) - 1;\n\t\t\t\tshader_group.closestHitShader                     = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.anyHitShader                         = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.intersectionShader                   = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group_create_infos.push_back(shader_group);\n\n\t\t\t\traygen_count++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Ray Miss Group\n\t{\n\t\tfor (const auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tif (stage & RHIShaderStage::Miss)\n\t\t\t{\n\t\t\t\tVkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info = {};\n\t\t\t\tpipeline_shader_stage_create_info.sType                           = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\t\tpipeline_shader_stage_create_info.stage                           = VK_SHADER_STAGE_MISS_BIT_KHR;\n\t\t\t\tpipeline_shader_stage_create_info.module                          = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\t\tpipeline_shader_stage_create_info.pName                           = shader->GetEntryPoint().c_str();\n\t\t\t\tpipeline_shader_stage_create_infos.push_back(pipeline_shader_stage_create_info);\n\n\t\t\t\tVkRayTracingShaderGroupCreateInfoKHR shader_group = {};\n\t\t\t\tshader_group.sType                                = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;\n\t\t\t\tshader_group.type                                 = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;\n\t\t\t\tshader_group.generalShader                        = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size()) - 1;\n\t\t\t\tshader_group.closestHitShader                     = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.anyHitShader                         = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.intersectionShader                   = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group_create_infos.push_back(shader_group);\n\n\t\t\t\traymiss_count++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Closest Hit Group\n\t{\n\t\tfor (const auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tif (stage & RHIShaderStage::ClosestHit)\n\t\t\t{\n\t\t\t\tVkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info = {};\n\t\t\t\tpipeline_shader_stage_create_info.sType                           = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\t\tpipeline_shader_stage_create_info.stage                           = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;\n\t\t\t\tpipeline_shader_stage_create_info.module                          = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\t\tpipeline_shader_stage_create_info.pName                           = shader->GetEntryPoint().c_str();\n\t\t\t\tpipeline_shader_stage_create_infos.push_back(pipeline_shader_stage_create_info);\n\n\t\t\t\tVkRayTracingShaderGroupCreateInfoKHR shader_group = {};\n\t\t\t\tshader_group.sType                                = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;\n\t\t\t\tshader_group.type                                 = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;\n\t\t\t\tshader_group.generalShader                        = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.closestHitShader                     = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size()) - 1;\n\t\t\t\tshader_group.anyHitShader                         = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.intersectionShader                   = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group_create_infos.push_back(shader_group);\n\n\t\t\t\trayhit_count++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Any Hit Group\n\t{\n\t\tfor (const auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tif (stage & RHIShaderStage::AnyHit)\n\t\t\t{\n\t\t\t\tVkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info = {};\n\t\t\t\tpipeline_shader_stage_create_info.sType                           = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\t\tpipeline_shader_stage_create_info.stage                           = VK_SHADER_STAGE_ANY_HIT_BIT_KHR;\n\t\t\t\tpipeline_shader_stage_create_info.module                          = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\t\tpipeline_shader_stage_create_info.pName                           = shader->GetEntryPoint().c_str();\n\t\t\t\tpipeline_shader_stage_create_infos.push_back(pipeline_shader_stage_create_info);\n\n\t\t\t\tVkRayTracingShaderGroupCreateInfoKHR shader_group = {};\n\t\t\t\tshader_group.sType                                = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;\n\t\t\t\tshader_group.type                                 = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;\n\t\t\t\tshader_group.generalShader                        = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.closestHitShader                     = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.anyHitShader                         = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size()) - 1;\n\t\t\t\tshader_group.intersectionShader                   = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group_create_infos.push_back(shader_group);\n\n\t\t\t\trayhit_count++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Intersection Group\n\t{\n\t\tfor (const auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tif (stage & RHIShaderStage::Intersection)\n\t\t\t{\n\t\t\t\tVkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info = {};\n\t\t\t\tpipeline_shader_stage_create_info.sType                           = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\t\tpipeline_shader_stage_create_info.stage                           = VK_SHADER_STAGE_INTERSECTION_BIT_KHR;\n\t\t\t\tpipeline_shader_stage_create_info.module                          = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\t\tpipeline_shader_stage_create_info.pName                           = shader->GetEntryPoint().c_str();\n\t\t\t\tpipeline_shader_stage_create_infos.push_back(pipeline_shader_stage_create_info);\n\n\t\t\t\tVkRayTracingShaderGroupCreateInfoKHR shader_group = {};\n\t\t\t\tshader_group.sType                                = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;\n\t\t\t\tshader_group.type                                 = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;\n\t\t\t\tshader_group.generalShader                        = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.closestHitShader                     = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.anyHitShader                         = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.intersectionShader                   = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size()) - 1;\n\t\t\t\tshader_group_create_infos.push_back(shader_group);\n\n\t\t\t\trayhit_count++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Callable Group\n\t{\n\t\tfor (const auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tif (stage & RHIShaderStage::Callable)\n\t\t\t{\n\t\t\t\tVkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info = {};\n\t\t\t\tpipeline_shader_stage_create_info.sType                           = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;\n\t\t\t\tpipeline_shader_stage_create_info.stage                           = VK_SHADER_STAGE_CALLABLE_BIT_KHR;\n\t\t\t\tpipeline_shader_stage_create_info.module                          = static_cast<const Shader *>(shader)->GetHandle();\n\t\t\t\tpipeline_shader_stage_create_info.pName                           = shader->GetEntryPoint().c_str();\n\t\t\t\tpipeline_shader_stage_create_infos.push_back(pipeline_shader_stage_create_info);\n\n\t\t\t\tVkRayTracingShaderGroupCreateInfoKHR shader_group = {};\n\t\t\t\tshader_group.sType                                = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;\n\t\t\t\tshader_group.type                                 = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;\n\t\t\t\tshader_group.generalShader                        = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size()) - 1;\n\t\t\t\tshader_group.closestHitShader                     = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.anyHitShader                         = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group.intersectionShader                   = VK_SHADER_UNUSED_KHR;\n\t\t\t\tshader_group_create_infos.push_back(shader_group);\n\n\t\t\t\tcallable_count++;\n\t\t\t}\n\t\t}\n\t}\n\n\tVkRayTracingPipelineCreateInfoKHR raytracing_pipeline_create_info = {};\n\traytracing_pipeline_create_info.sType                             = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;\n\traytracing_pipeline_create_info.stageCount                        = static_cast<uint32_t>(pipeline_shader_stage_create_infos.size());\n\traytracing_pipeline_create_info.pStages                           = pipeline_shader_stage_create_infos.data();\n\traytracing_pipeline_create_info.groupCount                        = static_cast<uint32_t>(shader_group_create_infos.size());\n\traytracing_pipeline_create_info.pGroups                           = shader_group_create_infos.data();\n\traytracing_pipeline_create_info.maxPipelineRayRecursionDepth      = 4;\n\traytracing_pipeline_create_info.layout                            = GetPipelineLayout(descriptor);\n\n\tvkCreateRayTracingPipelinesKHR(static_cast<Device *>(p_device)->GetDevice(), VK_NULL_HANDLE, CreatePipelineCache(std::this_thread::get_id()), 1, &raytracing_pipeline_create_info, nullptr, &pipeline);\n\n\t{\n\t\tstd::lock_guard<std::mutex> lock(Mutex);\n\t\tPipelines.emplace(hash, pipeline);\n\t}\n\n\t// Create shader binding table\n\t/*\n\t    SBT Layout:\n\n\t        /-----------\\\n\t        | raygen    |\n\t        |-----------|\n\t        | miss        |\n\t        |-----------|\n\t        | hit           |\n\t        |-----------|\n\t        | callable   |\n\t        \\-----------/\n\n\t*/\n\n\tauto sbt = std::make_unique<ShaderBindingTableInfos>();\n\n\tVkPhysicalDeviceRayTracingPipelinePropertiesKHR raytracing_properties = {};\n\traytracing_properties.sType                                           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;\n\tVkPhysicalDeviceProperties2 deviceProperties2                         = {};\n\tdeviceProperties2.sType                                               = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;\n\tdeviceProperties2.pNext                                               = &raytracing_properties;\n\tvkGetPhysicalDeviceProperties2(static_cast<Device *>(p_device)->GetPhysicalDevice(), &deviceProperties2);\n\n\tconst uint32_t handle_size         = raytracing_properties.shaderGroupHandleSize;\n\tconst uint32_t handle_size_aligned = (raytracing_properties.shaderGroupHandleSize + raytracing_properties.shaderGroupHandleAlignment - 1) & ~(raytracing_properties.shaderGroupHandleAlignment - 1);\n\tconst uint32_t group_count         = static_cast<uint32_t>(shader_group_create_infos.size());\n\tconst uint32_t sbt_size            = group_count * handle_size_aligned;\n\n\tstd::vector<uint8_t> shader_handle_storage(sbt_size);\n\n\tvkGetRayTracingShaderGroupHandlesKHR(static_cast<Device *>(p_device)->GetDevice(), pipeline, 0, group_count, sbt_size, shader_handle_storage.data());\n\n\tuint32_t handle_offset = 0;\n\n\t// Gen Group\n\t{\n\t\tsbt->raygen = std::make_unique<ShaderBindingTableInfo>(static_cast<Device *>(p_device), raygen_count);\n\t\tstd::memcpy(sbt->raygen->GetData(), shader_handle_storage.data() + handle_offset, handle_size * raygen_count);\n\t\thandle_offset += raygen_count * handle_size_aligned;\n\t}\n\n\t// Miss Group\n\t{\n\t\tsbt->miss = std::make_unique<ShaderBindingTableInfo>(static_cast<Device *>(p_device), raymiss_count);\n\t\tstd::memcpy(sbt->miss->GetData(), shader_handle_storage.data() + handle_offset, handle_size * raymiss_count);\n\t\thandle_offset += raymiss_count * handle_size_aligned;\n\t}\n\n\t// Hit Group\n\t{\n\t\tsbt->hit = std::make_unique<ShaderBindingTableInfo>(static_cast<Device *>(p_device), rayhit_count);\n\t\tstd::memcpy(sbt->hit->GetData(), shader_handle_storage.data() + handle_offset, handle_size * rayhit_count);\n\t\thandle_offset += rayhit_count * handle_size_aligned;\n\t}\n\n\t// Callable Group\n\t{\n\t\tsbt->callable = std::make_unique<ShaderBindingTableInfo>(static_cast<Device *>(p_device), callable_count);\n\t\tstd::memcpy(sbt->callable->GetData(), shader_handle_storage.data() + handle_offset, handle_size * callable_count);\n\t\thandle_offset += callable_count * handle_size_aligned;\n\t}\n\n\t{\n\t\tstd::lock_guard<std::mutex> lock(Mutex);\n\t\tShaderBindingTables.emplace(pipeline, std::move(sbt));\n\t}\n\n\treturn pipeline;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/PipelineState.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Descriptor;\nclass RenderTarget;\n\nstruct ShaderBindingTable\n{\n\tconst VkStridedDeviceAddressRegionKHR *raygen   = nullptr;\n\tconst VkStridedDeviceAddressRegionKHR *miss     = nullptr;\n\tconst VkStridedDeviceAddressRegionKHR *hit      = nullptr;\n\tconst VkStridedDeviceAddressRegionKHR *callable = nullptr;\n};\n\nclass PipelineState : public RHIPipelineState\n{\n  public:\n\tPipelineState(RHIDevice *device);\n\n\tvirtual ~PipelineState() override;\n\n\tVkPipelineLayout GetPipelineLayout(Descriptor *descriptor);\n\n\tVkPipeline GetPipeline(Descriptor *descriptor, RenderTarget *render_target);\n\n\tShaderBindingTable GetShaderBindingTable(VkPipeline pipeline);\n\n\tVkPipelineBindPoint GetPipelineBindPoint() const;\n\n  private:\n\tVkPipelineCache  CreatePipelineCache(const std::thread::id &thread_id);\n\tVkPipelineLayout CreatePipelineLayout(Descriptor *descriptor);\n\tVkPipeline       CreateGraphicsPipeline(Descriptor *descriptor, RenderTarget *render_target);\n\tVkPipeline       CreateComputePipeline(Descriptor *descriptor);\n\tVkPipeline       CreateRayTracingPipeline(Descriptor *descriptor);\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Profiler.cpp",
    "content": "#include \"Profiler.hpp\"\n\n#include \"Command.hpp\"\n#include \"Device.hpp\"\n\nnamespace Ilum::Vulkan\n{\nProfiler::Profiler(RHIDevice *device, uint32_t frame_count) :\n    RHIProfiler(device, frame_count)\n{\n\tVkQueryPoolCreateInfo createInfo = {};\n\tcreateInfo.sType                 = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;\n\tcreateInfo.pNext                 = nullptr;\n\tcreateInfo.flags                 = 0;\n\n\tcreateInfo.queryType  = VK_QUERY_TYPE_TIMESTAMP;\n\tcreateInfo.queryCount = 2;\n\n\tm_query_pools.resize(frame_count);\n\tfor (auto &pool : m_query_pools)\n\t{\n\t\tvkCreateQueryPool(static_cast<Device *>(p_device)->GetDevice(), &createInfo, nullptr, &pool);\n\t}\n}\n\nProfiler ::~Profiler()\n{\n\tfor (auto &pool : m_query_pools)\n\t{\n\t\tvkDestroyQueryPool(static_cast<Device *>(p_device)->GetDevice(), pool, nullptr);\n\t}\n}\n\nvoid Profiler::Begin(RHICommand *cmd_buffer, uint32_t frame_index)\n{\n\tm_current_index = frame_index;\n\tm_cmd_buffer    = static_cast<Command *>(cmd_buffer)->GetHandle();\n\n\tm_state.thread_id = std::this_thread::get_id();\n\n\tvkGetQueryPoolResults(static_cast<Device *>(p_device)->GetDevice(), m_query_pools[m_current_index], 0, 1, sizeof(uint64_t), &m_state.gpu_start, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);\n\tvkGetQueryPoolResults(static_cast<Device *>(p_device)->GetDevice(), m_query_pools[m_current_index], 1, 1, sizeof(uint64_t), &m_state.gpu_end, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);\n\tm_state.gpu_time = static_cast<float>(m_state.gpu_end - m_state.gpu_start) / 1000000.f;\n\tm_state.cpu_time = std::chrono::duration<float, std::milli>(m_state.cpu_end - m_state.cpu_start).count();\n\n\tvkCmdResetQueryPool(m_cmd_buffer, m_query_pools[m_current_index], 0, 2);\n\tvkCmdWriteTimestamp(m_cmd_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, m_query_pools[m_current_index], 0);\n\tm_state.cpu_start = std::chrono::high_resolution_clock::now();\n}\n\nvoid Profiler::End(RHICommand *cmd_buffer)\n{\n\tassert(m_cmd_buffer != VK_NULL_HANDLE);\n\tvkCmdWriteTimestamp(m_cmd_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, m_query_pools[m_current_index], 1);\n\tm_state.cpu_end = std::chrono::high_resolution_clock::now();\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Profiler.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Profiler : public RHIProfiler\n{\n  public:\n\tProfiler(RHIDevice *device, uint32_t frame_count);\n\n\tvirtual ~Profiler() override;\n\n\tvirtual void Begin(RHICommand *cmd_buffer, uint32_t frame_index) override;\n\n\tvirtual void End(RHICommand *cmd_buffer) override;\n\n  private:\n\tstd::vector<VkQueryPool> m_query_pools;\n\tuint32_t                 m_current_index = 0;\n\tVkCommandBuffer          m_cmd_buffer    = VK_NULL_HANDLE;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Queue.cpp",
    "content": "#include \"Queue.hpp\"\n#include \"Command.hpp\"\n#include \"Device.hpp\"\n#include \"Synchronization.hpp\"\n\nnamespace Ilum::Vulkan\n{\nQueue::Queue(RHIDevice *device) :\n    RHIQueue(device), p_device(static_cast<Device *>(device))\n{\n\tfor (uint32_t i = 0; i < p_device->GetQueueCount(RHIQueueFamily::Graphics); i++)\n\t{\n\t\tm_queues[RHIQueueFamily::Graphics].push_back(VK_NULL_HANDLE);\n\t\tvkGetDeviceQueue(p_device->GetDevice(), p_device->GetQueueFamily(RHIQueueFamily::Graphics), i, &m_queues[RHIQueueFamily::Graphics].back());\n\t\tm_queue_fences.emplace(m_queues[RHIQueueFamily::Graphics].back(), VK_NULL_HANDLE);\n\n\t\t{\n\t\t\tstd::string queue_name = \"Graphics Queue - \" + std::to_string(i);\n\n\t\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\t\tinfo.pObjectName                   = queue_name.c_str();\n\t\t\tinfo.objectHandle                  = (uint64_t) m_queues[RHIQueueFamily::Graphics].back();\n\t\t\tinfo.objectType                    = VK_OBJECT_TYPE_QUEUE;\n\t\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t\t}\n\t}\n\n\tfor (uint32_t i = 0; i < p_device->GetQueueCount(RHIQueueFamily::Transfer); i++)\n\t{\n\t\tm_queues[RHIQueueFamily::Transfer].push_back(VK_NULL_HANDLE);\n\t\tvkGetDeviceQueue(p_device->GetDevice(), p_device->GetQueueFamily(RHIQueueFamily::Transfer), i, &m_queues[RHIQueueFamily::Transfer].back());\n\t\tm_queue_fences.emplace(m_queues[RHIQueueFamily::Transfer].back(), VK_NULL_HANDLE);\n\n\t\t{\n\t\t\tstd::string queue_name = \"Transfer Queue - \" + std::to_string(i);\n\n\t\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\t\tinfo.pObjectName                   = queue_name.c_str();\n\t\t\tinfo.objectHandle                  = (uint64_t) m_queues[RHIQueueFamily::Graphics].back();\n\t\t\tinfo.objectType                    = VK_OBJECT_TYPE_QUEUE;\n\t\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t\t}\n\t}\n\n\tfor (uint32_t i = 0; i < p_device->GetQueueCount(RHIQueueFamily::Compute); i++)\n\t{\n\t\tm_queues[RHIQueueFamily::Compute].push_back(VK_NULL_HANDLE);\n\t\tvkGetDeviceQueue(p_device->GetDevice(), p_device->GetQueueFamily(RHIQueueFamily::Compute), i, &m_queues[RHIQueueFamily::Compute].back());\n\t\tm_queue_fences.emplace(m_queues[RHIQueueFamily::Compute].back(), VK_NULL_HANDLE);\n\n\t\t{\n\t\t\tstd::string queue_name = \"Compute Queue - \" + std::to_string(i);\n\n\t\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\t\tinfo.pObjectName                   = queue_name.c_str();\n\t\t\tinfo.objectHandle                  = (uint64_t) m_queues[RHIQueueFamily::Graphics].back();\n\t\t\tinfo.objectType                    = VK_OBJECT_TYPE_QUEUE;\n\t\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t\t}\n\t}\n\n\tfor (auto &[queue, fence] : m_queue_fences)\n\t{\n\t\tVkFenceCreateInfo create_info = {};\n\t\tcreate_info.sType             = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;\n\t\tvkCreateFence(p_device->GetDevice(), &create_info, nullptr, &fence);\n\t}\n\n\tm_queue_index[RHIQueueFamily::Graphics] = 0;\n\tm_queue_index[RHIQueueFamily::Transfer] = 0;\n\tm_queue_index[RHIQueueFamily::Compute]  = 0;\n}\n\nQueue::~Queue()\n{\n\tp_device->WaitIdle();\n\n\tfor (auto &[queue, fence] : m_queue_fences)\n\t{\n\t\tvkDestroyFence(p_device->GetDevice(), fence, nullptr);\n\t}\n\tm_queue_fences.clear();\n}\n\nvoid Queue::Execute(RHIQueueFamily family, const std::vector<SubmitInfo> &submit_infos, RHIFence *fence)\n{\n\tVkQueue queue    = m_queues.at(family).at(m_queue_index[family]++);\n\tVkFence vk_fence = fence ? static_cast<Fence *>(fence)->GetHandle() : m_queue_fences.at(queue);\n\n\tif (vkGetFenceStatus(p_device->GetDevice(), vk_fence) == VK_SUCCESS)\n\t{\n\t\tvkWaitForFences(p_device->GetDevice(), 1, &vk_fence, VK_TRUE, std::numeric_limits<uint64_t>::max());\n\t\tvkResetFences(p_device->GetDevice(), 1, &vk_fence);\n\t}\n\n\tstd::vector<VkSubmitInfo> vk_submit_infos;\n\tvk_submit_infos.reserve(submit_infos.size());\n\n\tstd::vector<std::vector<VkPipelineStageFlags>> pipeline_stage_flags(submit_infos.size());\n\tstd::vector<std::vector<VkCommandBuffer>>      cmd_buffers(submit_infos.size());\n\tstd::vector<std::vector<VkSemaphore>>          wait_semaphores(submit_infos.size());\n\tstd::vector<std::vector<VkSemaphore>>          signal_semaphores(submit_infos.size());\n\n\tfor (uint32_t i = 0; i < submit_infos.size(); i++)\n\t{\n\t\tconst auto &submit_info = submit_infos[i];\n\n\t\tpipeline_stage_flags[i].resize(submit_info.wait_semaphores.size());\n\t\tstd::fill(pipeline_stage_flags[i].begin(), pipeline_stage_flags[i].end(),\n\t\t          submit_info.queue_family == RHIQueueFamily::Compute ?\n\t\t              VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT :\n\t\t              (submit_info.queue_family == RHIQueueFamily::Graphics ?\n\t\t                   VK_PIPELINE_STAGE_VERTEX_INPUT_BIT :\n\t\t                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));\n\n\t\tcmd_buffers[i].reserve(submit_info.cmd_buffers.size());\n\t\tfor (auto &cmd_buffer : submit_info.cmd_buffers)\n\t\t{\n\t\t\tcmd_buffers[i].push_back(static_cast<Command *>(cmd_buffer)->GetHandle());\n\t\t}\n\n\t\twait_semaphores[i].reserve(submit_info.wait_semaphores.size());\n\t\tfor (auto &wait_semaphore : submit_info.wait_semaphores)\n\t\t{\n\t\t\twait_semaphores[i].push_back(static_cast<Semaphore *>(wait_semaphore)->GetHandle());\n\t\t}\n\n\t\tsignal_semaphores[i].reserve(submit_info.signal_semaphores.size());\n\t\tfor (auto &signal_semaphore : submit_info.signal_semaphores)\n\t\t{\n\t\t\tsignal_semaphores[i].push_back(static_cast<Semaphore *>(signal_semaphore)->GetHandle());\n\t\t}\n\n\t\tVkSubmitInfo vk_submit_info = {};\n\t\tvk_submit_info.sType        = VK_STRUCTURE_TYPE_SUBMIT_INFO;\n\n\t\tvk_submit_info.commandBufferCount   = static_cast<uint32_t>(cmd_buffers[i].size());\n\t\tvk_submit_info.pCommandBuffers      = cmd_buffers[i].data();\n\t\tvk_submit_info.signalSemaphoreCount = static_cast<uint32_t>(signal_semaphores[i].size());\n\t\tvk_submit_info.pSignalSemaphores    = signal_semaphores[i].data();\n\t\tvk_submit_info.waitSemaphoreCount   = static_cast<uint32_t>(wait_semaphores[i].size());\n\t\tvk_submit_info.pWaitSemaphores      = wait_semaphores[i].data();\n\t\tvk_submit_info.pWaitDstStageMask    = pipeline_stage_flags[i].data();\n\n\t\tvk_submit_infos.push_back(std::move(vk_submit_info));\n\t}\n\n\tvkQueueSubmit(queue, static_cast<uint32_t>(vk_submit_infos.size()), vk_submit_infos.data(), vk_fence);\n\n\tm_queue_index[family] = m_queue_index[family] % p_device->GetQueueCount(family);\n}\n\nvoid Queue::Execute(RHICommand *cmd_buffer)\n{\n\tauto vk_cmd_buffer = static_cast<Command *>(cmd_buffer)->GetHandle();\n\n\tRHIQueueFamily family = cmd_buffer->GetQueueFamily();\n\n\tsize_t  index = m_queue_index[family];\n\tVkQueue queue = m_queues.at(family).at(index);\n\tVkFence fence = m_queue_fences.at(queue);\n\n\tif (vkGetFenceStatus(p_device->GetDevice(), fence) == VK_SUCCESS)\n\t{\n\t\tvkWaitForFences(p_device->GetDevice(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());\n\t\tvkResetFences(p_device->GetDevice(), 1, &fence);\n\t}\n\n\tVkSubmitInfo submit_info         = {};\n\tsubmit_info.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;\n\tsubmit_info.commandBufferCount   = 1;\n\tsubmit_info.pCommandBuffers      = &vk_cmd_buffer;\n\tsubmit_info.signalSemaphoreCount = 0;\n\tsubmit_info.pSignalSemaphores    = nullptr;\n\tsubmit_info.waitSemaphoreCount   = 0;\n\tsubmit_info.pWaitSemaphores      = nullptr;\n\tsubmit_info.pWaitDstStageMask    = nullptr;\n\n\tvkQueueSubmit(m_queues[family][index], 1, &submit_info, fence);\n\tvkWaitForFences(p_device->GetDevice(), 1, &fence, VK_TRUE, std::numeric_limits<uint64_t>::max());\n\tvkResetFences(p_device->GetDevice(), 1, &fence);\n}\n\nvoid Queue::Wait()\n{\n\tstd::vector<VkFence> fences;\n\tfences.reserve(m_queue_fences.size());\n\n\tfor (auto &[queue, fence] : m_queue_fences)\n\t{\n\t\tif (vkGetFenceStatus(p_device->GetDevice(), fence) == VK_SUCCESS)\n\t\t{\n\t\t\tfences.push_back(fence);\n\t\t}\n\t}\n\n\tvkWaitForFences(p_device->GetDevice(), static_cast<uint32_t>(fences.size()), fences.data(), VK_TRUE, std::numeric_limits<uint64_t>::max());\n\tvkResetFences(p_device->GetDevice(), static_cast<uint32_t>(fences.size()), fences.data());\n}\n\nVkQueue Queue::GetHandle(RHIQueueFamily family, uint32_t index) const\n{\n\treturn m_queues.at(family).at(index % m_queues.at(family).size());\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Queue.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Device;\n\nclass Queue : public RHIQueue\n{\n  public:\n\tQueue(RHIDevice *device);\n\n\tvirtual ~Queue();\n\n\tvirtual void Execute(RHIQueueFamily family, const std::vector<SubmitInfo> &submit_infos, RHIFence *fence) override;\n\n\tvirtual void Execute(RHICommand *cmd_buffer) override;\n\n\tvirtual void Wait() override;\n\n\tVkQueue GetHandle(RHIQueueFamily family, uint32_t index) const;\n\n  private:\n\tDevice *p_device = nullptr;\n\n\tstd::map<RHIQueueFamily, std::vector<VkQueue>>  m_queues;\n\tstd::map<RHIQueueFamily, std::atomic<size_t>> m_queue_index;\n\n\tstd::unordered_map<VkQueue, VkFence> m_queue_fences;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/RenderTarget.cpp",
    "content": "#include \"RenderTarget.hpp\"\n#include \"Definitions.hpp\"\n#include \"Device.hpp\"\n#include \"Texture.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstatic std::unordered_map<size_t, VkRenderPass>  RenderPassCache;\nstatic std::unordered_map<size_t, VkFramebuffer> FramebufferCache;\n\nstatic uint32_t RenderTargetCount = 0;\n\nRenderTarget::RenderTarget(RHIDevice *device) :\n    RHIRenderTarget(device)\n{\n\tRenderTargetCount++;\n}\n\nRenderTarget::~RenderTarget()\n{\n\tif (--RenderTargetCount == 0)\n\t{\n\t\tp_device->WaitIdle();\n\n\t\tfor (auto &[hash, render_pass] : RenderPassCache)\n\t\t{\n\t\t\tvkDestroyRenderPass(static_cast<Device *>(p_device)->GetDevice(), render_pass, nullptr);\n\t\t}\n\n\t\tfor (auto &[hash, framebuffer] : FramebufferCache)\n\t\t{\n\t\t\tvkDestroyFramebuffer(static_cast<Device *>(p_device)->GetDevice(), framebuffer, nullptr);\n\t\t}\n\n\t\tRenderPassCache.clear();\n\t\tFramebufferCache.clear();\n\t}\n}\n\nRHIRenderTarget &RenderTarget::Set(uint32_t slot, RHITexture *texture, RHITextureDimension dimension, const ColorAttachment &attachment)\n{\n\treturn Set(slot, texture, TextureRange{dimension, 0, texture->GetDesc().mips, 0, texture->GetDesc().layers}, attachment);\n}\n\nRHIRenderTarget &RenderTarget::Set(uint32_t slot, RHITexture *texture, const TextureRange &range, const ColorAttachment &attachment)\n{\n\tVkRenderingAttachmentInfo attachment_info = {};\n\tattachment_info.sType                     = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;\n\tattachment_info.loadOp                    = ToVulkanLoadOp[attachment.load];\n\tattachment_info.storeOp                   = ToVulkanStoreOp[attachment.store];\n\tattachment_info.imageView                 = static_cast<Texture *>(texture)->GetView(range);\n\tattachment_info.imageLayout               = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;\n\tstd::memcpy(attachment_info.clearValue.color.float32, attachment.clear_value.data(), 4 * sizeof(float));\n\n\tHashCombine(m_hash, attachment_info.loadOp, attachment_info.storeOp, attachment_info.imageView, attachment_info.imageLayout);\n\n\twhile (slot >= m_color_attachments.size())\n\t{\n\t\tm_color_attachments.push_back({});\n\t\tm_color_formats.push_back({});\n\t}\n\n\tm_color_attachments[slot] = attachment_info;\n\tm_color_formats[slot]     = ToVulkanFormat[texture->GetDesc().format];\n\n\tm_width  = std::max(m_width, texture->GetDesc().width);\n\tm_height = std::max(m_height, texture->GetDesc().height);\n\tm_layers = std::max(m_layers, texture->GetDesc().layers);\n\n\treturn *this;\n}\n\nRHIRenderTarget &RenderTarget::Set(RHITexture *texture, RHITextureDimension dimension, const DepthStencilAttachment &attachment)\n{\n\treturn Set(texture, TextureRange{dimension, 0, texture->GetDesc().mips, 0, texture->GetDesc().layers}, attachment);\n}\n\nRHIRenderTarget &RenderTarget::Set(RHITexture *texture, const TextureRange &range, const DepthStencilAttachment &attachment)\n{\n\tVkRenderingAttachmentInfo attachment_info     = {};\n\tattachment_info.sType                         = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;\n\tattachment_info.loadOp                        = ToVulkanLoadOp[attachment.depth_load];\n\tattachment_info.storeOp                       = ToVulkanStoreOp[attachment.depth_store];\n\tattachment_info.imageView                     = static_cast<Texture *>(texture)->GetView(range);\n\tattachment_info.imageLayout                   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;\n\tattachment_info.clearValue.depthStencil.depth = attachment.clear_depth;\n\n\tHashCombine(m_hash, attachment_info.loadOp, attachment_info.storeOp, attachment_info.imageView, attachment_info.imageLayout);\n\n\tm_depth_attachment = attachment_info;\n\tm_depth_format     = ToVulkanFormat[texture->GetDesc().format];\n\n\tif (IsStencilFormat(texture->GetDesc().format))\n\t{\n\t\tattachment_info.loadOp                          = ToVulkanLoadOp[attachment.stencil_load];\n\t\tattachment_info.storeOp                         = ToVulkanStoreOp[attachment.stencil_store];\n\t\tattachment_info.clearValue.depthStencil.stencil = attachment.clear_stencil;\n\t\tm_stencil_attachment                            = attachment_info;\n\t\tm_stencil_format                                = ToVulkanFormat[texture->GetDesc().format];\n\n\t\tHashCombine(m_hash, attachment_info.loadOp, attachment_info.storeOp);\n\t}\n\n\tm_width  = std::max(m_width, texture->GetDesc().width);\n\tm_height = std::max(m_height, texture->GetDesc().height);\n\tm_layers = std::max(m_layers, texture->GetDesc().layers);\n\n\treturn *this;\n}\n\nVkRenderPass RenderTarget::GetRenderPass() const\n{\n\tstd::vector<VkAttachmentDescription> descriptions;\n\tstd::vector<VkAttachmentReference>   color_references;\n\tstd::optional<VkAttachmentReference> depth_stencil_reference;\n\n\tfor (uint32_t i = 0; i < m_color_attachments.size(); i++)\n\t{\n\t\tVkAttachmentDescription description = {};\n\t\tdescription.samples                 = VK_SAMPLE_COUNT_1_BIT;\n\t\tdescription.initialLayout           = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;\n\t\tdescription.finalLayout             = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;\n\t\tdescription.loadOp                  = m_color_attachments[i].loadOp;\n\t\tdescription.storeOp                 = m_color_attachments[i].storeOp;\n\t\tdescription.format                  = m_color_formats[i];\n\n\t\tVkAttachmentReference reference = {};\n\t\treference.attachment            = static_cast<uint32_t>(descriptions.size());\n\t\treference.layout                = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;\n\n\t\tdescriptions.push_back(description);\n\t\tcolor_references.push_back(reference);\n\t}\n\n\tif (m_depth_attachment.has_value() || m_stencil_attachment.has_value())\n\t{\n\t\tVkAttachmentDescription description = {};\n\t\tdescription.samples                 = VK_SAMPLE_COUNT_1_BIT;\n\t\tdescription.initialLayout           = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;\n\t\tdescription.finalLayout             = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;\n\t\tdescription.format                  = m_depth_format.value();\n\n\t\tif (m_depth_attachment.has_value())\n\t\t{\n\t\t\tdescription.loadOp  = m_depth_attachment.value().loadOp;\n\t\t\tdescription.storeOp = m_depth_attachment.value().storeOp;\n\t\t}\n\n\t\tif (m_stencil_attachment.has_value())\n\t\t{\n\t\t\tdescription.stencilLoadOp  = m_stencil_attachment.value().loadOp;\n\t\t\tdescription.stencilStoreOp = m_stencil_attachment.value().storeOp;\n\t\t}\n\n\t\tVkAttachmentReference reference = {};\n\t\treference.attachment            = static_cast<uint32_t>(descriptions.size());\n\t\treference.layout                = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;\n\n\t\tdescriptions.push_back(description);\n\t\tdepth_stencil_reference = reference;\n\t}\n\n\tif (RenderPassCache.find(m_hash) != RenderPassCache.end())\n\t{\n\t\treturn RenderPassCache.at(m_hash);\n\t}\n\n\tVkRenderPass render_pass = VK_NULL_HANDLE;\n\n\tVkSubpassDescription subpass_description    = {};\n\tsubpass_description.pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;\n\tsubpass_description.colorAttachmentCount    = static_cast<uint32_t>(color_references.size());\n\tsubpass_description.pColorAttachments       = color_references.data();\n\tsubpass_description.pDepthStencilAttachment = depth_stencil_reference.has_value() ? &depth_stencil_reference.value() : nullptr;\n\n\tstd::array<VkSubpassDependency, 2> subpass_dependencies;\n\n\tsubpass_dependencies[0].srcSubpass      = VK_SUBPASS_EXTERNAL;\n\tsubpass_dependencies[0].dstSubpass      = 0;\n\tsubpass_dependencies[0].srcStageMask    = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;\n\tsubpass_dependencies[0].dstStageMask    = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;\n\tsubpass_dependencies[0].srcAccessMask   = VK_ACCESS_MEMORY_READ_BIT;\n\tsubpass_dependencies[0].dstAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;\n\tsubpass_dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;\n\n\tsubpass_dependencies[1].srcSubpass      = 0;\n\tsubpass_dependencies[1].dstSubpass      = VK_SUBPASS_EXTERNAL;\n\tsubpass_dependencies[1].srcStageMask    = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;\n\tsubpass_dependencies[1].dstStageMask    = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;\n\tsubpass_dependencies[1].srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;\n\tsubpass_dependencies[1].dstAccessMask   = VK_ACCESS_MEMORY_READ_BIT;\n\tsubpass_dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;\n\n\t// Create render pass\n\tVkRenderPassCreateInfo render_pass_create_info = {};\n\trender_pass_create_info.sType                  = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;\n\trender_pass_create_info.attachmentCount        = static_cast<uint32_t>(descriptions.size());\n\trender_pass_create_info.pAttachments           = descriptions.data();\n\trender_pass_create_info.subpassCount           = 1;\n\trender_pass_create_info.pSubpasses             = &subpass_description;\n\trender_pass_create_info.dependencyCount        = static_cast<uint32_t>(subpass_dependencies.size());\n\trender_pass_create_info.pDependencies          = subpass_dependencies.data();\n\n\tvkCreateRenderPass(static_cast<Device *>(p_device)->GetDevice(), &render_pass_create_info, nullptr, &render_pass);\n\n\tRenderPassCache.emplace(m_hash, render_pass);\n\n\treturn render_pass;\n}\n\nVkFramebuffer RenderTarget::GetFramebuffer() const\n{\n\tstd::vector<VkImageView> views;\n\tviews.reserve(m_color_attachments.size() + 1);\n\tfor (auto &attachment : m_color_attachments)\n\t{\n\t\tviews.push_back(attachment.imageView);\n\t}\n\tif (m_depth_attachment.has_value())\n\t{\n\t\tviews.push_back(m_depth_attachment.value().imageView);\n\t}\n\n\tsize_t hash = 0;\n\tHashCombine(hash, views);\n\n\tif (FramebufferCache.find(hash) != FramebufferCache.end())\n\t{\n\t\treturn FramebufferCache.at(hash);\n\t}\n\n\tVkFramebufferCreateInfo frame_buffer_create_info = {};\n\tframe_buffer_create_info.sType                   = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;\n\tframe_buffer_create_info.renderPass              = GetRenderPass();\n\tframe_buffer_create_info.attachmentCount         = static_cast<uint32_t>(views.size());\n\tframe_buffer_create_info.pAttachments            = views.data();\n\tframe_buffer_create_info.width                   = m_width;\n\tframe_buffer_create_info.height                  = m_height;\n\tframe_buffer_create_info.layers                  = m_layers;\n\n\tVkFramebuffer frame_buffer = VK_NULL_HANDLE;\n\tvkCreateFramebuffer(static_cast<Device *>(p_device)->GetDevice(), &frame_buffer_create_info, nullptr, &frame_buffer);\n\n\tFramebufferCache.emplace(hash, frame_buffer);\n\n\treturn frame_buffer;\n}\n\nVkRect2D RenderTarget::GetRenderArea() const\n{\n\treturn VkRect2D{\n\t    VkOffset2D{0, 0},\n\t    VkExtent2D{m_width, m_height}};\n}\n\nstd::vector<VkClearValue> RenderTarget::GetClearValue() const\n{\n\tstd::vector<VkClearValue> clear_values;\n\tclear_values.reserve(m_color_attachments.size() + 1);\n\tfor (auto &attachment : m_color_attachments)\n\t{\n\t\tclear_values.push_back(attachment.clearValue);\n\t}\n\tif (m_depth_attachment.has_value())\n\t{\n\t\tclear_values.push_back(m_depth_attachment.value().clearValue);\n\t}\n\n\treturn clear_values;\n}\n\nconst std::vector<VkRenderingAttachmentInfo> &RenderTarget::GetColorAttachments()\n{\n\treturn m_color_attachments;\n}\n\nconst std::optional<VkRenderingAttachmentInfo> &RenderTarget::GetDepthAttachment()\n{\n\treturn m_depth_attachment;\n}\n\nconst std::optional<VkRenderingAttachmentInfo> &RenderTarget::GetStencilAttachment()\n{\n\treturn m_stencil_attachment;\n}\n\nconst std::vector<VkFormat> &RenderTarget::GetColorFormats()\n{\n\treturn m_color_formats;\n}\n\nconst std::optional<VkFormat> &RenderTarget::GetDepthFormat()\n{\n\treturn m_depth_format;\n}\n\nconst std::optional<VkFormat> &RenderTarget::GetStencilFormat()\n{\n\treturn m_stencil_format;\n}\n\nsize_t RenderTarget::GetFormatHash() const\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, m_color_formats);\n\n\tif (m_depth_format.has_value())\n\t{\n\t\tHashCombine(hash, m_depth_format.value());\n\t}\n\n\tif (m_stencil_format.has_value())\n\t{\n\t\tHashCombine(hash, m_stencil_format.value());\n\t}\n\n\treturn hash;\n}\n\nsize_t RenderTarget::GetHash() const\n{\n\treturn m_hash;\n}\n\nRHIRenderTarget &RenderTarget::Clear()\n{\n\tm_color_attachments.clear();\n\tm_depth_attachment.reset();\n\tm_stencil_attachment.reset();\n\n\tm_color_formats.clear();\n\tm_depth_format.reset();\n\tm_stencil_format.reset();\n\n\tm_width  = 0;\n\tm_height = 0;\n\n\tm_hash = 0;\n\n\treturn *this;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/RenderTarget.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstruct FrameBufferResolve\n{\n\tVkImageView  view;\n\tVkClearValue clear_value;\n};\n\nclass RenderTarget : public RHIRenderTarget\n{\n  public:\n\tRenderTarget(RHIDevice *device);\n\n\tvirtual ~RenderTarget() override;\n\n\tvirtual RHIRenderTarget &Set(uint32_t slot, RHITexture *texture, RHITextureDimension dimension, const ColorAttachment &attachment) override;\n\tvirtual RHIRenderTarget &Set(uint32_t slot, RHITexture *texture, const TextureRange &range, const ColorAttachment &attachment) override;\n\tvirtual RHIRenderTarget &Set(RHITexture *texture, RHITextureDimension dimension, const DepthStencilAttachment &attachment) override;\n\tvirtual RHIRenderTarget &Set(RHITexture *texture, const TextureRange &range, const DepthStencilAttachment &attachment) override;\n\n\tVkRenderPass GetRenderPass() const;\n\n\tVkFramebuffer GetFramebuffer() const;\n\n\tVkRect2D GetRenderArea() const;\n\n\tstd::vector<VkClearValue> GetClearValue() const;\n\n\tconst std::vector<VkRenderingAttachmentInfo> &GetColorAttachments();\n\n\tconst std::optional<VkRenderingAttachmentInfo> &GetDepthAttachment();\n\n\tconst std::optional<VkRenderingAttachmentInfo> &GetStencilAttachment();\n\n\tconst std::vector<VkFormat> &GetColorFormats();\n\n\tconst std::optional<VkFormat> &GetDepthFormat();\n\n\tconst std::optional<VkFormat> &GetStencilFormat();\n\n\tsize_t GetFormatHash() const;\n\n\tsize_t GetHash() const;\n\n\tvirtual RHIRenderTarget &Clear() override;\n\n  private:\n\t// Dynamic Rendering\n\tstd::vector<VkRenderingAttachmentInfo>   m_color_attachments;\n\tstd::optional<VkRenderingAttachmentInfo> m_depth_attachment;\n\tstd::optional<VkRenderingAttachmentInfo> m_stencil_attachment;\n\n\tstd::vector<VkFormat>   m_color_formats;\n\tstd::optional<VkFormat> m_depth_format;\n\tstd::optional<VkFormat> m_stencil_format;\n\n\tsize_t m_hash = 0;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Sampler.cpp",
    "content": "#include \"Sampler.hpp\"\n#include \"Definitions.hpp\"\n#include \"Device.hpp\"\n\nnamespace Ilum::Vulkan\n{\nSampler::Sampler(RHIDevice *device, const SamplerDesc &desc) :\n    RHISampler(device, desc)\n{\n\tVkSamplerCreateInfo create_info = {};\n\tcreate_info.sType               = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;\n\tcreate_info.minFilter           = ToVulkanFilter[desc.min_filter];\n\tcreate_info.magFilter           = ToVulkanFilter[desc.mag_filter];\n\tcreate_info.mipmapMode          = ToVulkanMipmapMode[desc.mipmap_mode];\n\tcreate_info.addressModeU        = ToVulkanAddressMode[desc.address_mode_u];\n\tcreate_info.addressModeV        = ToVulkanAddressMode[desc.address_mode_v];\n\tcreate_info.addressModeW        = ToVulkanAddressMode[desc.address_mode_w];\n\tcreate_info.anisotropyEnable    = desc.anisotropic;\n\tcreate_info.maxAnisotropy       = 16.f;\n\tcreate_info.mipLodBias          = desc.mip_lod_bias;\n\tcreate_info.minLod              = desc.min_lod;\n\tcreate_info.maxLod              = desc.max_lod;\n\tcreate_info.borderColor         = ToVulkanBorderColor[desc.border_color];\n\n\tvkCreateSampler(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &m_handle);\n}\n\nSampler::~Sampler()\n{\n\tif (m_handle)\n\t{\n\t\tvkDestroySampler(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t}\n}\n\nVkSampler Sampler::GetHandle() const\n{\n\treturn m_handle;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Sampler.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Sampler : public RHISampler\n{\n  public:\n\tSampler(RHIDevice *device, const SamplerDesc &desc);\n\tvirtual ~Sampler() override;\n\n\tVkSampler GetHandle() const;\n\n  private:\n\tVkSampler m_handle = VK_NULL_HANDLE;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Shader.cpp",
    "content": "#pragma once\n\n#include \"Shader.hpp\"\n#include \"Device.hpp\"\n\nnamespace Ilum::Vulkan\n{\nShader::Shader(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source) :\n    RHIShader(device, entry_point, source)\n{\n\tVkShaderModuleCreateInfo create_info = {};\n\tcreate_info.sType                    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;\n\tcreate_info.codeSize                 = source.size();\n\tcreate_info.pCode                    = reinterpret_cast<const uint32_t *>(source.data());\n\tvkCreateShaderModule(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &m_handle);\n}\n\nShader::~Shader()\n{\n\tif (m_handle)\n\t{\n\t\tvkDestroyShaderModule(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t}\n}\n\nVkShaderModule Shader::GetHandle() const\n{\n\treturn m_handle;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Shader.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Shader : public RHIShader\n{\n  public:\n\tShader(RHIDevice *device, const std::string& entry_point, const std::vector<uint8_t> &source);\n\t\n\tvirtual ~Shader() override;\n\n\tVkShaderModule GetHandle() const;\n\n  private:\n\tVkShaderModule m_handle = VK_NULL_HANDLE;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Swapchain.cpp",
    "content": "#pragma once\n\n#include \"Swapchain.hpp\"\n#include \"Command.hpp\"\n#include \"Device.hpp\"\n#include \"Queue.hpp\"\n#include \"Synchronization.hpp\"\n#include \"Texture.hpp\"\n\n#include <Core/Time.hpp>\n\n#ifdef _WIN32\n#\tinclude <Windows.h>\n#endif\n\n#include <algorithm>\n\nnamespace Ilum::Vulkan\n{\ninline std::optional<uint32_t> GetQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> &queue_family_properties, VkQueueFlagBits queue_flag)\n{\n\t// Dedicated queue for compute\n\t// Try to find a queue family index that supports compute but not graphics\n\tif (queue_flag & VK_QUEUE_COMPUTE_BIT)\n\t{\n\t\tfor (uint32_t i = 0; i < static_cast<uint32_t>(queue_family_properties.size()); i++)\n\t\t{\n\t\t\tif ((queue_family_properties[i].queueFlags & queue_flag) && ((queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0))\n\t\t\t{\n\t\t\t\treturn i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Dedicated queue for transfer\n\t// Try to find a queue family index that supports transfer but not graphics and compute\n\tif (queue_flag & VK_QUEUE_TRANSFER_BIT)\n\t{\n\t\tfor (uint32_t i = 0; i < static_cast<uint32_t>(queue_family_properties.size()); i++)\n\t\t{\n\t\t\tif ((queue_family_properties[i].queueFlags & queue_flag) && ((queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) && ((queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0))\n\t\t\t{\n\t\t\t\treturn i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// For other queue types or if no separate compute queue is present, return the first one to support the requested flags\n\tfor (uint32_t i = 0; i < static_cast<uint32_t>(queue_family_properties.size()); i++)\n\t{\n\t\tif (queue_family_properties[i].queueFlags & queue_flag)\n\t\t{\n\t\t\treturn i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn std::optional<uint32_t>();\n}\n\ninline VkPresentModeKHR GetPresentMode(const VkPhysicalDevice &physical_device, const VkSurfaceKHR &surface, bool vsync)\n{\n\tuint32_t                      presentmode_count;\n\tstd::vector<VkPresentModeKHR> presentmodes;\n\tvkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &presentmode_count, nullptr);\n\tif (presentmode_count != 0)\n\t{\n\t\tpresentmodes.resize(presentmode_count);\n\t\tvkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &presentmode_count, presentmodes.data());\n\t}\n\n\tfor (VkPresentModeKHR present_mode : presentmodes)\n\t{\n\t\tif (!vsync)\n\t\t{\n\t\t\tif (VK_PRESENT_MODE_MAILBOX_KHR == present_mode)\n\t\t\t{\n\t\t\t\treturn VK_PRESENT_MODE_MAILBOX_KHR;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (VK_PRESENT_MODE_FIFO_KHR == present_mode)\n\t\t\t{\n\t\t\t\treturn VK_PRESENT_MODE_FIFO_KHR;\n\t\t\t}\n\t\t}\n\t}\n\treturn VK_PRESENT_MODE_FIFO_KHR;\n}\n\nSwapchain::Swapchain(Device *device, void *window_handle, uint32_t width, uint32_t height, bool vsync) :\n    RHISwapchain(device, width, height, vsync)\n{\n#ifdef _WIN32\n\t{\n\t\tVkWin32SurfaceCreateInfoKHR createInfo{};\n\t\tcreateInfo.sType     = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;\n\t\tcreateInfo.hwnd      = (HWND) window_handle;\n\t\tcreateInfo.hinstance = GetModuleHandle(nullptr);\n\t\tauto result          = vkCreateWin32SurfaceKHR(static_cast<Device *>(device)->GetInstance(), &createInfo, nullptr, &m_surface);\n\t}\n#endif        // _WIN32\n\n\t// m_capabilities\n\tauto result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(static_cast<Device *>(device)->GetPhysicalDevice(), m_surface, &m_capabilities);\n\n\t// formats\n\tuint32_t                        format_count;\n\tstd::vector<VkSurfaceFormatKHR> formats;\n\tvkGetPhysicalDeviceSurfaceFormatsKHR(static_cast<Device *>(device)->GetPhysicalDevice(), m_surface, &format_count, nullptr);\n\tif (format_count != 0)\n\t{\n\t\tformats.resize(format_count);\n\t\tvkGetPhysicalDeviceSurfaceFormatsKHR(static_cast<Device *>(device)->GetPhysicalDevice(), m_surface, &format_count, formats.data());\n\t}\n\n\t// Choose swapchain surface format\n\tfor (const auto &surface_format : formats)\n\t{\n\t\tif (surface_format.format == VK_FORMAT_B8G8R8A8_UNORM &&\n\t\t    surface_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)\n\t\t{\n\t\t\tm_surface_format = surface_format;\n\t\t}\n\t}\n\tif (m_surface_format.format == VK_FORMAT_UNDEFINED)\n\t{\n\t\tm_surface_format = formats[0];\n\t}\n\n\t// Choose swapchain extent\n\tVkExtent2D chosen_extent = {};\n\tif (m_capabilities.currentExtent.width != UINT32_MAX)\n\t{\n\t\tchosen_extent = m_capabilities.currentExtent;\n\t}\n\telse\n\t{\n\t\tVkExtent2D actualExtent = {};\n\t\tactualExtent.width      = width;\n\t\tactualExtent.height     = height;\n\n\t\tactualExtent.width =\n\t\t    std::clamp(actualExtent.width, m_capabilities.minImageExtent.width, m_capabilities.maxImageExtent.width);\n\t\tactualExtent.height =\n\t\t    std::clamp(actualExtent.height, m_capabilities.minImageExtent.height, m_capabilities.maxImageExtent.height);\n\n\t\tchosen_extent = actualExtent;\n\t}\n\n\tm_image_count = m_capabilities.minImageCount + 1;\n\tif (m_capabilities.maxImageCount > 0 && m_image_count > m_capabilities.maxImageCount)\n\t{\n\t\tm_image_count = m_capabilities.maxImageCount;\n\t}\n\n\t// Queue supporting\n\tuint32_t queue_family_property_count = 0;\n\tvkGetPhysicalDeviceQueueFamilyProperties(static_cast<Device *>(p_device)->GetPhysicalDevice(), &queue_family_property_count, nullptr);\n\tstd::vector<VkQueueFamilyProperties> queue_family_properties(queue_family_property_count);\n\tvkGetPhysicalDeviceQueueFamilyProperties(static_cast<Device *>(p_device)->GetPhysicalDevice(), &queue_family_property_count, queue_family_properties.data());\n\n\tstd::optional<uint32_t> graphics_family, compute_family, transfer_family;\n\n\tgraphics_family = GetQueueFamilyIndex(queue_family_properties, VK_QUEUE_GRAPHICS_BIT);\n\ttransfer_family = GetQueueFamilyIndex(queue_family_properties, VK_QUEUE_TRANSFER_BIT);\n\tcompute_family  = GetQueueFamilyIndex(queue_family_properties, VK_QUEUE_COMPUTE_BIT);\n\n\tVkQueueFlags support_queues = 0;\n\n\tfor (uint32_t i = 0; i < queue_family_property_count; i++)\n\t{\n\t\t// Check for presentation support\n\t\tVkBool32 present_support;\n\t\tvkGetPhysicalDeviceSurfaceSupportKHR(static_cast<Device *>(p_device)->GetPhysicalDevice(), i, m_surface, &present_support);\n\n\t\tif (queue_family_properties[i].queueCount > 0 && present_support)\n\t\t{\n\t\t\tm_present_family = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvkGetDeviceQueue(static_cast<Device *>(p_device)->GetDevice(), m_present_family, 0, &m_present_queue);\n\n\tResize(chosen_extent.width, chosen_extent.height, m_vsync);\n}\n\nSwapchain::~Swapchain()\n{\n\tif (m_swapchain)\n\t{\n\t\tvkDestroySwapchainKHR(static_cast<Device *>(p_device)->GetDevice(), m_swapchain, nullptr);\n\t}\n\n\tif (m_surface)\n\t{\n\t\tvkDestroySurfaceKHR(static_cast<Device *>(p_device)->GetInstance(), m_surface, nullptr);\n\t}\n}\n\nuint32_t Swapchain::GetTextureCount()\n{\n\treturn static_cast<uint32_t>(m_textures.size());\n}\n\nvoid Swapchain::AcquireNextTexture(RHISemaphore *signal_semaphore, RHIFence *signal_fence)\n{\n\tauto result = vkAcquireNextImageKHR(\n\t    static_cast<Device *>(p_device)->GetDevice(),\n\t    m_swapchain,\n\t    std::numeric_limits<uint64_t>::max(),\n\t    signal_semaphore ? static_cast<Semaphore *>(signal_semaphore)->GetHandle() : nullptr,\n\t    signal_fence ? static_cast<Fence *>(signal_fence)->GetHandle() : nullptr,\n\t    &m_frame_index);\n}\n\nRHITexture *Swapchain::GetCurrentTexture()\n{\n\treturn m_textures[m_frame_index].get();\n}\n\nuint32_t Swapchain::GetCurrentFrameIndex()\n{\n\treturn m_frame_index;\n}\n\nbool Swapchain::Present(RHISemaphore *semaphore)\n{\n\tVkSemaphore semaphore_handle = semaphore ? static_cast<Semaphore *>(semaphore)->GetHandle() : VK_NULL_HANDLE;\n\n\tVkPresentInfoKHR present_info = {};\n\tpresent_info.sType            = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;\n\tpresent_info.pNext            = NULL;\n\tpresent_info.swapchainCount   = 1;\n\tpresent_info.pSwapchains      = &m_swapchain;\n\tpresent_info.pImageIndices    = &m_frame_index;\n\n\tif (semaphore)\n\t{\n\t\tpresent_info.pWaitSemaphores    = &semaphore_handle;\n\t\tpresent_info.waitSemaphoreCount = 1;\n\t}\n\n\tvkQueueWaitIdle(m_present_queue);\n\tauto result = vkQueuePresentKHR(m_present_queue, &present_info);\n\n\tif (result == VK_ERROR_OUT_OF_DATE_KHR)\n\t{\n\t\tm_frame_index = 0;\n\t}\n\n\treturn result == VK_SUCCESS;\n}\n\nvoid Swapchain::Resize(uint32_t width, uint32_t height, bool vsync)\n{\n\tp_device->WaitIdle();\n\n\tm_width  = width;\n\tm_height = height;\n\tm_vsync  = vsync;\n\n\tVkSwapchainCreateInfoKHR createInfo = {};\n\tcreateInfo.sType                    = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;\n\tcreateInfo.surface                  = m_surface;\n\n\tcreateInfo.minImageCount    = m_image_count;\n\tcreateInfo.imageFormat      = m_surface_format.format;\n\tcreateInfo.imageColorSpace  = m_surface_format.colorSpace;\n\tcreateInfo.imageExtent      = VkExtent2D{width, height};\n\tcreateInfo.imageArrayLayers = 1;\n\tcreateInfo.imageUsage       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT;\n\n\tuint32_t queueFamilyIndices[] = {m_present_family};\n\n\tcreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;\n\tcreateInfo.preTransform     = m_capabilities.currentTransform;\n\tcreateInfo.compositeAlpha   = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;\n\tcreateInfo.presentMode      = GetPresentMode(static_cast<Device *>(p_device)->GetPhysicalDevice(), m_surface, m_vsync);\n\tcreateInfo.clipped          = VK_TRUE;\n\n\tVkSwapchainKHR old_swapchain = m_swapchain;\n\n\tcreateInfo.oldSwapchain = old_swapchain;\n\n\tvkCreateSwapchainKHR(static_cast<Device *>(p_device)->GetDevice(), &createInfo, nullptr, &m_swapchain);\n\n\tif (old_swapchain)\n\t{\n\t\tvkDestroySwapchainKHR(static_cast<Device *>(p_device)->GetDevice(), old_swapchain, nullptr);\n\t}\n\n\t{\n\t\tm_textures.clear();\n\n\t\tTextureDesc desc = {};\n\t\tdesc.width       = width;\n\t\tdesc.height      = height;\n\t\tdesc.depth       = 1;\n\t\tdesc.mips        = 1;\n\t\tdesc.layers      = 1;\n\t\tdesc.samples     = 1;\n\n\t\t// TODO: Maybe different format?\n\t\tdesc.format = RHIFormat::B8G8R8A8_UNORM;\n\t\tdesc.usage  = RHITextureUsage::RenderTarget | RHITextureUsage::UnorderedAccess;\n\n\t\tuint32_t m_image_count = 0;\n\n\t\tstd::vector<VkImage> images;\n\t\tvkGetSwapchainImagesKHR(static_cast<Device *>(p_device)->GetDevice(), m_swapchain, &m_image_count, nullptr);\n\t\timages.resize(m_image_count);\n\t\tvkGetSwapchainImagesKHR(static_cast<Device *>(p_device)->GetDevice(), m_swapchain, &m_image_count, images.data());\n\n\t\tfor (size_t i = 0; i < images.size(); i++)\n\t\t{\n\t\t\tdesc.name = \"Swapchain Image \" + std::to_string(i);\n\t\t\tm_textures.emplace_back(std::make_unique<Texture>(static_cast<Device *>(p_device), desc, images[i]));\n\t\t}\n\t}\n\n\t{\n\t\tauto cmd_buffer = std::make_unique<Command>(p_device, RHIQueueFamily::Graphics);\n\t\tcmd_buffer->Init();\n\t\tcmd_buffer->Begin();\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_textures[0].get(), RHIResourceState::Undefined, RHIResourceState::Present, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{m_textures[1].get(), RHIResourceState::Undefined, RHIResourceState::Present, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{m_textures[2].get(), RHIResourceState::Undefined, RHIResourceState::Present, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t\t                                    {});\n\t\tcmd_buffer->End();\n\t\tauto fence = std::make_unique<Fence>(p_device);\n\n\t\tauto vk_cmd_buffer = cmd_buffer->GetHandle();\n\n\t\tVkSubmitInfo submit_info         = {};\n\t\tsubmit_info.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;\n\t\tsubmit_info.commandBufferCount   = 1;\n\t\tsubmit_info.pCommandBuffers      = &vk_cmd_buffer;\n\t\tsubmit_info.signalSemaphoreCount = 0;\n\t\tsubmit_info.pSignalSemaphores    = nullptr;\n\t\tsubmit_info.waitSemaphoreCount   = 0;\n\t\tsubmit_info.pWaitSemaphores      = nullptr;\n\t\tsubmit_info.pWaitDstStageMask    = nullptr;\n\n\t\tvkQueueSubmit(m_present_queue, 1, &submit_info, fence ? fence->GetHandle() : nullptr);\n\t\tfence->Wait();\n\t}\n\n\tm_frame_index = 0;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Swapchain.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Texture;\nclass Queue;\nclass Device;\n\nclass Swapchain : public RHISwapchain\n{\n  public:\n\tSwapchain(Device *device, void *window_handle, uint32_t width, uint32_t height, bool vsync);\n\n\tvirtual ~Swapchain() override;\n\n\tvirtual uint32_t GetTextureCount() override;\n\n\tvirtual void AcquireNextTexture(RHISemaphore *signal_semaphore, RHIFence *signal_fence) override;\n\n\tvirtual RHITexture *GetCurrentTexture() override;\n\n\tvirtual uint32_t GetCurrentFrameIndex() override;\n\n\tvirtual bool Present(RHISemaphore *semaphore) override;\n\n\tvirtual void Resize(uint32_t width, uint32_t height, bool vsync) override;\n\n  private:\n\tVkSurfaceKHR   m_surface   = VK_NULL_HANDLE;\n\tVkSwapchainKHR m_swapchain = VK_NULL_HANDLE;\n\n\tVkQueue m_present_queue = VK_NULL_HANDLE;\n\tuint32_t m_present_family = 0;\n\n\tstd::vector<std::unique_ptr<Texture>> m_textures;\n\n\tuint32_t                 m_image_count = 0;\n\tVkSurfaceFormatKHR       m_surface_format;\n\tVkSurfaceCapabilitiesKHR m_capabilities;\n\n\tuint32_t m_frame_index = 0;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Synchronization.cpp",
    "content": "#include \"Synchronization.hpp\"\n#include \"Device.hpp\"\n\n#include <dxgi1_2.h>\n\nnamespace Ilum::Vulkan\n{\nFence::Fence(RHIDevice *device) :\n    RHIFence(device)\n{\n\tVkFenceCreateInfo create_info = {};\n\tcreate_info.sType             = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;\n\tvkCreateFence(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &m_handle);\n}\n\nFence::~Fence()\n{\n\tif (m_handle)\n\t{\n\t\tvkDestroyFence(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t}\n}\n\nvoid Fence::Wait(uint64_t timeout)\n{\n\tvkWaitForFences(static_cast<Device *>(p_device)->GetDevice(), 1, &m_handle, true, timeout);\n}\n\nvoid Fence::Reset()\n{\n\tvkResetFences(static_cast<Device *>(p_device)->GetDevice(), 1, &m_handle);\n}\n\nVkFence Fence::GetHandle() const\n{\n\treturn m_handle;\n}\n\nSemaphore::Semaphore(RHIDevice *device) :\n    RHISemaphore(device)\n{\n\tVkSemaphoreCreateInfo create_info = {};\n\tcreate_info.sType                 = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;\n\tcreate_info.pNext                 = nullptr;\n\n#ifdef CUDA_ENABLE\n#\tif defined(_WIN64)\n\tWindowsSecurityAttributes windows_security_attributes;\n\n\tVkExportSemaphoreWin32HandleInfoKHR export_semaphore_win32_handle_info = {};\n\texport_semaphore_win32_handle_info.sType                               = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR;\n\texport_semaphore_win32_handle_info.pNext                               = NULL;\n\texport_semaphore_win32_handle_info.pAttributes                         = &windows_security_attributes;\n\texport_semaphore_win32_handle_info.dwAccess                            = DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;\n\texport_semaphore_win32_handle_info.name                                = (LPCWSTR) NULL;\n#\tendif\n\tVkExportSemaphoreCreateInfoKHR export_semaphore_create_info = {};\n\n\texport_semaphore_create_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR;\n#\tif defined(_WIN64)\n\texport_semaphore_create_info.pNext       = &export_semaphore_win32_handle_info;\n\texport_semaphore_create_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#\telse\n\texport_semaphore_create_info.pNext       = NULL;\n\texport_semaphore_create_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;\n#\tendif\n\tcreate_info.pNext = &export_semaphore_create_info;\n#endif        // CUDA_ENABLE\n\n\n\n\tvkCreateSemaphore(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &m_handle);\n}\n\nSemaphore::~Semaphore()\n{\n\tif (m_handle)\n\t{\n\t\tvkDestroySemaphore(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t}\n}\n\nvoid Semaphore::SetName(const std::string &name)\n{\n\tVkDebugUtilsObjectNameInfoEXT info = {};\n\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\tinfo.pObjectName                   = name.c_str();\n\tinfo.objectHandle                  = (uint64_t) m_handle;\n\tinfo.objectType                    = VK_OBJECT_TYPE_SEMAPHORE;\n\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n}\n\nVkSemaphore Semaphore::GetHandle() const\n{\n\treturn m_handle;\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Synchronization.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nclass Fence : public RHIFence\n{\n  public:\n\tFence(RHIDevice *device);\n\tvirtual ~Fence() override;\n\n\tvirtual void Wait(uint64_t timeout = std::numeric_limits<uint64_t>::max()) override;\n\tvirtual void Reset() override;\n\n\tVkFence GetHandle() const;\n\n  private:\n\tVkFence m_handle = VK_NULL_HANDLE;\n};\n\nclass Semaphore : public RHISemaphore\n{\n  public:\n\tSemaphore(RHIDevice *device);\n\n\tvirtual ~Semaphore() override;\n\n\tvirtual void SetName(const std::string &name) override;\n\n\tVkSemaphore GetHandle() const;\n\n  private:\n\tVkSemaphore m_handle = VK_NULL_HANDLE;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Texture.cpp",
    "content": "#include \"Texture.hpp\"\n#include \"Definitions.hpp\"\n#include \"Device.hpp\"\n\n#include <dxgi1_2.h>\n\nnamespace Ilum::Vulkan\n{\nTextureState TextureState::Create(RHIResourceState state)\n{\n\tTextureState vk_state = {};\n\n\tswitch (state)\n\t{\n\t\tcase RHIResourceState::TransferSource:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_TRANSFER_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_TRANSFER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::TransferDest:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_TRANSFER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::ShaderResource:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_SHADER_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::UnorderedAccess:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_GENERAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::RenderTarget:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::DepthWrite:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::DepthRead:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;\n\t\t\tvk_state.access_mask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;\n\t\t\tbreak;\n\t\tcase RHIResourceState::Present:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;\n\t\t\tvk_state.access_mask = VK_ACCESS_MEMORY_READ_BIT;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tvk_state.layout      = VK_IMAGE_LAYOUT_UNDEFINED;\n\t\t\tvk_state.access_mask = VK_ACCESS_NONE_KHR;\n\t\t\tvk_state.stage       = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;\n\t\t\tbreak;\n\t}\n\treturn vk_state;\n}\n\nTexture::Texture(RHIDevice *device, const TextureDesc &desc) :\n    RHITexture(device, desc)\n{\n\tVkImageCreateInfo create_info = {};\n\tcreate_info.sType             = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;\n\tcreate_info.imageType         = VK_IMAGE_TYPE_2D;\n\tcreate_info.format            = ToVulkanFormat[desc.format];\n\tcreate_info.extent            = VkExtent3D{desc.width, desc.height, desc.depth};\n\tcreate_info.samples           = ToVulkanSampleCountFlag[desc.samples];\n\tcreate_info.mipLevels         = desc.mips;\n\tcreate_info.arrayLayers       = desc.layers;\n\tcreate_info.tiling            = VK_IMAGE_TILING_OPTIMAL;\n\tcreate_info.usage             = ToVulkanImageUsage(desc.usage);\n\tcreate_info.sharingMode       = VK_SHARING_MODE_EXCLUSIVE;\n\tcreate_info.initialLayout     = VK_IMAGE_LAYOUT_UNDEFINED;\n\n\t// Render Target Setting\n\tif (desc.usage & RHITextureUsage::RenderTarget)\n\t{\n\t\tcreate_info.usage |= IsDepthFormat(desc.format) ?\n\t\t                         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :\n                                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;\n\t}\n\n\t// Cubemap Setting\n\tif (desc.layers % 6 == 0 && desc.width == desc.height && desc.depth == 1)\n\t{\n\t\tcreate_info.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;\n\t}\n\n\t// External memory use vkallocate method\n#ifdef CUDA_ENABLE\n\tVkExternalMemoryImageCreateInfo external_create_info = {};\n\n\texternal_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;\n\texternal_create_info.pNext = nullptr;\n#\tifdef _WIN64\n\texternal_create_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#\telse\n\texternal_create_info.handleTypes        = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;\n#\tendif\n\tcreate_info.pNext = &external_create_info;\n\n\tvkCreateImage(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &m_handle);\n\n\tVkMemoryRequirements memory_req = {};\n\tvkGetImageMemoryRequirements(static_cast<Device *>(p_device)->GetDevice(), m_handle, &memory_req);\n\tm_memory_size = memory_req.size;\n\n#\tifdef _WIN64\n\tWindowsSecurityAttributes winSecurityAttributes;\n\n\tVkExportMemoryWin32HandleInfoKHR vulkanExportMemoryWin32HandleInfoKHR = {};\n\tvulkanExportMemoryWin32HandleInfoKHR.sType =\n\t    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;\n\tvulkanExportMemoryWin32HandleInfoKHR.pNext       = NULL;\n\tvulkanExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;\n\tvulkanExportMemoryWin32HandleInfoKHR.dwAccess =\n\t    DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;\n\tvulkanExportMemoryWin32HandleInfoKHR.name = (LPCWSTR) NULL;\n#\tendif\n\tVkExportMemoryAllocateInfoKHR export_memory_allocate_info = {};\n\texport_memory_allocate_info.sType =\n\t    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;\n#\tifdef _WIN64\n\texport_memory_allocate_info.pNext       = &vulkanExportMemoryWin32HandleInfoKHR;\n\texport_memory_allocate_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#\telse\n\texport_memory_allocate_info.pNext       = NULL;\n\texport_memory_allocate_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;\n#\tendif\n\n\tVkMemoryAllocateInfo allocate_Info = {};\n\tallocate_Info.sType                = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;\n\tallocate_Info.allocationSize       = memory_req.size;\n\tallocate_Info.pNext                = &export_memory_allocate_info;\n\n\tVkPhysicalDeviceMemoryProperties physical_device_properties = {};\n\tvkGetPhysicalDeviceMemoryProperties(static_cast<Device *>(p_device)->GetPhysicalDevice(), &physical_device_properties);\n\n\tfor (uint32_t i = 0; i < physical_device_properties.memoryTypeCount; i++)\n\t{\n\t\tif ((memory_req.memoryTypeBits & (1 << i)) &&\n\t\t    (physical_device_properties.memoryTypes[i].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==\n\t\t        (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))\n\t\t{\n\t\t\tallocate_Info.memoryTypeIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvkAllocateMemory(static_cast<Device *>(p_device)->GetDevice(), &allocate_Info, nullptr, &m_memory);\n\tvkBindImageMemory(static_cast<Device *>(p_device)->GetDevice(), m_handle, m_memory, 0);\n#else\n\tVmaAllocationCreateInfo allocation_create_info = {};\n\n\tallocation_create_info.usage = VMA_MEMORY_USAGE_GPU_ONLY;\n\n\tvmaCreateImage(static_cast<Device *>(p_device)->GetAllocator(), &create_info, &allocation_create_info, &m_handle, &m_allocation, nullptr);\n\n\tVkMemoryRequirements memory_req = {};\n\tvkGetImageMemoryRequirements(static_cast<Device *>(p_device)->GetDevice(), m_handle, &memory_req);\n\tm_memory_size = memory_req.size;\n#endif        // CUDA_ENABLE\n\n\tif (!m_desc.name.empty())\n\t{\n\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\tinfo.pObjectName                   = m_desc.name.c_str();\n\t\tinfo.objectHandle                  = (uint64_t) m_handle;\n\t\tinfo.objectType                    = VK_OBJECT_TYPE_IMAGE;\n\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t}\n}\n\nTexture::Texture(RHIDevice *device, const TextureDesc &desc, VkImage image, bool is_swapchain_buffer) :\n    RHITexture(device, desc), m_handle(image), m_is_swapchain_buffer(is_swapchain_buffer)\n{\n\tif (!m_desc.name.empty())\n\t{\n\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\tinfo.pObjectName                   = m_desc.name.c_str();\n\t\tinfo.objectHandle                  = (uint64_t) m_handle;\n\t\tinfo.objectType                    = VK_OBJECT_TYPE_IMAGE;\n\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t}\n}\n\nstd::unique_ptr<RHITexture> Texture::Alias(const TextureDesc &desc)\n{\n\tif (!m_allocation)\n\t{\n\t\treturn std::make_unique<Texture>(p_device, desc);\n\t}\n\n\tVkImageCreateInfo create_info = {};\n\tcreate_info.sType             = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;\n\tcreate_info.imageType         = VK_IMAGE_TYPE_2D;\n\tcreate_info.format            = ToVulkanFormat[desc.format];\n\tcreate_info.extent            = VkExtent3D{desc.width, desc.height, desc.depth};\n\tcreate_info.samples           = ToVulkanSampleCountFlag[desc.samples];\n\tcreate_info.mipLevels         = desc.mips;\n\tcreate_info.arrayLayers       = desc.layers;\n\tcreate_info.tiling            = VK_IMAGE_TILING_OPTIMAL;\n\tcreate_info.usage             = ToVulkanImageUsage(desc.usage);\n\tcreate_info.sharingMode       = VK_SHARING_MODE_EXCLUSIVE;\n\tcreate_info.initialLayout     = VK_IMAGE_LAYOUT_UNDEFINED;\n\tcreate_info.flags             = VK_IMAGE_CREATE_ALIAS_BIT;\n\n\t// Render Target Setting\n\tif (desc.usage & RHITextureUsage::RenderTarget)\n\t{\n\t\tcreate_info.usage |= IsDepthFormat(desc.format) ?\n\t\t                         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :\n                                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;\n\t}\n\n\t// Cubemap Setting\n\tif (desc.layers % 6 == 0 && desc.width == desc.height && desc.depth == 1)\n\t{\n\t\tcreate_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;\n\t}\n\n\tVkImage image = VK_NULL_HANDLE;\n\tvmaCreateAliasingImage(static_cast<Device *>(p_device)->GetAllocator(), m_allocation, &create_info, &image);\n\treturn std::make_unique<Texture>(p_device, desc, image, false);\n\n\t/*vkCreateImage(static_cast<Device *>(p_device)->GetDevice(), &create_info, nullptr, &image);\n\n\tVkMemoryRequirements memory_req = {};\n\tvkGetImageMemoryRequirements(static_cast<Device *>(p_device)->GetDevice(), image, &memory_req);\n\n\tVmaAllocationInfo info = {};\n\tvmaGetAllocationInfo(static_cast<Device *>(p_device)->GetAllocator(), m_allocation, &info);\n\n\tif (info.size >= memory_req.size)\n\t{\n\t\tvmaBindImageMemory(static_cast<Device *>(p_device)->GetAllocator(), m_allocation, image);\n\t\treturn std::make_unique<Texture>(p_device, desc, image, false);\n\t}\n\telse\n\t{\n\t\tvkDestroyImage(static_cast<Device *>(p_device)->GetDevice(), image, nullptr);\n\t\treturn std::make_unique<Texture>(p_device, desc);\n\t}*/\n}\n\nTexture::~Texture()\n{\n\tvkDeviceWaitIdle(static_cast<Device *>(p_device)->GetDevice());\n\n\tif (m_allocation)\n\t{\n\t\tvmaFreeMemory(static_cast<Device *>(p_device)->GetAllocator(), m_allocation);\n\t\tm_allocation = VK_NULL_HANDLE;\n\t}\n\n\tif (m_memory)\n\t{\n\t\tvkFreeMemory(static_cast<Device *>(p_device)->GetDevice(), m_memory, nullptr);\n\t\tm_memory = VK_NULL_HANDLE;\n\t}\n\n\tif (m_handle && !m_is_swapchain_buffer)\n\t{\n\t\tvkDestroyImage(static_cast<Device *>(p_device)->GetDevice(), m_handle, nullptr);\n\t\tm_handle = VK_NULL_HANDLE;\n\t}\n\n\tfor (auto &[hash, view] : m_view_cache)\n\t{\n\t\tvkDestroyImageView(static_cast<Device *>(p_device)->GetDevice(), view, nullptr);\n\t}\n\tm_view_cache.clear();\n}\n\nVkImage Texture::GetHandle() const\n{\n\treturn m_handle;\n}\n\nVkDeviceMemory Texture::GetMemory() const\n{\n\treturn m_memory;\n}\n\nsize_t Texture::GetMemorySize() const\n{\n\treturn m_memory_size;\n}\n\nVkImageView Texture::GetView(const TextureRange &range) const\n{\n\tsize_t hash = range.Hash();\n\tif (m_view_cache.find(hash) != m_view_cache.end())\n\t{\n\t\treturn m_view_cache.at(hash);\n\t}\n\n\tVkImageViewCreateInfo view_create_info           = {};\n\tview_create_info.sType                           = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;\n\tview_create_info.format                          = ToVulkanFormat[m_desc.format];\n\tview_create_info.image                           = m_handle;\n\tview_create_info.subresourceRange.aspectMask     = IsDepthFormat(m_desc.format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;\n\tview_create_info.subresourceRange.baseArrayLayer = range.base_layer;\n\tview_create_info.subresourceRange.baseMipLevel   = range.base_mip;\n\tview_create_info.subresourceRange.layerCount     = range.layer_count;\n\tview_create_info.subresourceRange.levelCount     = range.mip_count;\n\tview_create_info.viewType                        = ToVulkanImageViewType[range.dimension];\n\tview_create_info.components                      = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};\n\n\tm_view_cache[hash] = VK_NULL_HANDLE;\n\tvkCreateImageView(static_cast<Device *>(p_device)->GetDevice(), &view_create_info, nullptr, &m_view_cache[hash]);\n\n\tif (!m_desc.name.empty())\n\t{\n\t\tstd::string name = fmt::format(\"{} - View {}\", m_desc.name, std::to_string(hash));\n\n\t\tVkDebugUtilsObjectNameInfoEXT info = {};\n\t\tinfo.sType                         = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;\n\t\tinfo.pObjectName                   = name.c_str();\n\t\tinfo.objectHandle                  = (uint64_t) m_view_cache[hash];\n\t\tinfo.objectType                    = VK_OBJECT_TYPE_IMAGE_VIEW;\n\t\tstatic_cast<Device *>(p_device)->SetVulkanObjectName(info);\n\t}\n\n\treturn m_view_cache.at(hash);\n}\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Texture.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum::Vulkan\n{\nstruct TextureState\n{\n\tVkImageLayout        layout      = VK_IMAGE_LAYOUT_UNDEFINED;\n\tVkAccessFlags        access_mask = VK_ACCESS_NONE;\n\tVkPipelineStageFlags stage       = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;\n\n\tinline bool operator==(const TextureState &other)\n\t{\n\t\treturn layout == other.layout &&\n\t\t       access_mask == other.access_mask &&\n\t\t       stage == other.stage;\n\t}\n\n\tstatic TextureState Create(RHIResourceState state);\n};\n\nclass Texture : public RHITexture\n{\n  public:\n\tTexture(RHIDevice *device, const TextureDesc &desc);\n\n\tTexture(RHIDevice *device, const TextureDesc &desc, VkImage image, bool is_swapchain_buffer = true);\n\n\tvirtual std::unique_ptr<RHITexture> Alias(const TextureDesc &desc) override;\n\n\tvirtual ~Texture() override;\n\n\tVkImage GetHandle() const;\n\n\tVkDeviceMemory GetMemory() const;\n\n\tvirtual size_t GetMemorySize() const override;\n\n\tVkImageView GetView(const TextureRange &range) const;\n\n  private:\n\tVkImage        m_handle     = VK_NULL_HANDLE;\n\tVmaAllocation  m_allocation = VK_NULL_HANDLE;\n\tVkDeviceMemory m_memory     = VK_NULL_HANDLE;\n\n\tsize_t m_memory_size = 0;\n\n\tbool m_is_swapchain_buffer = false;\n\n\tmutable std::unordered_map<size_t, VkImageView> m_view_cache;\n};\n}        // namespace Ilum::Vulkan"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/Vulkan.cpp",
    "content": "#include \"Fwd.hpp\"\n\n#include \"AccelerationStructure.hpp\"\n#include \"Buffer.hpp\"\n#include \"Command.hpp\"\n#include \"Descriptor.hpp\"\n#include \"Device.hpp\"\n#include \"Frame.hpp\"\n#include \"PipelineState.hpp\"\n#include \"Profiler.hpp\"\n#include \"Queue.hpp\"\n#include \"RenderTarget.hpp\"\n#include \"Sampler.hpp\"\n#include \"Shader.hpp\"\n#include \"Swapchain.hpp\"\n#include \"Synchronization.hpp\"\n#include \"Texture.hpp\"\n\nusing namespace Ilum;\nusing namespace Ilum::Vulkan;\n\n#undef CreateSemaphore\n\nextern \"C\"\n{\n\tEXPORT_API RHIDevice *CreateDevice()\n\t{\n\t\treturn new Device;\n\t}\n\n\tEXPORT_API RHIFrame *CreateFrame(Device *device)\n\t{\n\t\treturn new Frame(device);\n\t}\n\n\tEXPORT_API RHISwapchain *CreateSwapchain(Device *device, void *window_handle, uint32_t width, uint32_t height, bool vsync)\n\t{\n\t\treturn new Swapchain(device, window_handle, width, height, vsync);\n\t}\n\n\tEXPORT_API RHIQueue *CreateQueue(Device *device)\n\t{\n\t\treturn new Queue(device);\n\t}\n\n\tEXPORT_API RHIBuffer *CreateBuffer(Device *device, const BufferDesc &desc)\n\t{\n\t\treturn new Buffer(device, desc);\n\t}\n\n\tEXPORT_API RHITexture *CreateTexture(Device *device, const TextureDesc &desc)\n\t{\n\t\treturn new Texture(device, desc);\n\t}\n\n\tEXPORT_API RHISampler *CreateSampler(Device *device, const SamplerDesc &desc)\n\t{\n\t\treturn new Sampler(device, desc);\n\t}\n\n\tEXPORT_API RHIShader *CreateShader(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source)\n\t{\n\t\treturn new Shader(device, entry_point, source);\n\t}\n\n\tEXPORT_API RHIRenderTarget *CreateRenderTarget(Device *device)\n\t{\n\t\treturn new RenderTarget(device);\n\t}\n\n\tEXPORT_API RHISemaphore *CreateSemaphore(Device *device)\n\t{\n\t\treturn new Semaphore(device);\n\t}\n\n\tEXPORT_API RHIFence *CreateFence(Device *device)\n\t{\n\t\treturn new Fence(device);\n\t}\n\n\tEXPORT_API RHIDescriptor *CreateDescriptor(Device *device, const ShaderMeta &meta)\n\t{\n\t\treturn new Descriptor(device, meta);\n\t}\n\n\tEXPORT_API RHIPipelineState *CreatePipelineState(Device *device)\n\t{\n\t\treturn new PipelineState(device);\n\t}\n\n\tEXPORT_API RHIProfiler *CreateProfiler(RHIDevice *device, uint32_t frame_count)\n\t{\n\t\treturn new Profiler(device, frame_count);\n\t}\n\n\tEXPORT_API RHIAccelerationStructure *CreateAccelerationStructure(Device *device)\n\t{\n\t\treturn new AccelerationStructure(device);\n\t}\n\n\tEXPORT_API HANDLE GetTextureMemHandle(Device *device, Texture *texture)\n\t{\n\t\tHANDLE handle = {};\n\n\t\tVkMemoryGetWin32HandleInfoKHR handle_info = {};\n\n\t\thandle_info.sType  = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;\n\t\thandle_info.pNext  = NULL;\n\t\thandle_info.memory = texture->GetMemory();\n\n#ifdef _WIN64\n\t\thandle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#else\n\t\thandle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;\n#endif        // _WIN64\n\n\t\tdevice->GetMemoryWin32Handle(&handle_info, &handle);\n\n\t\treturn handle;\n\t}\n\n\tEXPORT_API HANDLE GetBufferMemHandle(Device *device, Buffer *buffer)\n\t{\n\t\tHANDLE handle = {};\n\n\t\tVkMemoryGetWin32HandleInfoKHR handle_info = {};\n\n\t\thandle_info.sType  = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;\n\t\thandle_info.pNext  = NULL;\n\t\thandle_info.memory = buffer->GetMemory();\n\n#ifdef _WIN64\n\t\thandle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#else\n\t\thandle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;\n#endif        // _WIN64\n\n\t\tdevice->GetMemoryWin32Handle(&handle_info, &handle);\n\n\t\treturn handle;\n\t}\n\n\tEXPORT_API HANDLE GetSemaphoreHandle(Device *device, Semaphore *semaphore)\n\t{\n\t\tHANDLE handle = {};\n\n\t\tVkSemaphoreGetWin32HandleInfoKHR handle_info = {};\n\t\thandle_info.sType                            = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR;\n\t\thandle_info.pNext                            = NULL;\n\t\thandle_info.semaphore                        = semaphore->GetHandle();\n\n#ifdef _WIN64\n\t\thandle_info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;\n#else\n\t\thandle_info.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;\n#endif        // _WIN64\n\n\t\tdevice->GetSemaphoreWin32Handle(&handle_info, &handle);\n\n\t\treturn handle;\n\t}\n}"
  },
  {
    "path": "Source/Plugin/RHI/Vulkan/vk_mem_alloc.h",
    "content": "//\n// Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n\n#ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H\n#define AMD_VULKAN_MEMORY_ALLOCATOR_H\n\n/** \\mainpage Vulkan Memory Allocator\n\n<b>Version 3.1.0-development</b>\n\nCopyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved. \\n\nLicense: MIT\n\n<b>API documentation divided into groups:</b> [Modules](modules.html)\n\n\\section main_table_of_contents Table of contents\n\n- <b>User guide</b>\n  - \\subpage quick_start\n    - [Project setup](@ref quick_start_project_setup)\n    - [Initialization](@ref quick_start_initialization)\n    - [Resource allocation](@ref quick_start_resource_allocation)\n  - \\subpage choosing_memory_type\n    - [Usage](@ref choosing_memory_type_usage)\n    - [Required and preferred flags](@ref choosing_memory_type_required_preferred_flags)\n    - [Explicit memory types](@ref choosing_memory_type_explicit_memory_types)\n    - [Custom memory pools](@ref choosing_memory_type_custom_memory_pools)\n    - [Dedicated allocations](@ref choosing_memory_type_dedicated_allocations)\n  - \\subpage memory_mapping\n    - [Mapping functions](@ref memory_mapping_mapping_functions)\n    - [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory)\n    - [Cache flush and invalidate](@ref memory_mapping_cache_control)\n  - \\subpage staying_within_budget\n    - [Querying for budget](@ref staying_within_budget_querying_for_budget)\n    - [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage)\n  - \\subpage resource_aliasing\n  - \\subpage custom_memory_pools\n    - [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex)\n    - [Linear allocation algorithm](@ref linear_algorithm)\n      - [Free-at-once](@ref linear_algorithm_free_at_once)\n      - [Stack](@ref linear_algorithm_stack)\n      - [Double stack](@ref linear_algorithm_double_stack)\n      - [Ring buffer](@ref linear_algorithm_ring_buffer)\n  - \\subpage defragmentation\n  - \\subpage statistics\n    - [Numeric statistics](@ref statistics_numeric_statistics)\n    - [JSON dump](@ref statistics_json_dump)\n  - \\subpage allocation_annotation\n    - [Allocation user data](@ref allocation_user_data)\n    - [Allocation names](@ref allocation_names)\n  - \\subpage virtual_allocator\n  - \\subpage debugging_memory_usage\n    - [Memory initialization](@ref debugging_memory_usage_initialization)\n    - [Margins](@ref debugging_memory_usage_margins)\n    - [Corruption detection](@ref debugging_memory_usage_corruption_detection)\n  - \\subpage opengl_interop\n- \\subpage usage_patterns\n    - [GPU-only resource](@ref usage_patterns_gpu_only)\n    - [Staging copy for upload](@ref usage_patterns_staging_copy_upload)\n    - [Readback](@ref usage_patterns_readback)\n    - [Advanced data uploading](@ref usage_patterns_advanced_data_uploading)\n    - [Other use cases](@ref usage_patterns_other_use_cases)\n- \\subpage configuration\n  - [Pointers to Vulkan functions](@ref config_Vulkan_functions)\n  - [Custom host memory allocator](@ref custom_memory_allocator)\n  - [Device memory allocation callbacks](@ref allocation_callbacks)\n  - [Device heap memory limit](@ref heap_memory_limit)\n- <b>Extension support</b>\n    - \\subpage vk_khr_dedicated_allocation\n    - \\subpage enabling_buffer_device_address\n    - \\subpage vk_ext_memory_priority\n    - \\subpage vk_amd_device_coherent_memory\n- \\subpage general_considerations\n  - [Thread safety](@ref general_considerations_thread_safety)\n  - [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)\n  - [Validation layer warnings](@ref general_considerations_validation_layer_warnings)\n  - [Allocation algorithm](@ref general_considerations_allocation_algorithm)\n  - [Features not supported](@ref general_considerations_features_not_supported)\n\n\\section main_see_also See also\n\n- [**Product page on GPUOpen**](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)\n- [**Source repository on GitHub**](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)\n\n\\defgroup group_init Library initialization\n\n\\brief API elements related to the initialization and management of the entire library, especially #VmaAllocator object.\n\n\\defgroup group_alloc Memory allocation\n\n\\brief API elements related to the allocation, deallocation, and management of Vulkan memory, buffers, images.\nMost basic ones being: vmaCreateBuffer(), vmaCreateImage().\n\n\\defgroup group_virtual Virtual allocator\n\n\\brief API elements related to the mechanism of \\ref virtual_allocator - using the core allocation algorithm\nfor user-defined purpose without allocating any real GPU memory.\n\n\\defgroup group_stats Statistics\n\n\\brief API elements that query current status of the allocator, from memory usage, budget, to full dump of the internal state in JSON format.\nSee documentation chapter: \\ref statistics.\n*/\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef VULKAN_H_\n    #include <vulkan/vulkan.h>\n#endif\n\n#if !defined(VMA_VULKAN_VERSION)\n    #if defined(VK_VERSION_1_3)\n        #define VMA_VULKAN_VERSION 1003000\n    #elif defined(VK_VERSION_1_2)\n        #define VMA_VULKAN_VERSION 1002000\n    #elif defined(VK_VERSION_1_1)\n        #define VMA_VULKAN_VERSION 1001000\n    #else\n        #define VMA_VULKAN_VERSION 1000000\n    #endif\n#endif\n\n#if defined(__ANDROID__) && defined(VK_NO_PROTOTYPES) && VMA_STATIC_VULKAN_FUNCTIONS\n    extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;\n    extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;\n    extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;\n    extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;\n    extern PFN_vkAllocateMemory vkAllocateMemory;\n    extern PFN_vkFreeMemory vkFreeMemory;\n    extern PFN_vkMapMemory vkMapMemory;\n    extern PFN_vkUnmapMemory vkUnmapMemory;\n    extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;\n    extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;\n    extern PFN_vkBindBufferMemory vkBindBufferMemory;\n    extern PFN_vkBindImageMemory vkBindImageMemory;\n    extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;\n    extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;\n    extern PFN_vkCreateBuffer vkCreateBuffer;\n    extern PFN_vkDestroyBuffer vkDestroyBuffer;\n    extern PFN_vkCreateImage vkCreateImage;\n    extern PFN_vkDestroyImage vkDestroyImage;\n    extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer;\n    #if VMA_VULKAN_VERSION >= 1001000\n        extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2;\n        extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2;\n        extern PFN_vkBindBufferMemory2 vkBindBufferMemory2;\n        extern PFN_vkBindImageMemory2 vkBindImageMemory2;\n        extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2;\n    #endif // #if VMA_VULKAN_VERSION >= 1001000\n#endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES\n\n#if !defined(VMA_DEDICATED_ALLOCATION)\n    #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation\n        #define VMA_DEDICATED_ALLOCATION 1\n    #else\n        #define VMA_DEDICATED_ALLOCATION 0\n    #endif\n#endif\n\n#if !defined(VMA_BIND_MEMORY2)\n    #if VK_KHR_bind_memory2\n        #define VMA_BIND_MEMORY2 1\n    #else\n        #define VMA_BIND_MEMORY2 0\n    #endif\n#endif\n\n#if !defined(VMA_MEMORY_BUDGET)\n    #if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000)\n        #define VMA_MEMORY_BUDGET 1\n    #else\n        #define VMA_MEMORY_BUDGET 0\n    #endif\n#endif\n\n// Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers.\n#if !defined(VMA_BUFFER_DEVICE_ADDRESS)\n    #if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION >= 1002000\n        #define VMA_BUFFER_DEVICE_ADDRESS 1\n    #else\n        #define VMA_BUFFER_DEVICE_ADDRESS 0\n    #endif\n#endif\n\n// Defined to 1 when VK_EXT_memory_priority device extension is defined in Vulkan headers.\n#if !defined(VMA_MEMORY_PRIORITY)\n    #if VK_EXT_memory_priority\n        #define VMA_MEMORY_PRIORITY 1\n    #else\n        #define VMA_MEMORY_PRIORITY 0\n    #endif\n#endif\n\n// Defined to 1 when VK_KHR_external_memory device extension is defined in Vulkan headers.\n#if !defined(VMA_EXTERNAL_MEMORY)\n    #if VK_KHR_external_memory\n        #define VMA_EXTERNAL_MEMORY 1\n    #else\n        #define VMA_EXTERNAL_MEMORY 0\n    #endif\n#endif\n\n// Define these macros to decorate all public functions with additional code,\n// before and after returned type, appropriately. This may be useful for\n// exporting the functions when compiling VMA as a separate library. Example:\n// #define VMA_CALL_PRE  __declspec(dllexport)\n// #define VMA_CALL_POST __cdecl\n#ifndef VMA_CALL_PRE\n    #define VMA_CALL_PRE\n#endif\n#ifndef VMA_CALL_POST\n    #define VMA_CALL_POST\n#endif\n\n// Define this macro to decorate pointers with an attribute specifying the\n// length of the array they point to if they are not null.\n//\n// The length may be one of\n// - The name of another parameter in the argument list where the pointer is declared\n// - The name of another member in the struct where the pointer is declared\n// - The name of a member of a struct type, meaning the value of that member in\n//   the context of the call. For example\n//   VMA_LEN_IF_NOT_NULL(\"VkPhysicalDeviceMemoryProperties::memoryHeapCount\"),\n//   this means the number of memory heaps available in the device associated\n//   with the VmaAllocator being dealt with.\n#ifndef VMA_LEN_IF_NOT_NULL\n    #define VMA_LEN_IF_NOT_NULL(len)\n#endif\n\n// The VMA_NULLABLE macro is defined to be _Nullable when compiling with Clang.\n// see: https://clang.llvm.org/docs/AttributeReference.html#nullable\n#ifndef VMA_NULLABLE\n    #ifdef __clang__\n        #define VMA_NULLABLE _Nullable\n    #else\n        #define VMA_NULLABLE\n    #endif\n#endif\n\n// The VMA_NOT_NULL macro is defined to be _Nonnull when compiling with Clang.\n// see: https://clang.llvm.org/docs/AttributeReference.html#nonnull\n#ifndef VMA_NOT_NULL\n    #ifdef __clang__\n        #define VMA_NOT_NULL _Nonnull\n    #else\n        #define VMA_NOT_NULL\n    #endif\n#endif\n\n// If non-dispatchable handles are represented as pointers then we can give\n// then nullability annotations\n#ifndef VMA_NOT_NULL_NON_DISPATCHABLE\n    #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)\n        #define VMA_NOT_NULL_NON_DISPATCHABLE VMA_NOT_NULL\n    #else\n        #define VMA_NOT_NULL_NON_DISPATCHABLE\n    #endif\n#endif\n\n#ifndef VMA_NULLABLE_NON_DISPATCHABLE\n    #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)\n        #define VMA_NULLABLE_NON_DISPATCHABLE VMA_NULLABLE\n    #else\n        #define VMA_NULLABLE_NON_DISPATCHABLE\n    #endif\n#endif\n\n#ifndef VMA_STATS_STRING_ENABLED\n    #define VMA_STATS_STRING_ENABLED 1\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n//\n//    INTERFACE\n//\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n// Sections for managing code placement in file, only for development purposes e.g. for convenient folding inside an IDE.\n#ifndef _VMA_ENUM_DECLARATIONS\n\n/**\n\\addtogroup group_init\n@{\n*/\n\n/// Flags for created #VmaAllocator.\ntypedef enum VmaAllocatorCreateFlagBits\n{\n    /** \\brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you.\n\n    Using this flag may increase performance because internal mutexes are not used.\n    */\n    VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001,\n    /** \\brief Enables usage of VK_KHR_dedicated_allocation extension.\n\n    The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.\n    When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.\n\n    Using this extension will automatically allocate dedicated blocks of memory for\n    some buffers and images instead of suballocating place for them out of bigger\n    memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT\n    flag) when it is recommended by the driver. It may improve performance on some\n    GPUs.\n\n    You may set this flag only if you found out that following device extensions are\n    supported, you enabled them while creating Vulkan device passed as\n    VmaAllocatorCreateInfo::device, and you want them to be used internally by this\n    library:\n\n    - VK_KHR_get_memory_requirements2 (device extension)\n    - VK_KHR_dedicated_allocation (device extension)\n\n    When this flag is set, you can experience following warnings reported by Vulkan\n    validation layer. You can ignore them.\n\n    > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.\n    */\n    VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002,\n    /**\n    Enables usage of VK_KHR_bind_memory2 extension.\n\n    The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.\n    When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.\n\n    You may set this flag only if you found out that this device extension is supported,\n    you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,\n    and you want it to be used internally by this library.\n\n    The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,\n    which allow to pass a chain of `pNext` structures while binding.\n    This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2().\n    */\n    VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004,\n    /**\n    Enables usage of VK_EXT_memory_budget extension.\n\n    You may set this flag only if you found out that this device extension is supported,\n    you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,\n    and you want it to be used internally by this library, along with another instance extension\n    VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted).\n\n    The extension provides query for current memory usage and budget, which will probably\n    be more accurate than an estimation used by the library otherwise.\n    */\n    VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008,\n    /**\n    Enables usage of VK_AMD_device_coherent_memory extension.\n\n    You may set this flag only if you:\n\n    - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,\n    - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device,\n    - want it to be used internally by this library.\n\n    The extension and accompanying device feature provide access to memory types with\n    `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags.\n    They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR.\n\n    When the extension is not enabled, such memory types are still enumerated, but their usage is illegal.\n    To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type,\n    returning `VK_ERROR_FEATURE_NOT_PRESENT`.\n    */\n    VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 0x00000010,\n    /**\n    Enables usage of \"buffer device address\" feature, which allows you to use function\n    `vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader.\n\n    You may set this flag only if you:\n\n    1. (For Vulkan version < 1.2) Found as available and enabled device extension\n    VK_KHR_buffer_device_address.\n    This extension is promoted to core Vulkan 1.2.\n    2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`.\n\n    When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA.\n    The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to\n    allocated memory blocks wherever it might be needed.\n\n    For more information, see documentation chapter \\ref enabling_buffer_device_address.\n    */\n    VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 0x00000020,\n    /**\n    Enables usage of VK_EXT_memory_priority extension in the library.\n\n    You may set this flag only if you found available and enabled this device extension,\n    along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`,\n    while creating Vulkan device passed as VmaAllocatorCreateInfo::device.\n\n    When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority\n    are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored.\n\n    A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.\n    Larger values are higher priority. The granularity of the priorities is implementation-dependent.\n    It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`.\n    The value to be used for default priority is 0.5.\n    For more details, see the documentation of the VK_EXT_memory_priority extension.\n    */\n    VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT = 0x00000040,\n\n    VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF\n} VmaAllocatorCreateFlagBits;\n/// See #VmaAllocatorCreateFlagBits.\ntypedef VkFlags VmaAllocatorCreateFlags;\n\n/** @} */\n\n/**\n\\addtogroup group_alloc\n@{\n*/\n\n/// \\brief Intended usage of the allocated memory.\ntypedef enum VmaMemoryUsage\n{\n    /** No intended memory usage specified.\n    Use other members of VmaAllocationCreateInfo to specify your requirements.\n    */\n    VMA_MEMORY_USAGE_UNKNOWN = 0,\n    /**\n    \\deprecated Obsolete, preserved for backward compatibility.\n    Prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.\n    */\n    VMA_MEMORY_USAGE_GPU_ONLY = 1,\n    /**\n    \\deprecated Obsolete, preserved for backward compatibility.\n    Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`.\n    */\n    VMA_MEMORY_USAGE_CPU_ONLY = 2,\n    /**\n    \\deprecated Obsolete, preserved for backward compatibility.\n    Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.\n    */\n    VMA_MEMORY_USAGE_CPU_TO_GPU = 3,\n    /**\n    \\deprecated Obsolete, preserved for backward compatibility.\n    Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`.\n    */\n    VMA_MEMORY_USAGE_GPU_TO_CPU = 4,\n    /**\n    \\deprecated Obsolete, preserved for backward compatibility.\n    Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.\n    */\n    VMA_MEMORY_USAGE_CPU_COPY = 5,\n    /**\n    Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`.\n    Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.\n\n    Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`.\n\n    Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\n    */\n    VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6,\n    /**\n    Selects best memory type automatically.\n    This flag is recommended for most common use cases.\n\n    When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),\n    you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT\n    in VmaAllocationCreateInfo::flags.\n\n    It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.\n    vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()\n    and not with generic memory allocation functions.\n    */\n    VMA_MEMORY_USAGE_AUTO = 7,\n    /**\n    Selects best memory type automatically with preference for GPU (device) memory.\n\n    When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),\n    you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT\n    in VmaAllocationCreateInfo::flags.\n\n    It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.\n    vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()\n    and not with generic memory allocation functions.\n    */\n    VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE = 8,\n    /**\n    Selects best memory type automatically with preference for CPU (host) memory.\n\n    When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),\n    you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT\n    in VmaAllocationCreateInfo::flags.\n\n    It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.\n    vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()\n    and not with generic memory allocation functions.\n    */\n    VMA_MEMORY_USAGE_AUTO_PREFER_HOST = 9,\n\n    VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF\n} VmaMemoryUsage;\n\n/// Flags to be passed as VmaAllocationCreateInfo::flags.\ntypedef enum VmaAllocationCreateFlagBits\n{\n    /** \\brief Set this flag if the allocation should have its own memory block.\n\n    Use it for special, big resources, like fullscreen images used as attachments.\n    */\n    VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001,\n\n    /** \\brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block.\n\n    If new allocation cannot be placed in any of the existing blocks, allocation\n    fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error.\n\n    You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and\n    #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense.\n    */\n    VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002,\n    /** \\brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.\n\n    Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.\n\n    It is valid to use this flag for allocation made from memory type that is not\n    `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is\n    useful if you need an allocation that is efficient to use on GPU\n    (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that\n    support it (e.g. Intel GPU).\n    */\n    VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,\n    /** \\deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead.\n\n    Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a\n    null-terminated string. Instead of copying pointer value, a local copy of the\n    string is made and stored in allocation's `pName`. The string is automatically\n    freed together with the allocation. It is also used in vmaBuildStatsString().\n    */\n    VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,\n    /** Allocation will be created from upper stack in a double stack pool.\n\n    This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag.\n    */\n    VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,\n    /** Create both buffer/image and allocation, but don't bind them together.\n    It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.\n    The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage().\n    Otherwise it is ignored.\n\n    If you want to make sure the new buffer/image is not tied to the new memory allocation\n    through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block,\n    use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT.\n    */\n    VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080,\n    /** Create allocation only if additional device memory required for it, if any, won't exceed\n    memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.\n    */\n    VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,\n    /** \\brief Set this flag if the allocated memory will have aliasing resources.\n\n    Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.\n    Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.\n    */\n    VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200,\n    /**\n    Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).\n\n    - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,\n      you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.\n    - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.\n      This includes allocations created in \\ref custom_memory_pools.\n\n    Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number,\n    never read or accessed randomly, so a memory type can be selected that is uncached and write-combined.\n\n    \\warning Violating this declaration may work correctly, but will likely be very slow.\n    Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;`\n    Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once.\n    */\n    VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400,\n    /**\n    Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).\n\n    - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,\n      you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.\n    - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.\n      This includes allocations created in \\ref custom_memory_pools.\n\n    Declares that mapped memory can be read, written, and accessed in random order,\n    so a `HOST_CACHED` memory type is required.\n    */\n    VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = 0x00000800,\n    /**\n    Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,\n    it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected\n    if it may improve performance.\n\n    By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type\n    (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some \"staging\" buffer and\n    issue an explicit transfer to write/read your data.\n    To prepare for this possibility, don't forget to add appropriate flags like\n    `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image.\n    */\n    VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT = 0x00001000,\n    /** Allocation strategy that chooses smallest possible free range for the allocation\n    to minimize memory usage and fragmentation, possibly at the expense of allocation time.\n    */\n    VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 0x00010000,\n    /** Allocation strategy that chooses first suitable free range for the allocation -\n    not necessarily in terms of the smallest offset but the one that is easiest and fastest to find\n    to minimize allocation time, possibly at the expense of allocation quality.\n    */\n    VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 0x00020000,\n    /** Allocation strategy that chooses always the lowest offset in available space.\n    This is not the most efficient strategy but achieves highly packed data.\n    Used internally by defragmentation, not recommended in typical usage.\n    */\n    VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT  = 0x00040000,\n    /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT.\n    */\n    VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,\n    /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT.\n    */\n    VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,\n    /** A bit mask to extract only `STRATEGY` bits from entire set of flags.\n    */\n    VMA_ALLOCATION_CREATE_STRATEGY_MASK =\n        VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT |\n        VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT |\n        VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,\n\n    VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF\n} VmaAllocationCreateFlagBits;\n/// See #VmaAllocationCreateFlagBits.\ntypedef VkFlags VmaAllocationCreateFlags;\n\n/// Flags to be passed as VmaPoolCreateInfo::flags.\ntypedef enum VmaPoolCreateFlagBits\n{\n    /** \\brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.\n\n    This is an optional optimization flag.\n\n    If you always allocate using vmaCreateBuffer(), vmaCreateImage(),\n    vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator\n    knows exact type of your allocations so it can handle Buffer-Image Granularity\n    in the optimal way.\n\n    If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),\n    exact type of such allocations is not known, so allocator must be conservative\n    in handling Buffer-Image Granularity, which can lead to suboptimal allocation\n    (wasted memory). In that case, if you can make sure you always allocate only\n    buffers and linear images or only optimal images out of this pool, use this flag\n    to make allocator disregard Buffer-Image Granularity and so make allocations\n    faster and more optimal.\n    */\n    VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,\n\n    /** \\brief Enables alternative, linear allocation algorithm in this pool.\n\n    Specify this flag to enable linear allocation algorithm, which always creates\n    new allocations after last one and doesn't reuse space from allocations freed in\n    between. It trades memory consumption for simplified algorithm and data\n    structure, which has better performance and uses less memory for metadata.\n\n    By using this flag, you can achieve behavior of free-at-once, stack,\n    ring buffer, and double stack.\n    For details, see documentation chapter \\ref linear_algorithm.\n    */\n    VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,\n\n    /** Bit mask to extract only `ALGORITHM` bits from entire set of flags.\n    */\n    VMA_POOL_CREATE_ALGORITHM_MASK =\n        VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT,\n\n    VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF\n} VmaPoolCreateFlagBits;\n/// Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits.\ntypedef VkFlags VmaPoolCreateFlags;\n\n/// Flags to be passed as VmaDefragmentationInfo::flags.\ntypedef enum VmaDefragmentationFlagBits\n{\n    /* \\brief Use simple but fast algorithm for defragmentation.\n    May not achieve best results but will require least time to compute and least allocations to copy.\n    */\n    VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT = 0x1,\n    /* \\brief Default defragmentation algorithm, applied also when no `ALGORITHM` flag is specified.\n    Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved.\n    */\n    VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT = 0x2,\n    /* \\brief Perform full defragmentation of memory.\n    Can result in notably more time to compute and allocations to copy, but will achieve best memory packing.\n    */\n    VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT = 0x4,\n    /** \\brief Use the most roboust algorithm at the cost of time to compute and number of copies to make.\n    Only available when bufferImageGranularity is greater than 1, since it aims to reduce\n    alignment issues between different types of resources.\n    Otherwise falls back to same behavior as #VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT.\n    */\n    VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8,\n\n    /// A bit mask to extract only `ALGORITHM` bits from entire set of flags.\n    VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK =\n        VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT |\n        VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT |\n        VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT |\n        VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT,\n\n    VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF\n} VmaDefragmentationFlagBits;\n/// See #VmaDefragmentationFlagBits.\ntypedef VkFlags VmaDefragmentationFlags;\n\n/// Operation performed on single defragmentation move. See structure #VmaDefragmentationMove.\ntypedef enum VmaDefragmentationMoveOperation\n{\n    /// Buffer/image has been recreated at `dstTmpAllocation`, data has been copied, old buffer/image has been destroyed. `srcAllocation` should be changed to point to the new place. This is the default value set by vmaBeginDefragmentationPass().\n    VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY = 0,\n    /// Set this value if you cannot move the allocation. New place reserved at `dstTmpAllocation` will be freed. `srcAllocation` will remain unchanged.\n    VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1,\n    /// Set this value if you decide to abandon the allocation and you destroyed the buffer/image. New place reserved at `dstTmpAllocation` will be freed, along with `srcAllocation`, which will be destroyed.\n    VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2,\n} VmaDefragmentationMoveOperation;\n\n/** @} */\n\n/**\n\\addtogroup group_virtual\n@{\n*/\n\n/// Flags to be passed as VmaVirtualBlockCreateInfo::flags.\ntypedef enum VmaVirtualBlockCreateFlagBits\n{\n    /** \\brief Enables alternative, linear allocation algorithm in this virtual block.\n\n    Specify this flag to enable linear allocation algorithm, which always creates\n    new allocations after last one and doesn't reuse space from allocations freed in\n    between. It trades memory consumption for simplified algorithm and data\n    structure, which has better performance and uses less memory for metadata.\n\n    By using this flag, you can achieve behavior of free-at-once, stack,\n    ring buffer, and double stack.\n    For details, see documentation chapter \\ref linear_algorithm.\n    */\n    VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 0x00000001,\n\n    /** \\brief Bit mask to extract only `ALGORITHM` bits from entire set of flags.\n    */\n    VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK =\n        VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT,\n\n    VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF\n} VmaVirtualBlockCreateFlagBits;\n/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits.\ntypedef VkFlags VmaVirtualBlockCreateFlags;\n\n/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags.\ntypedef enum VmaVirtualAllocationCreateFlagBits\n{\n    /** \\brief Allocation will be created from upper stack in a double stack pool.\n\n    This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag.\n    */\n    VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,\n    /** \\brief Allocation strategy that tries to minimize memory usage.\n    */\n    VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,\n    /** \\brief Allocation strategy that tries to minimize allocation time.\n    */\n    VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,\n    /** Allocation strategy that chooses always the lowest offset in available space.\n    This is not the most efficient strategy but achieves highly packed data.\n    */\n    VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,\n    /** \\brief A bit mask to extract only `STRATEGY` bits from entire set of flags.\n\n    These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits.\n    */\n    VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK,\n\n    VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF\n} VmaVirtualAllocationCreateFlagBits;\n/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits.\ntypedef VkFlags VmaVirtualAllocationCreateFlags;\n\n/** @} */\n\n#endif // _VMA_ENUM_DECLARATIONS\n\n#ifndef _VMA_DATA_TYPES_DECLARATIONS\n\n/**\n\\addtogroup group_init\n@{ */\n\n/** \\struct VmaAllocator\n\\brief Represents main object of this library initialized.\n\nFill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it.\nCall function vmaDestroyAllocator() to destroy it.\n\nIt is recommended to create just one object of this type per `VkDevice` object,\nright after Vulkan is initialized and keep it alive until before Vulkan device is destroyed.\n*/\nVK_DEFINE_HANDLE(VmaAllocator)\n\n/** @} */\n\n/**\n\\addtogroup group_alloc\n@{\n*/\n\n/** \\struct VmaPool\n\\brief Represents custom memory pool\n\nFill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it.\nCall function vmaDestroyPool() to destroy it.\n\nFor more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools).\n*/\nVK_DEFINE_HANDLE(VmaPool)\n\n/** \\struct VmaAllocation\n\\brief Represents single memory allocation.\n\nIt may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type\nplus unique offset.\n\nThere are multiple ways to create such object.\nYou need to fill structure VmaAllocationCreateInfo.\nFor more information see [Choosing memory type](@ref choosing_memory_type).\n\nAlthough the library provides convenience functions that create Vulkan buffer or image,\nallocate memory for it and bind them together,\nbinding of the allocation to a buffer or an image is out of scope of the allocation itself.\nAllocation object can exist without buffer/image bound,\nbinding can be done manually by the user, and destruction of it can be done\nindependently of destruction of the allocation.\n\nThe object also remembers its size and some other information.\nTo retrieve this information, use function vmaGetAllocationInfo() and inspect\nreturned structure VmaAllocationInfo.\n*/\nVK_DEFINE_HANDLE(VmaAllocation)\n\n/** \\struct VmaDefragmentationContext\n\\brief An opaque object that represents started defragmentation process.\n\nFill structure #VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it.\nCall function vmaEndDefragmentation() to destroy it.\n*/\nVK_DEFINE_HANDLE(VmaDefragmentationContext)\n\n/** @} */\n\n/**\n\\addtogroup group_virtual\n@{\n*/\n\n/** \\struct VmaVirtualAllocation\n\\brief Represents single memory allocation done inside VmaVirtualBlock.\n\nUse it as a unique identifier to virtual allocation within the single block.\n\nUse value `VK_NULL_HANDLE` to represent a null/invalid allocation.\n*/\nVK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaVirtualAllocation)\n\n/** @} */\n\n/**\n\\addtogroup group_virtual\n@{\n*/\n\n/** \\struct VmaVirtualBlock\n\\brief Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory.\n\nFill in #VmaVirtualBlockCreateInfo structure and use vmaCreateVirtualBlock() to create it. Use vmaDestroyVirtualBlock() to destroy it.\nFor more information, see documentation chapter \\ref virtual_allocator.\n\nThis object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally.\n*/\nVK_DEFINE_HANDLE(VmaVirtualBlock)\n\n/** @} */\n\n/**\n\\addtogroup group_init\n@{\n*/\n\n/// Callback function called after successful vkAllocateMemory.\ntypedef void (VKAPI_PTR* PFN_vmaAllocateDeviceMemoryFunction)(\n    VmaAllocator VMA_NOT_NULL                    allocator,\n    uint32_t                                     memoryType,\n    VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory,\n    VkDeviceSize                                 size,\n    void* VMA_NULLABLE                           pUserData);\n\n/// Callback function called before vkFreeMemory.\ntypedef void (VKAPI_PTR* PFN_vmaFreeDeviceMemoryFunction)(\n    VmaAllocator VMA_NOT_NULL                    allocator,\n    uint32_t                                     memoryType,\n    VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory,\n    VkDeviceSize                                 size,\n    void* VMA_NULLABLE                           pUserData);\n\n/** \\brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`.\n\nProvided for informative purpose, e.g. to gather statistics about number of\nallocations or total amount of memory allocated in Vulkan.\n\nUsed in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.\n*/\ntypedef struct VmaDeviceMemoryCallbacks\n{\n    /// Optional, can be null.\n    PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate;\n    /// Optional, can be null.\n    PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree;\n    /// Optional, can be null.\n    void* VMA_NULLABLE pUserData;\n} VmaDeviceMemoryCallbacks;\n\n/** \\brief Pointers to some Vulkan functions - a subset used by the library.\n\nUsed in VmaAllocatorCreateInfo::pVulkanFunctions.\n*/\ntypedef struct VmaVulkanFunctions\n{\n    /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS.\n    PFN_vkGetInstanceProcAddr VMA_NULLABLE vkGetInstanceProcAddr;\n    /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS.\n    PFN_vkGetDeviceProcAddr VMA_NULLABLE vkGetDeviceProcAddr;\n    PFN_vkGetPhysicalDeviceProperties VMA_NULLABLE vkGetPhysicalDeviceProperties;\n    PFN_vkGetPhysicalDeviceMemoryProperties VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties;\n    PFN_vkAllocateMemory VMA_NULLABLE vkAllocateMemory;\n    PFN_vkFreeMemory VMA_NULLABLE vkFreeMemory;\n    PFN_vkMapMemory VMA_NULLABLE vkMapMemory;\n    PFN_vkUnmapMemory VMA_NULLABLE vkUnmapMemory;\n    PFN_vkFlushMappedMemoryRanges VMA_NULLABLE vkFlushMappedMemoryRanges;\n    PFN_vkInvalidateMappedMemoryRanges VMA_NULLABLE vkInvalidateMappedMemoryRanges;\n    PFN_vkBindBufferMemory VMA_NULLABLE vkBindBufferMemory;\n    PFN_vkBindImageMemory VMA_NULLABLE vkBindImageMemory;\n    PFN_vkGetBufferMemoryRequirements VMA_NULLABLE vkGetBufferMemoryRequirements;\n    PFN_vkGetImageMemoryRequirements VMA_NULLABLE vkGetImageMemoryRequirements;\n    PFN_vkCreateBuffer VMA_NULLABLE vkCreateBuffer;\n    PFN_vkDestroyBuffer VMA_NULLABLE vkDestroyBuffer;\n    PFN_vkCreateImage VMA_NULLABLE vkCreateImage;\n    PFN_vkDestroyImage VMA_NULLABLE vkDestroyImage;\n    PFN_vkCmdCopyBuffer VMA_NULLABLE vkCmdCopyBuffer;\n#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    /// Fetch \"vkGetBufferMemoryRequirements2\" on Vulkan >= 1.1, fetch \"vkGetBufferMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension.\n    PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR;\n    /// Fetch \"vkGetImageMemoryRequirements2\" on Vulkan >= 1.1, fetch \"vkGetImageMemoryRequirements2KHR\" when using VK_KHR_dedicated_allocation extension.\n    PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR;\n#endif\n#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000\n    /// Fetch \"vkBindBufferMemory2\" on Vulkan >= 1.1, fetch \"vkBindBufferMemory2KHR\" when using VK_KHR_bind_memory2 extension.\n    PFN_vkBindBufferMemory2KHR VMA_NULLABLE vkBindBufferMemory2KHR;\n    /// Fetch \"vkBindImageMemory2\" on Vulkan >= 1.1, fetch \"vkBindImageMemory2KHR\" when using VK_KHR_bind_memory2 extension.\n    PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR;\n#endif\n#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000\n    PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR;\n#endif\n#if VMA_VULKAN_VERSION >= 1003000\n    /// Fetch from \"vkGetDeviceBufferMemoryRequirements\" on Vulkan >= 1.3, but you can also fetch it from \"vkGetDeviceBufferMemoryRequirementsKHR\" if you enabled extension VK_KHR_maintenance4.\n    PFN_vkGetDeviceBufferMemoryRequirements VMA_NULLABLE vkGetDeviceBufferMemoryRequirements;\n    /// Fetch from \"vkGetDeviceImageMemoryRequirements\" on Vulkan >= 1.3, but you can also fetch it from \"vkGetDeviceImageMemoryRequirementsKHR\" if you enabled extension VK_KHR_maintenance4.\n    PFN_vkGetDeviceImageMemoryRequirements VMA_NULLABLE vkGetDeviceImageMemoryRequirements;\n#endif\n} VmaVulkanFunctions;\n\n/// Description of a Allocator to be created.\ntypedef struct VmaAllocatorCreateInfo\n{\n    /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum.\n    VmaAllocatorCreateFlags flags;\n    /// Vulkan physical device.\n    /** It must be valid throughout whole lifetime of created allocator. */\n    VkPhysicalDevice VMA_NOT_NULL physicalDevice;\n    /// Vulkan device.\n    /** It must be valid throughout whole lifetime of created allocator. */\n    VkDevice VMA_NOT_NULL device;\n    /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional.\n    /** Set to 0 to use default, which is currently 256 MiB. */\n    VkDeviceSize preferredLargeHeapBlockSize;\n    /// Custom CPU memory allocation callbacks. Optional.\n    /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */\n    const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks;\n    /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional.\n    /** Optional, can be null. */\n    const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks;\n    /** \\brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.\n\n    If not NULL, it must be a pointer to an array of\n    `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on\n    maximum number of bytes that can be allocated out of particular Vulkan memory\n    heap.\n\n    Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that\n    heap. This is also the default in case of `pHeapSizeLimit` = NULL.\n\n    If there is a limit defined for a heap:\n\n    - If user tries to allocate more memory from that heap using this allocator,\n      the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.\n    - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the\n      value of this limit will be reported instead when using vmaGetMemoryProperties().\n\n    Warning! Using this feature may not be equivalent to installing a GPU with\n    smaller amount of memory, because graphics driver doesn't necessary fail new\n    allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is\n    exceeded. It may return success and just silently migrate some device memory\n    blocks to system RAM. This driver behavior can also be controlled using\n    VK_AMD_memory_overallocation_behavior extension.\n    */\n    const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(\"VkPhysicalDeviceMemoryProperties::memoryHeapCount\") pHeapSizeLimit;\n\n    /** \\brief Pointers to Vulkan functions. Can be null.\n\n    For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions).\n    */\n    const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions;\n    /** \\brief Handle to Vulkan instance object.\n\n    Starting from version 3.0.0 this member is no longer optional, it must be set!\n    */\n    VkInstance VMA_NOT_NULL instance;\n    /** \\brief Optional. The highest version of Vulkan that the application is designed to use.\n\n    It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.\n    The patch version number specified is ignored. Only the major and minor versions are considered.\n    It must be less or equal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`.\n    Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation.\n    Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.\n    */\n    uint32_t vulkanApiVersion;\n#if VMA_EXTERNAL_MEMORY\n    /** \\brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type.\n\n    If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount`\n    elements, defining external memory handle types of particular Vulkan memory type,\n    to be passed using `VkExportMemoryAllocateInfoKHR`.\n\n    Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type.\n    This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL.\n    */\n    const VkExternalMemoryHandleTypeFlagsKHR* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(\"VkPhysicalDeviceMemoryProperties::memoryTypeCount\") pTypeExternalMemoryHandleTypes;\n#endif // #if VMA_EXTERNAL_MEMORY\n} VmaAllocatorCreateInfo;\n\n/// Information about existing #VmaAllocator object.\ntypedef struct VmaAllocatorInfo\n{\n    /** \\brief Handle to Vulkan instance object.\n\n    This is the same value as has been passed through VmaAllocatorCreateInfo::instance.\n    */\n    VkInstance VMA_NOT_NULL instance;\n    /** \\brief Handle to Vulkan physical device object.\n\n    This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice.\n    */\n    VkPhysicalDevice VMA_NOT_NULL physicalDevice;\n    /** \\brief Handle to Vulkan device object.\n\n    This is the same value as has been passed through VmaAllocatorCreateInfo::device.\n    */\n    VkDevice VMA_NOT_NULL device;\n} VmaAllocatorInfo;\n\n/** @} */\n\n/**\n\\addtogroup group_stats\n@{\n*/\n\n/** \\brief Calculated statistics of memory usage e.g. in a specific memory type, heap, custom pool, or total.\n\nThese are fast to calculate.\nSee functions: vmaGetHeapBudgets(), vmaGetPoolStatistics().\n*/\ntypedef struct VmaStatistics\n{\n    /** \\brief Number of `VkDeviceMemory` objects - Vulkan memory blocks allocated.\n    */\n    uint32_t blockCount;\n    /** \\brief Number of #VmaAllocation objects allocated.\n\n    Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`.\n    */\n    uint32_t allocationCount;\n    /** \\brief Number of bytes allocated in `VkDeviceMemory` blocks.\n\n    \\note To avoid confusion, please be aware that what Vulkan calls an \"allocation\" - a whole `VkDeviceMemory` object\n    (e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a \"block\" in VMA, while VMA calls\n    \"allocation\" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image.\n    */\n    VkDeviceSize blockBytes;\n    /** \\brief Total number of bytes occupied by all #VmaAllocation objects.\n\n    Always less or equal than `blockBytes`.\n    Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan\n    but unused by any #VmaAllocation.\n    */\n    VkDeviceSize allocationBytes;\n} VmaStatistics;\n\n/** \\brief More detailed statistics than #VmaStatistics.\n\nThese are slower to calculate. Use for debugging purposes.\nSee functions: vmaCalculateStatistics(), vmaCalculatePoolStatistics().\n\nPrevious version of the statistics API provided averages, but they have been removed\nbecause they can be easily calculated as:\n\n\\code\nVkDeviceSize allocationSizeAvg = detailedStats.statistics.allocationBytes / detailedStats.statistics.allocationCount;\nVkDeviceSize unusedBytes = detailedStats.statistics.blockBytes - detailedStats.statistics.allocationBytes;\nVkDeviceSize unusedRangeSizeAvg = unusedBytes / detailedStats.unusedRangeCount;\n\\endcode\n*/\ntypedef struct VmaDetailedStatistics\n{\n    /// Basic statistics.\n    VmaStatistics statistics;\n    /// Number of free ranges of memory between allocations.\n    uint32_t unusedRangeCount;\n    /// Smallest allocation size. `VK_WHOLE_SIZE` if there are 0 allocations.\n    VkDeviceSize allocationSizeMin;\n    /// Largest allocation size. 0 if there are 0 allocations.\n    VkDeviceSize allocationSizeMax;\n    /// Smallest empty range size. `VK_WHOLE_SIZE` if there are 0 empty ranges.\n    VkDeviceSize unusedRangeSizeMin;\n    /// Largest empty range size. 0 if there are 0 empty ranges.\n    VkDeviceSize unusedRangeSizeMax;\n} VmaDetailedStatistics;\n\n/** \\brief  General statistics from current state of the Allocator -\ntotal memory usage across all memory heaps and types.\n\nThese are slower to calculate. Use for debugging purposes.\nSee function vmaCalculateStatistics().\n*/\ntypedef struct VmaTotalStatistics\n{\n    VmaDetailedStatistics memoryType[VK_MAX_MEMORY_TYPES];\n    VmaDetailedStatistics memoryHeap[VK_MAX_MEMORY_HEAPS];\n    VmaDetailedStatistics total;\n} VmaTotalStatistics;\n\n/** \\brief Statistics of current memory usage and available budget for a specific memory heap.\n\nThese are fast to calculate.\nSee function vmaGetHeapBudgets().\n*/\ntypedef struct VmaBudget\n{\n    /** \\brief Statistics fetched from the library.\n    */\n    VmaStatistics statistics;\n    /** \\brief Estimated current memory usage of the program, in bytes.\n\n    Fetched from system using VK_EXT_memory_budget extension if enabled.\n\n    It might be different than `statistics.blockBytes` (usually higher) due to additional implicit objects\n    also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or\n    `VkDeviceMemory` blocks allocated outside of this library, if any.\n    */\n    VkDeviceSize usage;\n    /** \\brief Estimated amount of memory available to the program, in bytes.\n\n    Fetched from system using VK_EXT_memory_budget extension if enabled.\n\n    It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors\n    external to the program, decided by the operating system.\n    Difference `budget - usage` is the amount of additional memory that can probably\n    be allocated without problems. Exceeding the budget may result in various problems.\n    */\n    VkDeviceSize budget;\n} VmaBudget;\n\n/** @} */\n\n/**\n\\addtogroup group_alloc\n@{\n*/\n\n/** \\brief Parameters of new #VmaAllocation.\n\nTo be used with functions like vmaCreateBuffer(), vmaCreateImage(), and many others.\n*/\ntypedef struct VmaAllocationCreateInfo\n{\n    /// Use #VmaAllocationCreateFlagBits enum.\n    VmaAllocationCreateFlags flags;\n    /** \\brief Intended usage of memory.\n\n    You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \\n\n    If `pool` is not null, this member is ignored.\n    */\n    VmaMemoryUsage usage;\n    /** \\brief Flags that must be set in a Memory Type chosen for an allocation.\n\n    Leave 0 if you specify memory requirements in other way. \\n\n    If `pool` is not null, this member is ignored.*/\n    VkMemoryPropertyFlags requiredFlags;\n    /** \\brief Flags that preferably should be set in a memory type chosen for an allocation.\n\n    Set to 0 if no additional flags are preferred. \\n\n    If `pool` is not null, this member is ignored. */\n    VkMemoryPropertyFlags preferredFlags;\n    /** \\brief Bitmask containing one bit set for every memory type acceptable for this allocation.\n\n    Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if\n    it meets other requirements specified by this structure, with no further\n    restrictions on memory type index. \\n\n    If `pool` is not null, this member is ignored.\n    */\n    uint32_t memoryTypeBits;\n    /** \\brief Pool that this allocation should be created in.\n\n    Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:\n    `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.\n    */\n    VmaPool VMA_NULLABLE pool;\n    /** \\brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().\n\n    If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either\n    null or pointer to a null-terminated string. The string will be then copied to\n    internal buffer, so it doesn't need to be valid after allocation call.\n    */\n    void* VMA_NULLABLE pUserData;\n    /** \\brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.\n\n    It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object\n    and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\n    Otherwise, it has the priority of a memory block where it is placed and this variable is ignored.\n    */\n    float priority;\n} VmaAllocationCreateInfo;\n\n/// Describes parameter of created #VmaPool.\ntypedef struct VmaPoolCreateInfo\n{\n    /** \\brief Vulkan memory type index to allocate this pool from.\n    */\n    uint32_t memoryTypeIndex;\n    /** \\brief Use combination of #VmaPoolCreateFlagBits.\n    */\n    VmaPoolCreateFlags flags;\n    /** \\brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.\n\n    Specify nonzero to set explicit, constant size of memory blocks used by this\n    pool.\n\n    Leave 0 to use default and let the library manage block sizes automatically.\n    Sizes of particular blocks may vary.\n    In this case, the pool will also support dedicated allocations.\n    */\n    VkDeviceSize blockSize;\n    /** \\brief Minimum number of blocks to be always allocated in this pool, even if they stay empty.\n\n    Set to 0 to have no preallocated blocks and allow the pool be completely empty.\n    */\n    size_t minBlockCount;\n    /** \\brief Maximum number of blocks that can be allocated in this pool. Optional.\n\n    Set to 0 to use default, which is `SIZE_MAX`, which means no limit.\n\n    Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated\n    throughout whole lifetime of this pool.\n    */\n    size_t maxBlockCount;\n    /** \\brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations.\n\n    It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object.\n    Otherwise, this variable is ignored.\n    */\n    float priority;\n    /** \\brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0.\n\n    Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.\n    It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,\n    e.g. when doing interop with OpenGL.\n    */\n    VkDeviceSize minAllocationAlignment;\n    /** \\brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional.\n\n    Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`.\n    It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`.\n    Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool.\n\n    Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`,\n    can be attached automatically by this library when using other, more convenient of its features.\n    */\n    void* VMA_NULLABLE pMemoryAllocateNext;\n} VmaPoolCreateInfo;\n\n/** @} */\n\n/**\n\\addtogroup group_alloc\n@{\n*/\n\n/// Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().\ntypedef struct VmaAllocationInfo\n{\n    /** \\brief Memory type index that this allocation was allocated from.\n\n    It never changes.\n    */\n    uint32_t memoryType;\n    /** \\brief Handle to Vulkan memory object.\n\n    Same memory object can be shared by multiple allocations.\n\n    It can change after the allocation is moved during \\ref defragmentation.\n    */\n    VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory;\n    /** \\brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation.\n\n    You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function\n    vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,\n    not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation\n    and apply this offset automatically.\n\n    It can change after the allocation is moved during \\ref defragmentation.\n    */\n    VkDeviceSize offset;\n    /** \\brief Size of this allocation, in bytes.\n\n    It never changes.\n\n    \\note Allocation size returned in this variable may be greater than the size\n    requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the\n    allocation is accessible for operations on memory e.g. using a pointer after\n    mapping with vmaMapMemory(), but operations on the resource e.g. using\n    `vkCmdCopyBuffer` must be limited to the size of the resource.\n    */\n    VkDeviceSize size;\n    /** \\brief Pointer to the beginning of this allocation as mapped data.\n\n    If the allocation hasn't been mapped using vmaMapMemory() and hasn't been\n    created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null.\n\n    It can change after call to vmaMapMemory(), vmaUnmapMemory().\n    It can also change after the allocation is moved during \\ref defragmentation.\n    */\n    void* VMA_NULLABLE pMappedData;\n    /** \\brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().\n\n    It can change after call to vmaSetAllocationUserData() for this allocation.\n    */\n    void* VMA_NULLABLE pUserData;\n    /** \\brief Custom allocation name that was set with vmaSetAllocationName().\n\n    It can change after call to vmaSetAllocationName() for this allocation.\n\n    Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with\n    additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED].\n    */\n    const char* VMA_NULLABLE pName;\n} VmaAllocationInfo;\n\n/** \\brief Parameters for defragmentation.\n\nTo be used with function vmaBeginDefragmentation().\n*/\ntypedef struct VmaDefragmentationInfo\n{\n    /// \\brief Use combination of #VmaDefragmentationFlagBits.\n    VmaDefragmentationFlags flags;\n    /** \\brief Custom pool to be defragmented.\n\n    If null then default pools will undergo defragmentation process.\n    */\n    VmaPool VMA_NULLABLE pool;\n    /** \\brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places.\n\n    `0` means no limit.\n    */\n    VkDeviceSize maxBytesPerPass;\n    /** \\brief Maximum number of allocations that can be moved during single pass to a different place.\n\n    `0` means no limit.\n    */\n    uint32_t maxAllocationsPerPass;\n} VmaDefragmentationInfo;\n\n/// Single move of an allocation to be done for defragmentation.\ntypedef struct VmaDefragmentationMove\n{\n    /// Operation to be performed on the allocation by vmaEndDefragmentationPass(). Default value is #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it.\n    VmaDefragmentationMoveOperation operation;\n    /// Allocation that should be moved.\n    VmaAllocation VMA_NOT_NULL srcAllocation;\n    /** \\brief Temporary allocation pointing to destination memory that will replace `srcAllocation`.\n\n    \\warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass,\n    to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory().\n    vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory.\n    */\n    VmaAllocation VMA_NOT_NULL dstTmpAllocation;\n} VmaDefragmentationMove;\n\n/** \\brief Parameters for incremental defragmentation steps.\n\nTo be used with function vmaBeginDefragmentationPass().\n*/\ntypedef struct VmaDefragmentationPassMoveInfo\n{\n    /// Number of elements in the `pMoves` array.\n    uint32_t moveCount;\n    /** \\brief Array of moves to be performed by the user in the current defragmentation pass.\n\n    Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass().\n\n    For each element, you should:\n\n    1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset.\n    2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`.\n    3. Make sure these commands finished executing on the GPU.\n    4. Destroy the old buffer/image.\n\n    Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass().\n    After this call, the allocation will point to the new place in memory.\n\n    Alternatively, if you cannot move specific allocation, you can set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE.\n\n    Alternatively, if you decide you want to completely remove the allocation:\n\n    1. Destroy its buffer/image.\n    2. Set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY.\n\n    Then, after vmaEndDefragmentationPass() the allocation will be freed.\n    */\n    VmaDefragmentationMove* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(moveCount) pMoves;\n} VmaDefragmentationPassMoveInfo;\n\n/// Statistics returned for defragmentation process in function vmaEndDefragmentation().\ntypedef struct VmaDefragmentationStats\n{\n    /// Total number of bytes that have been copied while moving allocations to different places.\n    VkDeviceSize bytesMoved;\n    /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects.\n    VkDeviceSize bytesFreed;\n    /// Number of allocations that have been moved to different places.\n    uint32_t allocationsMoved;\n    /// Number of empty `VkDeviceMemory` objects that have been released to the system.\n    uint32_t deviceMemoryBlocksFreed;\n} VmaDefragmentationStats;\n\n/** @} */\n\n/**\n\\addtogroup group_virtual\n@{\n*/\n\n/// Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock().\ntypedef struct VmaVirtualBlockCreateInfo\n{\n    /** \\brief Total size of the virtual block.\n\n    Sizes can be expressed in bytes or any units you want as long as you are consistent in using them.\n    For example, if you allocate from some array of structures, 1 can mean single instance of entire structure.\n    */\n    VkDeviceSize size;\n\n    /** \\brief Use combination of #VmaVirtualBlockCreateFlagBits.\n    */\n    VmaVirtualBlockCreateFlags flags;\n\n    /** \\brief Custom CPU memory allocation callbacks. Optional.\n\n    Optional, can be null. When specified, they will be used for all CPU-side memory allocations.\n    */\n    const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks;\n} VmaVirtualBlockCreateInfo;\n\n/// Parameters of created virtual allocation to be passed to vmaVirtualAllocate().\ntypedef struct VmaVirtualAllocationCreateInfo\n{\n    /** \\brief Size of the allocation.\n\n    Cannot be zero.\n    */\n    VkDeviceSize size;\n    /** \\brief Required alignment of the allocation. Optional.\n\n    Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset.\n    */\n    VkDeviceSize alignment;\n    /** \\brief Use combination of #VmaVirtualAllocationCreateFlagBits.\n    */\n    VmaVirtualAllocationCreateFlags flags;\n    /** \\brief Custom pointer to be associated with the allocation. Optional.\n\n    It can be any value and can be used for user-defined purposes. It can be fetched or changed later.\n    */\n    void* VMA_NULLABLE pUserData;\n} VmaVirtualAllocationCreateInfo;\n\n/// Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo().\ntypedef struct VmaVirtualAllocationInfo\n{\n    /** \\brief Offset of the allocation.\n\n    Offset at which the allocation was made.\n    */\n    VkDeviceSize offset;\n    /** \\brief Size of the allocation.\n\n    Same value as passed in VmaVirtualAllocationCreateInfo::size.\n    */\n    VkDeviceSize size;\n    /** \\brief Custom pointer associated with the allocation.\n\n    Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData().\n    */\n    void* VMA_NULLABLE pUserData;\n} VmaVirtualAllocationInfo;\n\n/** @} */\n\n#endif // _VMA_DATA_TYPES_DECLARATIONS\n\n#ifndef _VMA_FUNCTION_HEADERS\n\n/**\n\\addtogroup group_init\n@{\n*/\n\n/// Creates #VmaAllocator object.\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(\n    const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaAllocator VMA_NULLABLE* VMA_NOT_NULL pAllocator);\n\n/// Destroys allocator object.\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(\n    VmaAllocator VMA_NULLABLE allocator);\n\n/** \\brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc.\n\nIt might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to\n`VkPhysicalDevice`, `VkDevice` etc. every time using this function.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo);\n\n/**\nPhysicalDeviceProperties are fetched from physicalDevice by the allocator.\nYou can access it here, without fetching it again on your own.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkPhysicalDeviceProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceProperties);\n\n/**\nPhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator.\nYou can access it here, without fetching it again on your own.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceMemoryProperties);\n\n/**\n\\brief Given Memory Type Index, returns Property Flags of this memory type.\n\nThis is just a convenience function. Same information can be obtained using\nvmaGetMemoryProperties().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(\n    VmaAllocator VMA_NOT_NULL allocator,\n    uint32_t memoryTypeIndex,\n    VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);\n\n/** \\brief Sets index of the current frame.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(\n    VmaAllocator VMA_NOT_NULL allocator,\n    uint32_t frameIndex);\n\n/** @} */\n\n/**\n\\addtogroup group_stats\n@{\n*/\n\n/** \\brief Retrieves statistics from current state of the Allocator.\n\nThis function is called \"calculate\" not \"get\" because it has to traverse all\ninternal data structures, so it may be quite slow. Use it for debugging purposes.\nFor faster but more brief statistics suitable to be called every frame or every allocation,\nuse vmaGetHeapBudgets().\n\nNote that when using allocator from multiple threads, returned information may immediately\nbecome outdated.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaTotalStatistics* VMA_NOT_NULL pStats);\n\n/** \\brief Retrieves information about current memory usage and budget for all memory heaps.\n\n\\param allocator\n\\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used.\n\nThis function is called \"get\" not \"calculate\" because it is very fast, suitable to be called\nevery frame or every allocation. For more detailed statistics use vmaCalculateStatistics().\n\nNote that when using allocator from multiple threads, returned information may immediately\nbecome outdated.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaBudget* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(\"VkPhysicalDeviceMemoryProperties::memoryHeapCount\") pBudgets);\n\n/** @} */\n\n/**\n\\addtogroup group_alloc\n@{\n*/\n\n/**\n\\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.\n\nThis algorithm tries to find a memory type that:\n\n- Is allowed by memoryTypeBits.\n- Contains all the flags from pAllocationCreateInfo->requiredFlags.\n- Matches intended usage.\n- Has as many flags from pAllocationCreateInfo->preferredFlags as possible.\n\n\\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result\nfrom this function or any other allocating function probably means that your\ndevice doesn't support any memory type with requested features for the specific\ntype of resource you want to use it for. Please check parameters of your\nresource, like image layout (OPTIMAL versus LINEAR) or mip level count.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(\n    VmaAllocator VMA_NOT_NULL allocator,\n    uint32_t memoryTypeBits,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,\n    uint32_t* VMA_NOT_NULL pMemoryTypeIndex);\n\n/**\n\\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.\n\nIt can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.\nIt internally creates a temporary, dummy buffer that never has memory bound.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,\n    uint32_t* VMA_NOT_NULL pMemoryTypeIndex);\n\n/**\n\\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.\n\nIt can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.\nIt internally creates a temporary, dummy image that never has memory bound.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,\n    uint32_t* VMA_NOT_NULL pMemoryTypeIndex);\n\n/** \\brief Allocates Vulkan device memory and creates #VmaPool object.\n\n\\param allocator Allocator object.\n\\param pCreateInfo Parameters of pool to create.\n\\param[out] pPool Handle to created pool.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaPool VMA_NULLABLE* VMA_NOT_NULL pPool);\n\n/** \\brief Destroys #VmaPool object and frees Vulkan device memory.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaPool VMA_NULLABLE pool);\n\n/** @} */\n\n/**\n\\addtogroup group_stats\n@{\n*/\n\n/** \\brief Retrieves statistics of existing #VmaPool object.\n\n\\param allocator Allocator object.\n\\param pool Pool object.\n\\param[out] pPoolStats Statistics of specified pool.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaPool VMA_NOT_NULL pool,\n    VmaStatistics* VMA_NOT_NULL pPoolStats);\n\n/** \\brief Retrieves detailed statistics of existing #VmaPool object.\n\n\\param allocator Allocator object.\n\\param pool Pool object.\n\\param[out] pPoolStats Statistics of specified pool.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaPool VMA_NOT_NULL pool,\n    VmaDetailedStatistics* VMA_NOT_NULL pPoolStats);\n\n/** @} */\n\n/**\n\\addtogroup group_alloc\n@{\n*/\n\n/** \\brief Checks magic number in margins around all allocations in given memory pool in search for corruptions.\n\nCorruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,\n`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is\n`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).\n\nPossible return values:\n\n- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool.\n- `VK_SUCCESS` - corruption detection has been performed and succeeded.\n- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations.\n  `VMA_ASSERT` is also fired in that case.\n- Other value: Error returned by Vulkan, e.g. memory mapping failure.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaPool VMA_NOT_NULL pool);\n\n/** \\brief Retrieves name of a custom pool.\n\nAfter the call `ppName` is either null or points to an internally-owned null-terminated string\ncontaining name of the pool that was previously set. The pointer becomes invalid when the pool is\ndestroyed or its name is changed using vmaSetPoolName().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaPool VMA_NOT_NULL pool,\n    const char* VMA_NULLABLE* VMA_NOT_NULL ppName);\n\n/** \\brief Sets name of a custom pool.\n\n`pName` can be either null or pointer to a null-terminated string with new name for the pool.\nFunction makes internal copy of the string, so it can be changed or freed immediately after this call.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaPool VMA_NOT_NULL pool,\n    const char* VMA_NULLABLE pName);\n\n/** \\brief General purpose memory allocation.\n\n\\param allocator\n\\param pVkMemoryRequirements\n\\param pCreateInfo\n\\param[out] pAllocation Handle to allocated memory.\n\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().\n\nYou should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().\n\nIt is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(),\nvmaCreateBuffer(), vmaCreateImage() instead whenever possible.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,\n    VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);\n\n/** \\brief General purpose memory allocation for multiple allocation objects at once.\n\n\\param allocator Allocator object.\n\\param pVkMemoryRequirements Memory requirements for each allocation.\n\\param pCreateInfo Creation parameters for each allocation.\n\\param allocationCount Number of allocations to make.\n\\param[out] pAllocations Pointer to array that will be filled with handles to created allocations.\n\\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations.\n\nYou should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().\n\nWord \"pages\" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding.\nIt is just a general purpose allocation function able to make multiple allocations at once.\nIt may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times.\n\nAll allocations are made using same parameters. All of them are created out of the same memory pool and type.\nIf any allocation fails, all allocations already made within this function call are also freed, so that when\nreturned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkMemoryRequirements* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pVkMemoryRequirements,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pCreateInfo,\n    size_t allocationCount,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations,\n    VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo);\n\n/** \\brief Allocates memory suitable for given `VkBuffer`.\n\n\\param allocator\n\\param buffer\n\\param pCreateInfo\n\\param[out] pAllocation Handle to allocated memory.\n\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().\n\nIt only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindBufferMemory().\n\nThis is a special-purpose function. In most cases you should use vmaCreateBuffer().\n\nYou must free the allocation using vmaFreeMemory() when no longer needed.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,\n    VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);\n\n/** \\brief Allocates memory suitable for given `VkImage`.\n\n\\param allocator\n\\param image\n\\param pCreateInfo\n\\param[out] pAllocation Handle to allocated memory.\n\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().\n\nIt only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindImageMemory().\n\nThis is a special-purpose function. In most cases you should use vmaCreateImage().\n\nYou must free the allocation using vmaFreeMemory() when no longer needed.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VkImage VMA_NOT_NULL_NON_DISPATCHABLE image,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,\n    VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);\n\n/** \\brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage().\n\nPassing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VmaAllocation VMA_NULLABLE allocation);\n\n/** \\brief Frees memory and destroys multiple allocations.\n\nWord \"pages\" is just a suggestion to use this function to free pieces of memory used for sparse binding.\nIt is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(),\nvmaAllocateMemoryPages() and other functions.\nIt may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times.\n\nAllocations in `pAllocations` array can come from any memory pools and types.\nPassing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(\n    VmaAllocator VMA_NOT_NULL allocator,\n    size_t allocationCount,\n    const VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations);\n\n/** \\brief Returns current information about specified allocation.\n\nCurrent parameters of given allocation are returned in `pAllocationInfo`.\n\nAlthough this function doesn't lock any mutex, so it should be quite efficient,\nyou should avoid calling it too often.\nYou can retrieve same VmaAllocationInfo structure while creating your resource, from function\nvmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change\n(e.g. due to defragmentation).\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo);\n\n/** \\brief Sets pUserData in given allocation to new value.\n\nThe value of pointer `pUserData` is copied to allocation's `pUserData`.\nIt is opaque, so you can use it however you want - e.g.\nas a pointer, ordinal number or some handle to you own data.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    void* VMA_NULLABLE pUserData);\n\n/** \\brief Sets pName in given allocation to new value.\n\n`pName` must be either null, or pointer to a null-terminated string. The function\nmakes local copy of the string and sets it as allocation's `pName`. String\npassed as pName doesn't need to be valid for whole lifetime of the allocation -\nyou can free it after this call. String previously pointed by allocation's\n`pName` is freed from memory.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    const char* VMA_NULLABLE pName);\n\n/**\n\\brief Given an allocation, returns Property Flags of its memory type.\n\nThis is just a convenience function. Same information can be obtained using\nvmaGetAllocationInfo() + vmaGetMemoryProperties().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);\n\n/** \\brief Maps memory represented by given allocation and returns pointer to it.\n\nMaps memory represented by given allocation to make it accessible to CPU code.\nWhen succeeded, `*ppData` contains pointer to first byte of this memory.\n\n\\warning\nIf the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is\ncorrectly offsetted to the beginning of region assigned to this particular allocation.\nUnlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block.\nYou should not add VmaAllocationInfo::offset to it!\n\nMapping is internally reference-counted and synchronized, so despite raw Vulkan\nfunction `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`\nmultiple times simultaneously, it is safe to call this function on allocations\nassigned to the same memory block. Actual Vulkan memory will be mapped on first\nmapping and unmapped on last unmapping.\n\nIf the function succeeded, you must call vmaUnmapMemory() to unmap the\nallocation when mapping is no longer needed or before freeing the allocation, at\nthe latest.\n\nIt also safe to call this function multiple times on the same allocation. You\nmust call vmaUnmapMemory() same number of times as you called vmaMapMemory().\n\nIt is also safe to call this function on allocation created with\n#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time.\nYou must still call vmaUnmapMemory() same number of times as you called\nvmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the\n\"0-th\" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag.\n\nThis function fails when used on allocation made in memory type that is not\n`HOST_VISIBLE`.\n\nThis function doesn't automatically flush or invalidate caches.\nIf the allocation is made from a memory types that is not `HOST_COHERENT`,\nyou also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    void* VMA_NULLABLE* VMA_NOT_NULL ppData);\n\n/** \\brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().\n\nFor details, see description of vmaMapMemory().\n\nThis function doesn't automatically flush or invalidate caches.\nIf the allocation is made from a memory types that is not `HOST_COHERENT`,\nyou also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation);\n\n/** \\brief Flushes memory of given allocation.\n\nCalls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation.\nIt needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`.\nUnmap operation doesn't do that automatically.\n\n- `offset` must be relative to the beginning of allocation.\n- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.\n- `offset` and `size` don't have to be aligned.\n  They are internally rounded down/up to multiply of `nonCoherentAtomSize`.\n- If `size` is 0, this call is ignored.\n- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,\n  this call is ignored.\n\nWarning! `offset` and `size` are relative to the contents of given `allocation`.\nIf you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively.\nDo not pass allocation's offset as `offset`!!!\n\nThis function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is\ncalled, otherwise `VK_SUCCESS`.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize offset,\n    VkDeviceSize size);\n\n/** \\brief Invalidates memory of given allocation.\n\nCalls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation.\nIt needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`.\nMap operation doesn't do that automatically.\n\n- `offset` must be relative to the beginning of allocation.\n- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.\n- `offset` and `size` don't have to be aligned.\n  They are internally rounded down/up to multiply of `nonCoherentAtomSize`.\n- If `size` is 0, this call is ignored.\n- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,\n  this call is ignored.\n\nWarning! `offset` and `size` are relative to the contents of given `allocation`.\nIf you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively.\nDo not pass allocation's offset as `offset`!!!\n\nThis function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if\nit is called, otherwise `VK_SUCCESS`.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize offset,\n    VkDeviceSize size);\n\n/** \\brief Flushes memory of given set of allocations.\n\nCalls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations.\nFor more information, see documentation of vmaFlushAllocation().\n\n\\param allocator\n\\param allocationCount\n\\param allocations\n\\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero.\n\\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations.\n\nThis function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is\ncalled, otherwise `VK_SUCCESS`.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations(\n    VmaAllocator VMA_NOT_NULL allocator,\n    uint32_t allocationCount,\n    const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations,\n    const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets,\n    const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes);\n\n/** \\brief Invalidates memory of given set of allocations.\n\nCalls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations.\nFor more information, see documentation of vmaInvalidateAllocation().\n\n\\param allocator\n\\param allocationCount\n\\param allocations\n\\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero.\n\\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations.\n\nThis function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is\ncalled, otherwise `VK_SUCCESS`.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations(\n    VmaAllocator VMA_NOT_NULL allocator,\n    uint32_t allocationCount,\n    const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations,\n    const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets,\n    const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes);\n\n/** \\brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.\n\n\\param allocator\n\\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked.\n\nCorruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,\n`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are\n`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).\n\nPossible return values:\n\n- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types.\n- `VK_SUCCESS` - corruption detection has been performed and succeeded.\n- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations.\n  `VMA_ASSERT` is also fired in that case.\n- Other value: Error returned by Vulkan, e.g. memory mapping failure.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(\n    VmaAllocator VMA_NOT_NULL allocator,\n    uint32_t memoryTypeBits);\n\n/** \\brief Begins defragmentation process.\n\n\\param allocator Allocator object.\n\\param pInfo Structure filled with parameters of defragmentation.\n\\param[out] pContext Context object that must be passed to vmaEndDefragmentation() to finish defragmentation.\n\\returns\n- `VK_SUCCESS` if defragmentation can begin.\n- `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported.\n\nFor more information about defragmentation, see documentation chapter:\n[Defragmentation](@ref defragmentation).\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VmaDefragmentationInfo* VMA_NOT_NULL pInfo,\n    VmaDefragmentationContext VMA_NULLABLE* VMA_NOT_NULL pContext);\n\n/** \\brief Ends defragmentation process.\n\n\\param allocator Allocator object.\n\\param context Context object that has been created by vmaBeginDefragmentation().\n\\param[out] pStats Optional stats for the defragmentation. Can be null.\n\nUse this function to finish defragmentation started by vmaBeginDefragmentation().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaDefragmentationContext VMA_NOT_NULL context,\n    VmaDefragmentationStats* VMA_NULLABLE pStats);\n\n/** \\brief Starts single defragmentation pass.\n\n\\param allocator Allocator object.\n\\param context Context object that has been created by vmaBeginDefragmentation().\n\\param[out] pPassInfo Computed information for current pass.\n\\returns\n- `VK_SUCCESS` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation.\n- `VK_INCOMPLETE` if there are pending moves returned in `pPassInfo`. You need to perform them, call vmaEndDefragmentationPass(),\n  and then preferably try another pass with vmaBeginDefragmentationPass().\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaDefragmentationContext VMA_NOT_NULL context,\n    VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo);\n\n/** \\brief Ends single defragmentation pass.\n\n\\param allocator Allocator object.\n\\param context Context object that has been created by vmaBeginDefragmentation().\n\\param pPassInfo Computed information for current pass filled by vmaBeginDefragmentationPass() and possibly modified by you.\n\nReturns `VK_SUCCESS` if no more moves are possible or `VK_INCOMPLETE` if more defragmentations are possible.\n\nEnds incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`.\nAfter this call:\n\n- Allocations at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY\n  (which is the default) will be pointing to the new destination place.\n- Allocation at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY\n  will be freed.\n\nIf no more moves are possible you can end whole defragmentation.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaDefragmentationContext VMA_NOT_NULL context,\n    VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo);\n\n/** \\brief Binds buffer to allocation.\n\nBinds specified buffer to region of memory represented by specified allocation.\nGets `VkDeviceMemory` handle and offset from the allocation.\nIf you want to create a buffer, allocate memory for it and bind them together separately,\nyou should use this function for binding instead of standard `vkBindBufferMemory()`,\nbecause it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple\nallocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously\n(which is illegal in Vulkan).\n\nIt is recommended to use function vmaCreateBuffer() instead of this one.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer);\n\n/** \\brief Binds buffer to allocation with additional parameters.\n\n\\param allocator\n\\param allocation\n\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.\n\\param buffer\n\\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null.\n\nThis function is similar to vmaBindBufferMemory(), but it provides additional parameters.\n\nIf `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag\nor with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize allocationLocalOffset,\n    VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer,\n    const void* VMA_NULLABLE pNext);\n\n/** \\brief Binds image to allocation.\n\nBinds specified image to region of memory represented by specified allocation.\nGets `VkDeviceMemory` handle and offset from the allocation.\nIf you want to create an image, allocate memory for it and bind them together separately,\nyou should use this function for binding instead of standard `vkBindImageMemory()`,\nbecause it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple\nallocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously\n(which is illegal in Vulkan).\n\nIt is recommended to use function vmaCreateImage() instead of this one.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkImage VMA_NOT_NULL_NON_DISPATCHABLE image);\n\n/** \\brief Binds image to allocation with additional parameters.\n\n\\param allocator\n\\param allocation\n\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.\n\\param image\n\\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.\n\nThis function is similar to vmaBindImageMemory(), but it provides additional parameters.\n\nIf `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag\nor with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize allocationLocalOffset,\n    VkImage VMA_NOT_NULL_NON_DISPATCHABLE image,\n    const void* VMA_NULLABLE pNext);\n\n/** \\brief Creates a new `VkBuffer`, allocates and binds memory for it.\n\n\\param allocator\n\\param pBufferCreateInfo\n\\param pAllocationCreateInfo\n\\param[out] pBuffer Buffer that was created.\n\\param[out] pAllocation Allocation that was created.\n\\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().\n\nThis function automatically:\n\n-# Creates buffer.\n-# Allocates appropriate memory for it.\n-# Binds the buffer with the memory.\n\nIf any of these operations fail, buffer and allocation are not created,\nreturned value is negative error code, `*pBuffer` and `*pAllocation` are null.\n\nIf the function succeeded, you must destroy both buffer and allocation when you\nno longer need them using either convenience function vmaDestroyBuffer() or\nseparately, using `vkDestroyBuffer()` and vmaFreeMemory().\n\nIf #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,\nVK_KHR_dedicated_allocation extension is used internally to query driver whether\nit requires or prefers the new buffer to have dedicated allocation. If yes,\nand if dedicated allocation is possible\n(#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated\nallocation for this buffer, just like when using\n#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\n\n\\note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer,\nalthough recommended as a good practice, is out of scope of this library and could be implemented\nby the user as a higher-level logic on top of VMA.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,\n    VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);\n\n/** \\brief Creates a buffer with additional minimum alignment.\n\nSimilar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom,\nminimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g.\nfor interop with OpenGL.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,\n    VkDeviceSize minAlignment,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,\n    VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);\n\n/** \\brief Creates a new `VkBuffer`, binds already created memory for it.\n\n\\param allocator\n\\param allocation Allocation that provides memory to be used for binding new buffer to it.\n\\param pBufferCreateInfo\n\\param[out] pBuffer Buffer that was created.\n\nThis function automatically:\n\n-# Creates buffer.\n-# Binds the buffer with the supplied memory.\n\nIf any of these operations fail, buffer is not created,\nreturned value is negative error code and `*pBuffer` is null.\n\nIf the function succeeded, you must destroy the buffer when you\nno longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding\nallocation you can use convenience function vmaDestroyBuffer().\n\n\\note There is a new version of this function augmented with parameter `allocationLocalOffset` - see vmaCreateAliasingBuffer2().\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer);\n\n/** \\brief Creates a new `VkBuffer`, binds already created memory for it.\n\n\\param allocator\n\\param allocation Allocation that provides memory to be used for binding new buffer to it.\n\\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the allocation. Normally it should be 0.\n\\param pBufferCreateInfo \n\\param[out] pBuffer Buffer that was created.\n\nThis function automatically:\n\n-# Creates buffer.\n-# Binds the buffer with the supplied memory.\n\nIf any of these operations fail, buffer is not created,\nreturned value is negative error code and `*pBuffer` is null.\n\nIf the function succeeded, you must destroy the buffer when you\nno longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding\nallocation you can use convenience function vmaDestroyBuffer().\n\n\\note This is a new version of the function augmented with parameter `allocationLocalOffset`.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize allocationLocalOffset,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer);\n\n/** \\brief Destroys Vulkan buffer and frees allocated memory.\n\nThis is just a convenience function equivalent to:\n\n\\code\nvkDestroyBuffer(device, buffer, allocationCallbacks);\nvmaFreeMemory(allocator, allocation);\n\\endcode\n\nIt is safe to pass null as buffer and/or allocation.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE buffer,\n    VmaAllocation VMA_NULLABLE allocation);\n\n/// Function similar to vmaCreateBuffer().\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(\n    VmaAllocator VMA_NOT_NULL allocator,\n    const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,\n    const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage,\n    VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,\n    VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);\n\n/// Function similar to vmaCreateAliasingBuffer() but for images.\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage);\n\n/// Function similar to vmaCreateAliasingBuffer2() but for images.\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize allocationLocalOffset,\n    const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage);\n\n/** \\brief Destroys Vulkan image and frees allocated memory.\n\nThis is just a convenience function equivalent to:\n\n\\code\nvkDestroyImage(device, image, allocationCallbacks);\nvmaFreeMemory(allocator, allocation);\n\\endcode\n\nIt is safe to pass null as image and/or allocation.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE image,\n    VmaAllocation VMA_NULLABLE allocation);\n\n/** @} */\n\n/**\n\\addtogroup group_virtual\n@{\n*/\n\n/** \\brief Creates new #VmaVirtualBlock object.\n\n\\param pCreateInfo Parameters for creation.\n\\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock(\n    const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock);\n\n/** \\brief Destroys #VmaVirtualBlock object.\n\nPlease note that you should consciously handle virtual allocations that could remain unfreed in the block.\nYou should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock()\nif you are sure this is what you want. If you do neither, an assert is called.\n\nIf you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`,\ndon't forget to free them.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(\n    VmaVirtualBlock VMA_NULLABLE virtualBlock);\n\n/** \\brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations.\n*/\nVMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock);\n\n/** \\brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo);\n\n/** \\brief Allocates new virtual allocation inside given #VmaVirtualBlock.\n\nIf the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned\n(despite the function doesn't ever allocate actual GPU memory).\n`pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`.\n\n\\param virtualBlock Virtual block\n\\param pCreateInfo Parameters for the allocation\n\\param[out] pAllocation Returned handle of the new allocation\n\\param[out] pOffset Returned offset of the new allocation. Optional, can be null.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation,\n    VkDeviceSize* VMA_NULLABLE pOffset);\n\n/** \\brief Frees virtual allocation inside given #VmaVirtualBlock.\n\nIt is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation);\n\n/** \\brief Frees all virtual allocations inside given #VmaVirtualBlock.\n\nYou must either call this function or free each virtual allocation individually with vmaVirtualFree()\nbefore destroying a virtual block. Otherwise, an assert is called.\n\nIf you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`,\ndon't forget to free it as well.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock);\n\n/** \\brief Changes custom pointer associated with given virtual allocation.\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation,\n    void* VMA_NULLABLE pUserData);\n\n/** \\brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock.\n\nThis function is fast to call. For more detailed statistics, see vmaCalculateVirtualBlockStatistics().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaStatistics* VMA_NOT_NULL pStats);\n\n/** \\brief Calculates and returns detailed statistics about virtual allocations and memory usage in given #VmaVirtualBlock.\n\nThis function is slow to call. Use for debugging purposes.\nFor less detailed statistics, see vmaGetVirtualBlockStatistics().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaDetailedStatistics* VMA_NOT_NULL pStats);\n\n/** @} */\n\n#if VMA_STATS_STRING_ENABLED\n/**\n\\addtogroup group_stats\n@{\n*/\n\n/** \\brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock.\n\\param virtualBlock Virtual block.\n\\param[out] ppStatsString Returned string.\n\\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStatistics(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces.\n\nReturned string must be freed using vmaFreeVirtualBlockStatsString().\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString,\n    VkBool32 detailedMap);\n\n/// Frees a string returned by vmaBuildVirtualBlockStatsString().\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(\n    VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    char* VMA_NULLABLE pStatsString);\n\n/** \\brief Builds and returns statistics as a null-terminated string in JSON format.\n\\param allocator\n\\param[out] ppStatsString Must be freed using vmaFreeStatsString() function.\n\\param detailedMap\n*/\nVMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(\n    VmaAllocator VMA_NOT_NULL allocator,\n    char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString,\n    VkBool32 detailedMap);\n\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(\n    VmaAllocator VMA_NOT_NULL allocator,\n    char* VMA_NULLABLE pStatsString);\n\n/** @} */\n\n#endif // VMA_STATS_STRING_ENABLED\n\n#endif // _VMA_FUNCTION_HEADERS\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H\n\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n//\n//    IMPLEMENTATION\n//\n////////////////////////////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////////////////////////////\n\n// For Visual Studio IntelliSense.\n#if defined(__cplusplus) && defined(__INTELLISENSE__)\n#define VMA_IMPLEMENTATION\n#endif\n\n#ifdef VMA_IMPLEMENTATION\n#undef VMA_IMPLEMENTATION\n\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <utility>\n#include <type_traits>\n\n#ifdef _MSC_VER\n    #include <intrin.h> // For functions like __popcnt, _BitScanForward etc.\n#endif\n#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20\n    #include <bit> // For std::popcount\n#endif\n\n/*******************************************************************************\nCONFIGURATION SECTION\n\nDefine some of these macros before each #include of this header or change them\nhere if you need other then default behavior depending on your environment.\n*/\n#ifndef _VMA_CONFIGURATION\n\n/*\nDefine this macro to 1 to make the library fetch pointers to Vulkan functions\ninternally, like:\n\n    vulkanFunctions.vkAllocateMemory = &vkAllocateMemory;\n*/\n#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES)\n    #define VMA_STATIC_VULKAN_FUNCTIONS 1\n#endif\n\n/*\nDefine this macro to 1 to make the library fetch pointers to Vulkan functions\ninternally, like:\n\n    vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(device, \"vkAllocateMemory\");\n\nTo use this feature in new versions of VMA you now have to pass\nVmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as\nVmaAllocatorCreateInfo::pVulkanFunctions. Other members can be null.\n*/\n#if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS)\n    #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1\n#endif\n\n#ifndef VMA_USE_STL_SHARED_MUTEX\n    // Compiler conforms to C++17.\n    #if __cplusplus >= 201703L\n        #define VMA_USE_STL_SHARED_MUTEX 1\n    // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus\n    // Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2.\n    #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L\n        #define VMA_USE_STL_SHARED_MUTEX 1\n    #else\n        #define VMA_USE_STL_SHARED_MUTEX 0\n    #endif\n#endif\n\n/*\nDefine this macro to include custom header files without having to edit this file directly, e.g.:\n\n    // Inside of \"my_vma_configuration_user_includes.h\":\n\n    #include \"my_custom_assert.h\" // for MY_CUSTOM_ASSERT\n    #include \"my_custom_min.h\" // for my_custom_min\n    #include <algorithm>\n    #include <mutex>\n\n    // Inside a different file, which includes \"vk_mem_alloc.h\":\n\n    #define VMA_CONFIGURATION_USER_INCLUDES_H \"my_vma_configuration_user_includes.h\"\n    #define VMA_ASSERT(expr) MY_CUSTOM_ASSERT(expr)\n    #define VMA_MIN(v1, v2)  (my_custom_min(v1, v2))\n    #include \"vk_mem_alloc.h\"\n    ...\n\nThe following headers are used in this CONFIGURATION section only, so feel free to\nremove them if not needed.\n*/\n#if !defined(VMA_CONFIGURATION_USER_INCLUDES_H)\n    #include <cassert> // for assert\n    #include <algorithm> // for min, max\n    #include <mutex>\n#else\n    #include VMA_CONFIGURATION_USER_INCLUDES_H\n#endif\n\n#ifndef VMA_NULL\n   // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.\n   #define VMA_NULL   nullptr\n#endif\n\n// Normal assert to check for programmer's errors, especially in Debug configuration.\n#ifndef VMA_ASSERT\n   #ifdef NDEBUG\n       #define VMA_ASSERT(expr)\n   #else\n       #define VMA_ASSERT(expr)         assert(expr)\n   #endif\n#endif\n\n// Assert that will be called very often, like inside data structures e.g. operator[].\n// Making it non-empty can make program slow.\n#ifndef VMA_HEAVY_ASSERT\n   #ifdef NDEBUG\n       #define VMA_HEAVY_ASSERT(expr)\n   #else\n       #define VMA_HEAVY_ASSERT(expr)   //VMA_ASSERT(expr)\n   #endif\n#endif\n\n// If your compiler is not compatible with C++17 and definition of\n// aligned_alloc() function is missing, uncommenting following line may help:\n\n//#include <malloc.h>\n\n#if defined(__ANDROID_API__) && (__ANDROID_API__ < 16)\n#include <cstdlib>\nstatic void* vma_aligned_alloc(size_t alignment, size_t size)\n{\n    // alignment must be >= sizeof(void*)\n    if(alignment < sizeof(void*))\n    {\n        alignment = sizeof(void*);\n    }\n\n    return memalign(alignment, size);\n}\n#elif defined(__APPLE__) || defined(__ANDROID__) || (defined(__linux__) && defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC))\n#include <cstdlib>\n\n#if defined(__APPLE__)\n#include <AvailabilityMacros.h>\n#endif\n\nstatic void* vma_aligned_alloc(size_t alignment, size_t size)\n{\n    // Unfortunately, aligned_alloc causes VMA to crash due to it returning null pointers. (At least under 11.4)\n    // Therefore, for now disable this specific exception until a proper solution is found.\n    //#if defined(__APPLE__) && (defined(MAC_OS_X_VERSION_10_16) || defined(__IPHONE_14_0))\n    //#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_16 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0\n    //    // For C++14, usr/include/malloc/_malloc.h declares aligned_alloc()) only\n    //    // with the MacOSX11.0 SDK in Xcode 12 (which is what adds\n    //    // MAC_OS_X_VERSION_10_16), even though the function is marked\n    //    // available for 10.15. That is why the preprocessor checks for 10.16 but\n    //    // the __builtin_available checks for 10.15.\n    //    // People who use C++17 could call aligned_alloc with the 10.15 SDK already.\n    //    if (__builtin_available(macOS 10.15, iOS 13, *))\n    //        return aligned_alloc(alignment, size);\n    //#endif\n    //#endif\n\n    // alignment must be >= sizeof(void*)\n    if(alignment < sizeof(void*))\n    {\n        alignment = sizeof(void*);\n    }\n\n    void *pointer;\n    if(posix_memalign(&pointer, alignment, size) == 0)\n        return pointer;\n    return VMA_NULL;\n}\n#elif defined(_WIN32)\nstatic void* vma_aligned_alloc(size_t alignment, size_t size)\n{\n    return _aligned_malloc(size, alignment);\n}\n#elif __cplusplus >= 201703L // Compiler conforms to C++17.\nstatic void* vma_aligned_alloc(size_t alignment, size_t size)\n{\n    return aligned_alloc(alignment, size);\n}\n#else\nstatic void* vma_aligned_alloc(size_t alignment, size_t size)\n{\n    VMA_ASSERT(0 && \"Could not implement aligned_alloc automatically. Please enable C++17 or later in your compiler or provide custom implementation of macro VMA_SYSTEM_ALIGNED_MALLOC (and VMA_SYSTEM_ALIGNED_FREE if needed) using the API of your system.\");\n    return VMA_NULL;\n}\n#endif\n\n#if defined(_WIN32)\nstatic void vma_aligned_free(void* ptr)\n{\n    _aligned_free(ptr);\n}\n#else\nstatic void vma_aligned_free(void* VMA_NULLABLE ptr)\n{\n    free(ptr);\n}\n#endif\n\n#ifndef VMA_ALIGN_OF\n   #define VMA_ALIGN_OF(type)       (__alignof(type))\n#endif\n\n#ifndef VMA_SYSTEM_ALIGNED_MALLOC\n   #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) vma_aligned_alloc((alignment), (size))\n#endif\n\n#ifndef VMA_SYSTEM_ALIGNED_FREE\n   // VMA_SYSTEM_FREE is the old name, but might have been defined by the user\n   #if defined(VMA_SYSTEM_FREE)\n      #define VMA_SYSTEM_ALIGNED_FREE(ptr)     VMA_SYSTEM_FREE(ptr)\n   #else\n      #define VMA_SYSTEM_ALIGNED_FREE(ptr)     vma_aligned_free(ptr)\n    #endif\n#endif\n\n#ifndef VMA_COUNT_BITS_SET\n    // Returns number of bits set to 1 in (v)\n    #define VMA_COUNT_BITS_SET(v) VmaCountBitsSet(v)\n#endif\n\n#ifndef VMA_BITSCAN_LSB\n    // Scans integer for index of first nonzero value from the Least Significant Bit (LSB). If mask is 0 then returns UINT8_MAX\n    #define VMA_BITSCAN_LSB(mask) VmaBitScanLSB(mask)\n#endif\n\n#ifndef VMA_BITSCAN_MSB\n    // Scans integer for index of first nonzero value from the Most Significant Bit (MSB). If mask is 0 then returns UINT8_MAX\n    #define VMA_BITSCAN_MSB(mask) VmaBitScanMSB(mask)\n#endif\n\n#ifndef VMA_MIN\n   #define VMA_MIN(v1, v2)    ((std::min)((v1), (v2)))\n#endif\n\n#ifndef VMA_MAX\n   #define VMA_MAX(v1, v2)    ((std::max)((v1), (v2)))\n#endif\n\n#ifndef VMA_SWAP\n   #define VMA_SWAP(v1, v2)   std::swap((v1), (v2))\n#endif\n\n#ifndef VMA_SORT\n   #define VMA_SORT(beg, end, cmp)  std::sort(beg, end, cmp)\n#endif\n\n#ifndef VMA_DEBUG_LOG\n   #define VMA_DEBUG_LOG(format, ...)\n   /*\n   #define VMA_DEBUG_LOG(format, ...) do { \\\n       printf(format, __VA_ARGS__); \\\n       printf(\"\\n\"); \\\n   } while(false)\n   */\n#endif\n\n// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString.\n#if VMA_STATS_STRING_ENABLED\n    static inline void VmaUint32ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint32_t num)\n    {\n        snprintf(outStr, strLen, \"%u\", static_cast<unsigned int>(num));\n    }\n    static inline void VmaUint64ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint64_t num)\n    {\n        snprintf(outStr, strLen, \"%llu\", static_cast<unsigned long long>(num));\n    }\n    static inline void VmaPtrToStr(char* VMA_NOT_NULL outStr, size_t strLen, const void* ptr)\n    {\n        snprintf(outStr, strLen, \"%p\", ptr);\n    }\n#endif\n\n#ifndef VMA_MUTEX\n    class VmaMutex\n    {\n    public:\n        void Lock() { m_Mutex.lock(); }\n        void Unlock() { m_Mutex.unlock(); }\n        bool TryLock() { return m_Mutex.try_lock(); }\n    private:\n        std::mutex m_Mutex;\n    };\n    #define VMA_MUTEX VmaMutex\n#endif\n\n// Read-write mutex, where \"read\" is shared access, \"write\" is exclusive access.\n#ifndef VMA_RW_MUTEX\n    #if VMA_USE_STL_SHARED_MUTEX\n        // Use std::shared_mutex from C++17.\n        #include <shared_mutex>\n        class VmaRWMutex\n        {\n        public:\n            void LockRead() { m_Mutex.lock_shared(); }\n            void UnlockRead() { m_Mutex.unlock_shared(); }\n            bool TryLockRead() { return m_Mutex.try_lock_shared(); }\n            void LockWrite() { m_Mutex.lock(); }\n            void UnlockWrite() { m_Mutex.unlock(); }\n            bool TryLockWrite() { return m_Mutex.try_lock(); }\n        private:\n            std::shared_mutex m_Mutex;\n        };\n        #define VMA_RW_MUTEX VmaRWMutex\n    #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600\n        // Use SRWLOCK from WinAPI.\n        // Minimum supported client = Windows Vista, server = Windows Server 2008.\n        class VmaRWMutex\n        {\n        public:\n            VmaRWMutex() { InitializeSRWLock(&m_Lock); }\n            void LockRead() { AcquireSRWLockShared(&m_Lock); }\n            void UnlockRead() { ReleaseSRWLockShared(&m_Lock); }\n            bool TryLockRead() { return TryAcquireSRWLockShared(&m_Lock) != FALSE; }\n            void LockWrite() { AcquireSRWLockExclusive(&m_Lock); }\n            void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); }\n            bool TryLockWrite() { return TryAcquireSRWLockExclusive(&m_Lock) != FALSE; }\n        private:\n            SRWLOCK m_Lock;\n        };\n        #define VMA_RW_MUTEX VmaRWMutex\n    #else\n        // Less efficient fallback: Use normal mutex.\n        class VmaRWMutex\n        {\n        public:\n            void LockRead() { m_Mutex.Lock(); }\n            void UnlockRead() { m_Mutex.Unlock(); }\n            bool TryLockRead() { return m_Mutex.TryLock(); }\n            void LockWrite() { m_Mutex.Lock(); }\n            void UnlockWrite() { m_Mutex.Unlock(); }\n            bool TryLockWrite() { return m_Mutex.TryLock(); }\n        private:\n            VMA_MUTEX m_Mutex;\n        };\n        #define VMA_RW_MUTEX VmaRWMutex\n    #endif // #if VMA_USE_STL_SHARED_MUTEX\n#endif // #ifndef VMA_RW_MUTEX\n\n/*\nIf providing your own implementation, you need to implement a subset of std::atomic.\n*/\n#ifndef VMA_ATOMIC_UINT32\n    #include <atomic>\n    #define VMA_ATOMIC_UINT32 std::atomic<uint32_t>\n#endif\n\n#ifndef VMA_ATOMIC_UINT64\n    #include <atomic>\n    #define VMA_ATOMIC_UINT64 std::atomic<uint64_t>\n#endif\n\n#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY\n    /**\n    Every allocation will have its own memory block.\n    Define to 1 for debugging purposes only.\n    */\n    #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0)\n#endif\n\n#ifndef VMA_MIN_ALIGNMENT\n    /**\n    Minimum alignment of all allocations, in bytes.\n    Set to more than 1 for debugging purposes. Must be power of two.\n    */\n    #ifdef VMA_DEBUG_ALIGNMENT // Old name\n        #define VMA_MIN_ALIGNMENT VMA_DEBUG_ALIGNMENT\n    #else\n        #define VMA_MIN_ALIGNMENT (1)\n    #endif\n#endif\n\n#ifndef VMA_DEBUG_MARGIN\n    /**\n    Minimum margin after every allocation, in bytes.\n    Set nonzero for debugging purposes only.\n    */\n    #define VMA_DEBUG_MARGIN (0)\n#endif\n\n#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS\n    /**\n    Define this macro to 1 to automatically fill new allocations and destroyed\n    allocations with some bit pattern.\n    */\n    #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0)\n#endif\n\n#ifndef VMA_DEBUG_DETECT_CORRUPTION\n    /**\n    Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to\n    enable writing magic value to the margin after every allocation and\n    validating it, so that memory corruptions (out-of-bounds writes) are detected.\n    */\n    #define VMA_DEBUG_DETECT_CORRUPTION (0)\n#endif\n\n#ifndef VMA_DEBUG_GLOBAL_MUTEX\n    /**\n    Set this to 1 for debugging purposes only, to enable single mutex protecting all\n    entry calls to the library. Can be useful for debugging multithreading issues.\n    */\n    #define VMA_DEBUG_GLOBAL_MUTEX (0)\n#endif\n\n#ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY\n    /**\n    Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity.\n    Set to more than 1 for debugging purposes only. Must be power of two.\n    */\n    #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)\n#endif\n\n#ifndef VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT\n    /*\n    Set this to 1 to make VMA never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount\n    and return error instead of leaving up to Vulkan implementation what to do in such cases.\n    */\n    #define VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT (0)\n#endif\n\n#ifndef VMA_SMALL_HEAP_MAX_SIZE\n   /// Maximum size of a memory heap in Vulkan to consider it \"small\".\n   #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024)\n#endif\n\n#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE\n   /// Default size of a block allocated as single VkDeviceMemory from a \"large\" heap.\n   #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)\n#endif\n\n/*\nMapping hysteresis is a logic that launches when vmaMapMemory/vmaUnmapMemory is called\nor a persistently mapped allocation is created and destroyed several times in a row.\nIt keeps additional +1 mapping of a device memory block to prevent calling actual\nvkMapMemory/vkUnmapMemory too many times, which may improve performance and help\ntools like RenderDoc.\n*/\n#ifndef VMA_MAPPING_HYSTERESIS_ENABLED\n    #define VMA_MAPPING_HYSTERESIS_ENABLED 1\n#endif\n\n#ifndef VMA_CLASS_NO_COPY\n    #define VMA_CLASS_NO_COPY(className) \\\n        private: \\\n            className(const className&) = delete; \\\n            className& operator=(const className&) = delete;\n#endif\n\n#define VMA_VALIDATE(cond) do { if(!(cond)) { \\\n        VMA_ASSERT(0 && \"Validation failed: \" #cond); \\\n        return false; \\\n    } } while(false)\n\n/*******************************************************************************\nEND OF CONFIGURATION\n*/\n#endif // _VMA_CONFIGURATION\n\n\nstatic const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC;\nstatic const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;\n// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.\nstatic const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;\n\n// Copy of some Vulkan definitions so we don't need to check their existence just to handle few constants.\nstatic const uint32_t VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY = 0x00000040;\nstatic const uint32_t VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY = 0x00000080;\nstatic const uint32_t VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY = 0x00020000;\nstatic const uint32_t VK_IMAGE_CREATE_DISJOINT_BIT_COPY = 0x00000200;\nstatic const int32_t VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY = 1000158000;\nstatic const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u;\nstatic const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;\nstatic const uint32_t VMA_VENDOR_ID_AMD = 4098;\n\n// This one is tricky. Vulkan specification defines this code as available since\n// Vulkan 1.0, but doesn't actually define it in Vulkan SDK earlier than 1.2.131.\n// See pull request #207.\n#define VK_ERROR_UNKNOWN_COPY ((VkResult)-13)\n\n\n#if VMA_STATS_STRING_ENABLED\n// Correspond to values of enum VmaSuballocationType.\nstatic const char* VMA_SUBALLOCATION_TYPE_NAMES[] =\n{\n    \"FREE\",\n    \"UNKNOWN\",\n    \"BUFFER\",\n    \"IMAGE_UNKNOWN\",\n    \"IMAGE_LINEAR\",\n    \"IMAGE_OPTIMAL\",\n};\n#endif\n\nstatic VkAllocationCallbacks VmaEmptyAllocationCallbacks =\n    { VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };\n\n\n#ifndef _VMA_ENUM_DECLARATIONS\n\nenum VmaSuballocationType\n{\n    VMA_SUBALLOCATION_TYPE_FREE = 0,\n    VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,\n    VMA_SUBALLOCATION_TYPE_BUFFER = 2,\n    VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,\n    VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,\n    VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,\n    VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF\n};\n\nenum VMA_CACHE_OPERATION\n{\n    VMA_CACHE_FLUSH,\n    VMA_CACHE_INVALIDATE\n};\n\nenum class VmaAllocationRequestType\n{\n    Normal,\n    TLSF,\n    // Used by \"Linear\" algorithm.\n    UpperAddress,\n    EndOf1st,\n    EndOf2nd,\n};\n\n#endif // _VMA_ENUM_DECLARATIONS\n\n#ifndef _VMA_FORWARD_DECLARATIONS\n// Opaque handle used by allocation algorithms to identify single allocation in any conforming way.\nVK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaAllocHandle)\n\nstruct VmaMutexLock;\nstruct VmaMutexLockRead;\nstruct VmaMutexLockWrite;\n\ntemplate<typename T>\nstruct AtomicTransactionalIncrement;\n\ntemplate<typename T>\nstruct VmaStlAllocator;\n\ntemplate<typename T, typename AllocatorT>\nclass VmaVector;\n\ntemplate<typename T, typename AllocatorT, size_t N>\nclass VmaSmallVector;\n\ntemplate<typename T>\nclass VmaPoolAllocator;\n\ntemplate<typename T>\nstruct VmaListItem;\n\ntemplate<typename T>\nclass VmaRawList;\n\ntemplate<typename T, typename AllocatorT>\nclass VmaList;\n\ntemplate<typename ItemTypeTraits>\nclass VmaIntrusiveLinkedList;\n\n// Unused in this version\n#if 0\ntemplate<typename T1, typename T2>\nstruct VmaPair;\ntemplate<typename FirstT, typename SecondT>\nstruct VmaPairFirstLess;\n\ntemplate<typename KeyT, typename ValueT>\nclass VmaMap;\n#endif\n\n#if VMA_STATS_STRING_ENABLED\nclass VmaStringBuilder;\nclass VmaJsonWriter;\n#endif\n\nclass VmaDeviceMemoryBlock;\n\nstruct VmaDedicatedAllocationListItemTraits;\nclass VmaDedicatedAllocationList;\n\nstruct VmaSuballocation;\nstruct VmaSuballocationOffsetLess;\nstruct VmaSuballocationOffsetGreater;\nstruct VmaSuballocationItemSizeLess;\n\ntypedef VmaList<VmaSuballocation, VmaStlAllocator<VmaSuballocation>> VmaSuballocationList;\n\nstruct VmaAllocationRequest;\n\nclass VmaBlockMetadata;\nclass VmaBlockMetadata_Linear;\nclass VmaBlockMetadata_TLSF;\n\nclass VmaBlockVector;\n\nstruct VmaPoolListItemTraits;\n\nstruct VmaCurrentBudgetData;\n\nclass VmaAllocationObjectAllocator;\n\n#endif // _VMA_FORWARD_DECLARATIONS\n\n\n#ifndef _VMA_FUNCTIONS\n\n/*\nReturns number of bits set to 1 in (v).\n\nOn specific platforms and compilers you can use instrinsics like:\n\nVisual Studio:\n    return __popcnt(v);\nGCC, Clang:\n    return static_cast<uint32_t>(__builtin_popcount(v));\n\nDefine macro VMA_COUNT_BITS_SET to provide your optimized implementation.\nBut you need to check in runtime whether user's CPU supports these, as some old processors don't.\n*/\nstatic inline uint32_t VmaCountBitsSet(uint32_t v)\n{\n#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20\n    return std::popcount(v);\n#else\n    uint32_t c = v - ((v >> 1) & 0x55555555);\n    c = ((c >> 2) & 0x33333333) + (c & 0x33333333);\n    c = ((c >> 4) + c) & 0x0F0F0F0F;\n    c = ((c >> 8) + c) & 0x00FF00FF;\n    c = ((c >> 16) + c) & 0x0000FFFF;\n    return c;\n#endif\n}\n\nstatic inline uint8_t VmaBitScanLSB(uint64_t mask)\n{\n#if defined(_MSC_VER) && defined(_WIN64)\n    unsigned long pos;\n    if (_BitScanForward64(&pos, mask))\n        return static_cast<uint8_t>(pos);\n    return UINT8_MAX;\n#elif defined __GNUC__ || defined __clang__\n    return static_cast<uint8_t>(__builtin_ffsll(mask)) - 1U;\n#else\n    uint8_t pos = 0;\n    uint64_t bit = 1;\n    do\n    {\n        if (mask & bit)\n            return pos;\n        bit <<= 1;\n    } while (pos++ < 63);\n    return UINT8_MAX;\n#endif\n}\n\nstatic inline uint8_t VmaBitScanLSB(uint32_t mask)\n{\n#ifdef _MSC_VER\n    unsigned long pos;\n    if (_BitScanForward(&pos, mask))\n        return static_cast<uint8_t>(pos);\n    return UINT8_MAX;\n#elif defined __GNUC__ || defined __clang__\n    return static_cast<uint8_t>(__builtin_ffs(mask)) - 1U;\n#else\n    uint8_t pos = 0;\n    uint32_t bit = 1;\n    do\n    {\n        if (mask & bit)\n            return pos;\n        bit <<= 1;\n    } while (pos++ < 31);\n    return UINT8_MAX;\n#endif\n}\n\nstatic inline uint8_t VmaBitScanMSB(uint64_t mask)\n{\n#if defined(_MSC_VER) && defined(_WIN64)\n    unsigned long pos;\n    if (_BitScanReverse64(&pos, mask))\n        return static_cast<uint8_t>(pos);\n#elif defined __GNUC__ || defined __clang__\n    if (mask)\n        return 63 - static_cast<uint8_t>(__builtin_clzll(mask));\n#else\n    uint8_t pos = 63;\n    uint64_t bit = 1ULL << 63;\n    do\n    {\n        if (mask & bit)\n            return pos;\n        bit >>= 1;\n    } while (pos-- > 0);\n#endif\n    return UINT8_MAX;\n}\n\nstatic inline uint8_t VmaBitScanMSB(uint32_t mask)\n{\n#ifdef _MSC_VER\n    unsigned long pos;\n    if (_BitScanReverse(&pos, mask))\n        return static_cast<uint8_t>(pos);\n#elif defined __GNUC__ || defined __clang__\n    if (mask)\n        return 31 - static_cast<uint8_t>(__builtin_clz(mask));\n#else\n    uint8_t pos = 31;\n    uint32_t bit = 1UL << 31;\n    do\n    {\n        if (mask & bit)\n            return pos;\n        bit >>= 1;\n    } while (pos-- > 0);\n#endif\n    return UINT8_MAX;\n}\n\n/*\nReturns true if given number is a power of two.\nT must be unsigned integer number or signed integer but always nonnegative.\nFor 0 returns true.\n*/\ntemplate <typename T>\ninline bool VmaIsPow2(T x)\n{\n    return (x & (x - 1)) == 0;\n}\n\n// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16.\n// Use types like uint32_t, uint64_t as T.\ntemplate <typename T>\nstatic inline T VmaAlignUp(T val, T alignment)\n{\n    VMA_HEAVY_ASSERT(VmaIsPow2(alignment));\n    return (val + alignment - 1) & ~(alignment - 1);\n}\n\n// Aligns given value down to nearest multiply of align value. For example: VmaAlignDown(11, 8) = 8.\n// Use types like uint32_t, uint64_t as T.\ntemplate <typename T>\nstatic inline T VmaAlignDown(T val, T alignment)\n{\n    VMA_HEAVY_ASSERT(VmaIsPow2(alignment));\n    return val & ~(alignment - 1);\n}\n\n// Division with mathematical rounding to nearest number.\ntemplate <typename T>\nstatic inline T VmaRoundDiv(T x, T y)\n{\n    return (x + (y / (T)2)) / y;\n}\n\n// Divide by 'y' and round up to nearest integer.\ntemplate <typename T>\nstatic inline T VmaDivideRoundingUp(T x, T y)\n{\n    return (x + y - (T)1) / y;\n}\n\n// Returns smallest power of 2 greater or equal to v.\nstatic inline uint32_t VmaNextPow2(uint32_t v)\n{\n    v--;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    v++;\n    return v;\n}\n\nstatic inline uint64_t VmaNextPow2(uint64_t v)\n{\n    v--;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    v |= v >> 32;\n    v++;\n    return v;\n}\n\n// Returns largest power of 2 less or equal to v.\nstatic inline uint32_t VmaPrevPow2(uint32_t v)\n{\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    v = v ^ (v >> 1);\n    return v;\n}\n\nstatic inline uint64_t VmaPrevPow2(uint64_t v)\n{\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    v |= v >> 32;\n    v = v ^ (v >> 1);\n    return v;\n}\n\nstatic inline bool VmaStrIsEmpty(const char* pStr)\n{\n    return pStr == VMA_NULL || *pStr == '\\0';\n}\n\n/*\nReturns true if two memory blocks occupy overlapping pages.\nResourceA must be in less memory offset than ResourceB.\n\nAlgorithm is based on \"Vulkan 1.0.39 - A Specification (with all registered Vulkan extensions)\"\nchapter 11.6 \"Resource Memory Association\", paragraph \"Buffer-Image Granularity\".\n*/\nstatic inline bool VmaBlocksOnSamePage(\n    VkDeviceSize resourceAOffset,\n    VkDeviceSize resourceASize,\n    VkDeviceSize resourceBOffset,\n    VkDeviceSize pageSize)\n{\n    VMA_ASSERT(resourceAOffset + resourceASize <= resourceBOffset && resourceASize > 0 && pageSize > 0);\n    VkDeviceSize resourceAEnd = resourceAOffset + resourceASize - 1;\n    VkDeviceSize resourceAEndPage = resourceAEnd & ~(pageSize - 1);\n    VkDeviceSize resourceBStart = resourceBOffset;\n    VkDeviceSize resourceBStartPage = resourceBStart & ~(pageSize - 1);\n    return resourceAEndPage == resourceBStartPage;\n}\n\n/*\nReturns true if given suballocation types could conflict and must respect\nVkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer\nor linear image and another one is optimal image. If type is unknown, behave\nconservatively.\n*/\nstatic inline bool VmaIsBufferImageGranularityConflict(\n    VmaSuballocationType suballocType1,\n    VmaSuballocationType suballocType2)\n{\n    if (suballocType1 > suballocType2)\n    {\n        VMA_SWAP(suballocType1, suballocType2);\n    }\n\n    switch (suballocType1)\n    {\n    case VMA_SUBALLOCATION_TYPE_FREE:\n        return false;\n    case VMA_SUBALLOCATION_TYPE_UNKNOWN:\n        return true;\n    case VMA_SUBALLOCATION_TYPE_BUFFER:\n        return\n            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||\n            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;\n    case VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN:\n        return\n            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||\n            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR ||\n            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;\n    case VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR:\n        return\n            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;\n    case VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL:\n        return false;\n    default:\n        VMA_ASSERT(0);\n        return true;\n    }\n}\n\nstatic void VmaWriteMagicValue(void* pData, VkDeviceSize offset)\n{\n#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION\n    uint32_t* pDst = (uint32_t*)((char*)pData + offset);\n    const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);\n    for (size_t i = 0; i < numberCount; ++i, ++pDst)\n    {\n        *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;\n    }\n#else\n    // no-op\n#endif\n}\n\nstatic bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)\n{\n#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION\n    const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset);\n    const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);\n    for (size_t i = 0; i < numberCount; ++i, ++pSrc)\n    {\n        if (*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)\n        {\n            return false;\n        }\n    }\n#endif\n    return true;\n}\n\n/*\nFills structure with parameters of an example buffer to be used for transfers\nduring GPU memory defragmentation.\n*/\nstatic void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBufCreateInfo)\n{\n    memset(&outBufCreateInfo, 0, sizeof(outBufCreateInfo));\n    outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;\n    outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n    outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size.\n}\n\n\n/*\nPerforms binary search and returns iterator to first element that is greater or\nequal to (key), according to comparison (cmp).\n\nCmp should return true if first argument is less than second argument.\n\nReturned value is the found element, if present in the collection or place where\nnew element with value (key) should be inserted.\n*/\ntemplate <typename CmpLess, typename IterT, typename KeyT>\nstatic IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT& key, const CmpLess& cmp)\n{\n    size_t down = 0, up = (end - beg);\n    while (down < up)\n    {\n        const size_t mid = down + (up - down) / 2;  // Overflow-safe midpoint calculation\n        if (cmp(*(beg + mid), key))\n        {\n            down = mid + 1;\n        }\n        else\n        {\n            up = mid;\n        }\n    }\n    return beg + down;\n}\n\ntemplate<typename CmpLess, typename IterT, typename KeyT>\nIterT VmaBinaryFindSorted(const IterT& beg, const IterT& end, const KeyT& value, const CmpLess& cmp)\n{\n    IterT it = VmaBinaryFindFirstNotLess<CmpLess, IterT, KeyT>(\n        beg, end, value, cmp);\n    if (it == end ||\n        (!cmp(*it, value) && !cmp(value, *it)))\n    {\n        return it;\n    }\n    return end;\n}\n\n/*\nReturns true if all pointers in the array are not-null and unique.\nWarning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT.\nT must be pointer type, e.g. VmaAllocation, VmaPool.\n*/\ntemplate<typename T>\nstatic bool VmaValidatePointerArray(uint32_t count, const T* arr)\n{\n    for (uint32_t i = 0; i < count; ++i)\n    {\n        const T iPtr = arr[i];\n        if (iPtr == VMA_NULL)\n        {\n            return false;\n        }\n        for (uint32_t j = i + 1; j < count; ++j)\n        {\n            if (iPtr == arr[j])\n            {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\ntemplate<typename MainT, typename NewT>\nstatic inline void VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct)\n{\n    newStruct->pNext = mainStruct->pNext;\n    mainStruct->pNext = newStruct;\n}\n\n// This is the main algorithm that guides the selection of a memory type best for an allocation -\n// converts usage to required/preferred/not preferred flags.\nstatic bool FindMemoryPreferences(\n    bool isIntegratedGPU,\n    const VmaAllocationCreateInfo& allocCreateInfo,\n    VkFlags bufImgUsage, // VkBufferCreateInfo::usage or VkImageCreateInfo::usage. UINT32_MAX if unknown.\n    VkMemoryPropertyFlags& outRequiredFlags,\n    VkMemoryPropertyFlags& outPreferredFlags,\n    VkMemoryPropertyFlags& outNotPreferredFlags)\n{\n    outRequiredFlags = allocCreateInfo.requiredFlags;\n    outPreferredFlags = allocCreateInfo.preferredFlags;\n    outNotPreferredFlags = 0;\n\n    switch(allocCreateInfo.usage)\n    {\n    case VMA_MEMORY_USAGE_UNKNOWN:\n        break;\n    case VMA_MEMORY_USAGE_GPU_ONLY:\n        if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)\n        {\n            outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n        }\n        break;\n    case VMA_MEMORY_USAGE_CPU_ONLY:\n        outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;\n        break;\n    case VMA_MEMORY_USAGE_CPU_TO_GPU:\n        outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;\n        if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)\n        {\n            outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n        }\n        break;\n    case VMA_MEMORY_USAGE_GPU_TO_CPU:\n        outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;\n        outPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;\n        break;\n    case VMA_MEMORY_USAGE_CPU_COPY:\n        outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n        break;\n    case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED:\n        outRequiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;\n        break;\n    case VMA_MEMORY_USAGE_AUTO:\n    case VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE:\n    case VMA_MEMORY_USAGE_AUTO_PREFER_HOST:\n    {\n        if(bufImgUsage == UINT32_MAX)\n        {\n            VMA_ASSERT(0 && \"VMA_MEMORY_USAGE_AUTO* values can only be used with functions like vmaCreateBuffer, vmaCreateImage so that the details of the created resource are known.\");\n            return false;\n        }\n        // This relies on values of VK_IMAGE_USAGE_TRANSFER* being the same VK_BUFFER_IMAGE_TRANSFER*.\n        const bool deviceAccess = (bufImgUsage & ~(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) != 0;\n        const bool hostAccessSequentialWrite = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT) != 0;\n        const bool hostAccessRandom = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) != 0;\n        const bool hostAccessAllowTransferInstead = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) != 0;\n        const bool preferDevice = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;\n        const bool preferHost = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST;\n\n        // CPU random access - e.g. a buffer written to or transferred from GPU to read back on CPU.\n        if(hostAccessRandom)\n        {\n            if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost)\n            {\n                // Nice if it will end up in HOST_VISIBLE, but more importantly prefer DEVICE_LOCAL.\n                // Omitting HOST_VISIBLE here is intentional.\n                // In case there is DEVICE_LOCAL | HOST_VISIBLE | HOST_CACHED, it will pick that one.\n                // Otherwise, this will give same weight to DEVICE_LOCAL as HOST_VISIBLE | HOST_CACHED and select the former if occurs first on the list.\n                outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;\n            }\n            else\n            {\n                // Always CPU memory, cached.\n                outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;\n            }\n        }\n        // CPU sequential write - may be CPU or host-visible GPU memory, uncached and write-combined.\n        else if(hostAccessSequentialWrite)\n        {\n            // Want uncached and write-combined.\n            outNotPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;\n\n            if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost)\n            {\n                outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;\n            }\n            else\n            {\n                outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;\n                // Direct GPU access, CPU sequential write (e.g. a dynamic uniform buffer updated every frame)\n                if(deviceAccess)\n                {\n                    // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose GPU memory.\n                    if(preferHost)\n                        outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n                    else\n                        outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n                }\n                // GPU no direct access, CPU sequential write (e.g. an upload buffer to be transferred to the GPU)\n                else\n                {\n                    // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose CPU memory.\n                    if(preferDevice)\n                        outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n                    else\n                        outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n                }\n            }\n        }\n        // No CPU access\n        else\n        {\n            // GPU access, no CPU access (e.g. a color attachment image) - prefer GPU memory\n            if(deviceAccess)\n            {\n                // ...unless there is a clear preference from the user not to do so.\n                if(preferHost)\n                    outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n                else\n                    outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n            }\n            // No direct GPU access, no CPU access, just transfers.\n            // It may be staging copy intended for e.g. preserving image for next frame (then better GPU memory) or\n            // a \"swap file\" copy to free some GPU memory (then better CPU memory).\n            // Up to the user to decide. If no preferece, assume the former and choose GPU memory.\n            if(preferHost)\n                outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n            else\n                outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n        }\n        break;\n    }\n    default:\n        VMA_ASSERT(0);\n    }\n\n    // Avoid DEVICE_COHERENT unless explicitly requested.\n    if(((allocCreateInfo.requiredFlags | allocCreateInfo.preferredFlags) &\n        (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0)\n    {\n        outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY;\n    }\n\n    return true;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Memory allocation\n\nstatic void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment)\n{\n    void* result = VMA_NULL;\n    if ((pAllocationCallbacks != VMA_NULL) &&\n        (pAllocationCallbacks->pfnAllocation != VMA_NULL))\n    {\n        result = (*pAllocationCallbacks->pfnAllocation)(\n            pAllocationCallbacks->pUserData,\n            size,\n            alignment,\n            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n    }\n    else\n    {\n        result = VMA_SYSTEM_ALIGNED_MALLOC(size, alignment);\n    }\n    VMA_ASSERT(result != VMA_NULL && \"CPU memory allocation failed.\");\n    return result;\n}\n\nstatic void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr)\n{\n    if ((pAllocationCallbacks != VMA_NULL) &&\n        (pAllocationCallbacks->pfnFree != VMA_NULL))\n    {\n        (*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr);\n    }\n    else\n    {\n        VMA_SYSTEM_ALIGNED_FREE(ptr);\n    }\n}\n\ntemplate<typename T>\nstatic T* VmaAllocate(const VkAllocationCallbacks* pAllocationCallbacks)\n{\n    return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T), VMA_ALIGN_OF(T));\n}\n\ntemplate<typename T>\nstatic T* VmaAllocateArray(const VkAllocationCallbacks* pAllocationCallbacks, size_t count)\n{\n    return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T) * count, VMA_ALIGN_OF(T));\n}\n\n#define vma_new(allocator, type)   new(VmaAllocate<type>(allocator))(type)\n\n#define vma_new_array(allocator, type, count)   new(VmaAllocateArray<type>((allocator), (count)))(type)\n\ntemplate<typename T>\nstatic void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr)\n{\n    ptr->~T();\n    VmaFree(pAllocationCallbacks, ptr);\n}\n\ntemplate<typename T>\nstatic void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count)\n{\n    if (ptr != VMA_NULL)\n    {\n        for (size_t i = count; i--; )\n        {\n            ptr[i].~T();\n        }\n        VmaFree(pAllocationCallbacks, ptr);\n    }\n}\n\nstatic char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr)\n{\n    if (srcStr != VMA_NULL)\n    {\n        const size_t len = strlen(srcStr);\n        char* const result = vma_new_array(allocs, char, len + 1);\n        memcpy(result, srcStr, len + 1);\n        return result;\n    }\n    return VMA_NULL;\n}\n\n#if VMA_STATS_STRING_ENABLED\nstatic char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr, size_t strLen)\n{\n    if (srcStr != VMA_NULL)\n    {\n        char* const result = vma_new_array(allocs, char, strLen + 1);\n        memcpy(result, srcStr, strLen);\n        result[strLen] = '\\0';\n        return result;\n    }\n    return VMA_NULL;\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nstatic void VmaFreeString(const VkAllocationCallbacks* allocs, char* str)\n{\n    if (str != VMA_NULL)\n    {\n        const size_t len = strlen(str);\n        vma_delete_array(allocs, str, len + 1);\n    }\n}\n\ntemplate<typename CmpLess, typename VectorT>\nsize_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value)\n{\n    const size_t indexToInsert = VmaBinaryFindFirstNotLess(\n        vector.data(),\n        vector.data() + vector.size(),\n        value,\n        CmpLess()) - vector.data();\n    VmaVectorInsert(vector, indexToInsert, value);\n    return indexToInsert;\n}\n\ntemplate<typename CmpLess, typename VectorT>\nbool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value)\n{\n    CmpLess comparator;\n    typename VectorT::iterator it = VmaBinaryFindFirstNotLess(\n        vector.begin(),\n        vector.end(),\n        value,\n        comparator);\n    if ((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it))\n    {\n        size_t indexToRemove = it - vector.begin();\n        VmaVectorRemove(vector, indexToRemove);\n        return true;\n    }\n    return false;\n}\n#endif // _VMA_FUNCTIONS\n\n#ifndef _VMA_STATISTICS_FUNCTIONS\n\nstatic void VmaClearStatistics(VmaStatistics& outStats)\n{\n    outStats.blockCount = 0;\n    outStats.allocationCount = 0;\n    outStats.blockBytes = 0;\n    outStats.allocationBytes = 0;\n}\n\nstatic void VmaAddStatistics(VmaStatistics& inoutStats, const VmaStatistics& src)\n{\n    inoutStats.blockCount += src.blockCount;\n    inoutStats.allocationCount += src.allocationCount;\n    inoutStats.blockBytes += src.blockBytes;\n    inoutStats.allocationBytes += src.allocationBytes;\n}\n\nstatic void VmaClearDetailedStatistics(VmaDetailedStatistics& outStats)\n{\n    VmaClearStatistics(outStats.statistics);\n    outStats.unusedRangeCount = 0;\n    outStats.allocationSizeMin = VK_WHOLE_SIZE;\n    outStats.allocationSizeMax = 0;\n    outStats.unusedRangeSizeMin = VK_WHOLE_SIZE;\n    outStats.unusedRangeSizeMax = 0;\n}\n\nstatic void VmaAddDetailedStatisticsAllocation(VmaDetailedStatistics& inoutStats, VkDeviceSize size)\n{\n    inoutStats.statistics.allocationCount++;\n    inoutStats.statistics.allocationBytes += size;\n    inoutStats.allocationSizeMin = VMA_MIN(inoutStats.allocationSizeMin, size);\n    inoutStats.allocationSizeMax = VMA_MAX(inoutStats.allocationSizeMax, size);\n}\n\nstatic void VmaAddDetailedStatisticsUnusedRange(VmaDetailedStatistics& inoutStats, VkDeviceSize size)\n{\n    inoutStats.unusedRangeCount++;\n    inoutStats.unusedRangeSizeMin = VMA_MIN(inoutStats.unusedRangeSizeMin, size);\n    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, size);\n}\n\nstatic void VmaAddDetailedStatistics(VmaDetailedStatistics& inoutStats, const VmaDetailedStatistics& src)\n{\n    VmaAddStatistics(inoutStats.statistics, src.statistics);\n    inoutStats.unusedRangeCount += src.unusedRangeCount;\n    inoutStats.allocationSizeMin = VMA_MIN(inoutStats.allocationSizeMin, src.allocationSizeMin);\n    inoutStats.allocationSizeMax = VMA_MAX(inoutStats.allocationSizeMax, src.allocationSizeMax);\n    inoutStats.unusedRangeSizeMin = VMA_MIN(inoutStats.unusedRangeSizeMin, src.unusedRangeSizeMin);\n    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, src.unusedRangeSizeMax);\n}\n\n#endif // _VMA_STATISTICS_FUNCTIONS\n\n#ifndef _VMA_MUTEX_LOCK\n// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).\nstruct VmaMutexLock\n{\n    VMA_CLASS_NO_COPY(VmaMutexLock)\npublic:\n    VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) :\n        m_pMutex(useMutex ? &mutex : VMA_NULL)\n    {\n        if (m_pMutex) { m_pMutex->Lock(); }\n    }\n    ~VmaMutexLock() {  if (m_pMutex) { m_pMutex->Unlock(); } }\n\nprivate:\n    VMA_MUTEX* m_pMutex;\n};\n\n// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.\nstruct VmaMutexLockRead\n{\n    VMA_CLASS_NO_COPY(VmaMutexLockRead)\npublic:\n    VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) :\n        m_pMutex(useMutex ? &mutex : VMA_NULL)\n    {\n        if (m_pMutex) { m_pMutex->LockRead(); }\n    }\n    ~VmaMutexLockRead() { if (m_pMutex) { m_pMutex->UnlockRead(); } }\n\nprivate:\n    VMA_RW_MUTEX* m_pMutex;\n};\n\n// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.\nstruct VmaMutexLockWrite\n{\n    VMA_CLASS_NO_COPY(VmaMutexLockWrite)\npublic:\n    VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex)\n        : m_pMutex(useMutex ? &mutex : VMA_NULL)\n    {\n        if (m_pMutex) { m_pMutex->LockWrite(); }\n    }\n    ~VmaMutexLockWrite() { if (m_pMutex) { m_pMutex->UnlockWrite(); } }\n\nprivate:\n    VMA_RW_MUTEX* m_pMutex;\n};\n\n#if VMA_DEBUG_GLOBAL_MUTEX\n    static VMA_MUTEX gDebugGlobalMutex;\n    #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);\n#else\n    #define VMA_DEBUG_GLOBAL_MUTEX_LOCK\n#endif\n#endif // _VMA_MUTEX_LOCK\n\n#ifndef _VMA_ATOMIC_TRANSACTIONAL_INCREMENT\n// An object that increments given atomic but decrements it back in the destructor unless Commit() is called.\ntemplate<typename T>\nstruct AtomicTransactionalIncrement\n{\npublic:\n    typedef std::atomic<T> AtomicT;\n\n    ~AtomicTransactionalIncrement()\n    {\n        if(m_Atomic)\n            --(*m_Atomic);\n    }\n\n    void Commit() { m_Atomic = nullptr; }\n    T Increment(AtomicT* atomic)\n    {\n        m_Atomic = atomic;\n        return m_Atomic->fetch_add(1);\n    }\n\nprivate:\n    AtomicT* m_Atomic = nullptr;\n};\n#endif // _VMA_ATOMIC_TRANSACTIONAL_INCREMENT\n\n#ifndef _VMA_STL_ALLOCATOR\n// STL-compatible allocator.\ntemplate<typename T>\nstruct VmaStlAllocator\n{\n    const VkAllocationCallbacks* const m_pCallbacks;\n    typedef T value_type;\n\n    VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) {}\n    template<typename U>\n    VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) {}\n    VmaStlAllocator(const VmaStlAllocator&) = default;\n    VmaStlAllocator& operator=(const VmaStlAllocator&) = delete;\n\n    T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }\n    void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); }\n\n    template<typename U>\n    bool operator==(const VmaStlAllocator<U>& rhs) const\n    {\n        return m_pCallbacks == rhs.m_pCallbacks;\n    }\n    template<typename U>\n    bool operator!=(const VmaStlAllocator<U>& rhs) const\n    {\n        return m_pCallbacks != rhs.m_pCallbacks;\n    }\n};\n#endif // _VMA_STL_ALLOCATOR\n\n#ifndef _VMA_VECTOR\n/* Class with interface compatible with subset of std::vector.\nT must be POD because constructors and destructors are not called and memcpy is\nused for these objects. */\ntemplate<typename T, typename AllocatorT>\nclass VmaVector\n{\npublic:\n    typedef T value_type;\n    typedef T* iterator;\n    typedef const T* const_iterator;\n\n    VmaVector(const AllocatorT& allocator);\n    VmaVector(size_t count, const AllocatorT& allocator);\n    // This version of the constructor is here for compatibility with pre-C++14 std::vector.\n    // value is unused.\n    VmaVector(size_t count, const T& value, const AllocatorT& allocator) : VmaVector(count, allocator) {}\n    VmaVector(const VmaVector<T, AllocatorT>& src);\n    VmaVector& operator=(const VmaVector& rhs);\n    ~VmaVector() { VmaFree(m_Allocator.m_pCallbacks, m_pArray); }\n\n    bool empty() const { return m_Count == 0; }\n    size_t size() const { return m_Count; }\n    T* data() { return m_pArray; }\n    T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; }\n    T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; }\n    const T* data() const { return m_pArray; }\n    const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; }\n    const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; }\n\n    iterator begin() { return m_pArray; }\n    iterator end() { return m_pArray + m_Count; }\n    const_iterator cbegin() const { return m_pArray; }\n    const_iterator cend() const { return m_pArray + m_Count; }\n    const_iterator begin() const { return cbegin(); }\n    const_iterator end() const { return cend(); }\n\n    void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); }\n    void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); }\n    void push_front(const T& src) { insert(0, src); }\n\n    void push_back(const T& src);\n    void reserve(size_t newCapacity, bool freeMemory = false);\n    void resize(size_t newCount);\n    void clear() { resize(0); }\n    void shrink_to_fit();\n    void insert(size_t index, const T& src);\n    void remove(size_t index);\n\n    T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; }\n    const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; }\n\nprivate:\n    AllocatorT m_Allocator;\n    T* m_pArray;\n    size_t m_Count;\n    size_t m_Capacity;\n};\n\n#ifndef _VMA_VECTOR_FUNCTIONS\ntemplate<typename T, typename AllocatorT>\nVmaVector<T, AllocatorT>::VmaVector(const AllocatorT& allocator)\n    : m_Allocator(allocator),\n    m_pArray(VMA_NULL),\n    m_Count(0),\n    m_Capacity(0) {}\n\ntemplate<typename T, typename AllocatorT>\nVmaVector<T, AllocatorT>::VmaVector(size_t count, const AllocatorT& allocator)\n    : m_Allocator(allocator),\n    m_pArray(count ? (T*)VmaAllocateArray<T>(allocator.m_pCallbacks, count) : VMA_NULL),\n    m_Count(count),\n    m_Capacity(count) {}\n\ntemplate<typename T, typename AllocatorT>\nVmaVector<T, AllocatorT>::VmaVector(const VmaVector& src)\n    : m_Allocator(src.m_Allocator),\n    m_pArray(src.m_Count ? (T*)VmaAllocateArray<T>(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),\n    m_Count(src.m_Count),\n    m_Capacity(src.m_Count)\n{\n    if (m_Count != 0)\n    {\n        memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T));\n    }\n}\n\ntemplate<typename T, typename AllocatorT>\nVmaVector<T, AllocatorT>& VmaVector<T, AllocatorT>::operator=(const VmaVector& rhs)\n{\n    if (&rhs != this)\n    {\n        resize(rhs.m_Count);\n        if (m_Count != 0)\n        {\n            memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T));\n        }\n    }\n    return *this;\n}\n\ntemplate<typename T, typename AllocatorT>\nvoid VmaVector<T, AllocatorT>::push_back(const T& src)\n{\n    const size_t newIndex = size();\n    resize(newIndex + 1);\n    m_pArray[newIndex] = src;\n}\n\ntemplate<typename T, typename AllocatorT>\nvoid VmaVector<T, AllocatorT>::reserve(size_t newCapacity, bool freeMemory)\n{\n    newCapacity = VMA_MAX(newCapacity, m_Count);\n\n    if ((newCapacity < m_Capacity) && !freeMemory)\n    {\n        newCapacity = m_Capacity;\n    }\n\n    if (newCapacity != m_Capacity)\n    {\n        T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator, newCapacity) : VMA_NULL;\n        if (m_Count != 0)\n        {\n            memcpy(newArray, m_pArray, m_Count * sizeof(T));\n        }\n        VmaFree(m_Allocator.m_pCallbacks, m_pArray);\n        m_Capacity = newCapacity;\n        m_pArray = newArray;\n    }\n}\n\ntemplate<typename T, typename AllocatorT>\nvoid VmaVector<T, AllocatorT>::resize(size_t newCount)\n{\n    size_t newCapacity = m_Capacity;\n    if (newCount > m_Capacity)\n    {\n        newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8));\n    }\n\n    if (newCapacity != m_Capacity)\n    {\n        T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;\n        const size_t elementsToCopy = VMA_MIN(m_Count, newCount);\n        if (elementsToCopy != 0)\n        {\n            memcpy(newArray, m_pArray, elementsToCopy * sizeof(T));\n        }\n        VmaFree(m_Allocator.m_pCallbacks, m_pArray);\n        m_Capacity = newCapacity;\n        m_pArray = newArray;\n    }\n\n    m_Count = newCount;\n}\n\ntemplate<typename T, typename AllocatorT>\nvoid VmaVector<T, AllocatorT>::shrink_to_fit()\n{\n    if (m_Capacity > m_Count)\n    {\n        T* newArray = VMA_NULL;\n        if (m_Count > 0)\n        {\n            newArray = VmaAllocateArray<T>(m_Allocator.m_pCallbacks, m_Count);\n            memcpy(newArray, m_pArray, m_Count * sizeof(T));\n        }\n        VmaFree(m_Allocator.m_pCallbacks, m_pArray);\n        m_Capacity = m_Count;\n        m_pArray = newArray;\n    }\n}\n\ntemplate<typename T, typename AllocatorT>\nvoid VmaVector<T, AllocatorT>::insert(size_t index, const T& src)\n{\n    VMA_HEAVY_ASSERT(index <= m_Count);\n    const size_t oldCount = size();\n    resize(oldCount + 1);\n    if (index < oldCount)\n    {\n        memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T));\n    }\n    m_pArray[index] = src;\n}\n\ntemplate<typename T, typename AllocatorT>\nvoid VmaVector<T, AllocatorT>::remove(size_t index)\n{\n    VMA_HEAVY_ASSERT(index < m_Count);\n    const size_t oldCount = size();\n    if (index < oldCount - 1)\n    {\n        memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T));\n    }\n    resize(oldCount - 1);\n}\n#endif // _VMA_VECTOR_FUNCTIONS\n\ntemplate<typename T, typename allocatorT>\nstatic void VmaVectorInsert(VmaVector<T, allocatorT>& vec, size_t index, const T& item)\n{\n    vec.insert(index, item);\n}\n\ntemplate<typename T, typename allocatorT>\nstatic void VmaVectorRemove(VmaVector<T, allocatorT>& vec, size_t index)\n{\n    vec.remove(index);\n}\n#endif // _VMA_VECTOR\n\n#ifndef _VMA_SMALL_VECTOR\n/*\nThis is a vector (a variable-sized array), optimized for the case when the array is small.\n\nIt contains some number of elements in-place, which allows it to avoid heap allocation\nwhen the actual number of elements is below that threshold. This allows normal \"small\"\ncases to be fast without losing generality for large inputs.\n*/\ntemplate<typename T, typename AllocatorT, size_t N>\nclass VmaSmallVector\n{\npublic:\n    typedef T value_type;\n    typedef T* iterator;\n\n    VmaSmallVector(const AllocatorT& allocator);\n    VmaSmallVector(size_t count, const AllocatorT& allocator);\n    template<typename SrcT, typename SrcAllocatorT, size_t SrcN>\n    VmaSmallVector(const VmaSmallVector<SrcT, SrcAllocatorT, SrcN>&) = delete;\n    template<typename SrcT, typename SrcAllocatorT, size_t SrcN>\n    VmaSmallVector<T, AllocatorT, N>& operator=(const VmaSmallVector<SrcT, SrcAllocatorT, SrcN>&) = delete;\n    ~VmaSmallVector() = default;\n\n    bool empty() const { return m_Count == 0; }\n    size_t size() const { return m_Count; }\n    T* data() { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; }\n    T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; }\n    T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; }\n    const T* data() const { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; }\n    const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; }\n    const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; }\n\n    iterator begin() { return data(); }\n    iterator end() { return data() + m_Count; }\n\n    void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); }\n    void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); }\n    void push_front(const T& src) { insert(0, src); }\n\n    void push_back(const T& src);\n    void resize(size_t newCount, bool freeMemory = false);\n    void clear(bool freeMemory = false);\n    void insert(size_t index, const T& src);\n    void remove(size_t index);\n\n    T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; }\n    const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; }\n\nprivate:\n    size_t m_Count;\n    T m_StaticArray[N]; // Used when m_Size <= N\n    VmaVector<T, AllocatorT> m_DynamicArray; // Used when m_Size > N\n};\n\n#ifndef _VMA_SMALL_VECTOR_FUNCTIONS\ntemplate<typename T, typename AllocatorT, size_t N>\nVmaSmallVector<T, AllocatorT, N>::VmaSmallVector(const AllocatorT& allocator)\n    : m_Count(0),\n    m_DynamicArray(allocator) {}\n\ntemplate<typename T, typename AllocatorT, size_t N>\nVmaSmallVector<T, AllocatorT, N>::VmaSmallVector(size_t count, const AllocatorT& allocator)\n    : m_Count(count),\n    m_DynamicArray(count > N ? count : 0, allocator) {}\n\ntemplate<typename T, typename AllocatorT, size_t N>\nvoid VmaSmallVector<T, AllocatorT, N>::push_back(const T& src)\n{\n    const size_t newIndex = size();\n    resize(newIndex + 1);\n    data()[newIndex] = src;\n}\n\ntemplate<typename T, typename AllocatorT, size_t N>\nvoid VmaSmallVector<T, AllocatorT, N>::resize(size_t newCount, bool freeMemory)\n{\n    if (newCount > N && m_Count > N)\n    {\n        // Any direction, staying in m_DynamicArray\n        m_DynamicArray.resize(newCount);\n        if (freeMemory)\n        {\n            m_DynamicArray.shrink_to_fit();\n        }\n    }\n    else if (newCount > N && m_Count <= N)\n    {\n        // Growing, moving from m_StaticArray to m_DynamicArray\n        m_DynamicArray.resize(newCount);\n        if (m_Count > 0)\n        {\n            memcpy(m_DynamicArray.data(), m_StaticArray, m_Count * sizeof(T));\n        }\n    }\n    else if (newCount <= N && m_Count > N)\n    {\n        // Shrinking, moving from m_DynamicArray to m_StaticArray\n        if (newCount > 0)\n        {\n            memcpy(m_StaticArray, m_DynamicArray.data(), newCount * sizeof(T));\n        }\n        m_DynamicArray.resize(0);\n        if (freeMemory)\n        {\n            m_DynamicArray.shrink_to_fit();\n        }\n    }\n    else\n    {\n        // Any direction, staying in m_StaticArray - nothing to do here\n    }\n    m_Count = newCount;\n}\n\ntemplate<typename T, typename AllocatorT, size_t N>\nvoid VmaSmallVector<T, AllocatorT, N>::clear(bool freeMemory)\n{\n    m_DynamicArray.clear();\n    if (freeMemory)\n    {\n        m_DynamicArray.shrink_to_fit();\n    }\n    m_Count = 0;\n}\n\ntemplate<typename T, typename AllocatorT, size_t N>\nvoid VmaSmallVector<T, AllocatorT, N>::insert(size_t index, const T& src)\n{\n    VMA_HEAVY_ASSERT(index <= m_Count);\n    const size_t oldCount = size();\n    resize(oldCount + 1);\n    T* const dataPtr = data();\n    if (index < oldCount)\n    {\n        //  I know, this could be more optimal for case where memmove can be memcpy directly from m_StaticArray to m_DynamicArray.\n        memmove(dataPtr + (index + 1), dataPtr + index, (oldCount - index) * sizeof(T));\n    }\n    dataPtr[index] = src;\n}\n\ntemplate<typename T, typename AllocatorT, size_t N>\nvoid VmaSmallVector<T, AllocatorT, N>::remove(size_t index)\n{\n    VMA_HEAVY_ASSERT(index < m_Count);\n    const size_t oldCount = size();\n    if (index < oldCount - 1)\n    {\n        //  I know, this could be more optimal for case where memmove can be memcpy directly from m_DynamicArray to m_StaticArray.\n        T* const dataPtr = data();\n        memmove(dataPtr + index, dataPtr + (index + 1), (oldCount - index - 1) * sizeof(T));\n    }\n    resize(oldCount - 1);\n}\n#endif // _VMA_SMALL_VECTOR_FUNCTIONS\n#endif // _VMA_SMALL_VECTOR\n\n#ifndef _VMA_POOL_ALLOCATOR\n/*\nAllocator for objects of type T using a list of arrays (pools) to speed up\nallocation. Number of elements that can be allocated is not bounded because\nallocator can create multiple blocks.\n*/\ntemplate<typename T>\nclass VmaPoolAllocator\n{\n    VMA_CLASS_NO_COPY(VmaPoolAllocator)\npublic:\n    VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity);\n    ~VmaPoolAllocator();\n    template<typename... Types> T* Alloc(Types&&... args);\n    void Free(T* ptr);\n\nprivate:\n    union Item\n    {\n        uint32_t NextFreeIndex;\n        alignas(T) char Value[sizeof(T)];\n    };\n    struct ItemBlock\n    {\n        Item* pItems;\n        uint32_t Capacity;\n        uint32_t FirstFreeIndex;\n    };\n\n    const VkAllocationCallbacks* m_pAllocationCallbacks;\n    const uint32_t m_FirstBlockCapacity;\n    VmaVector<ItemBlock, VmaStlAllocator<ItemBlock>> m_ItemBlocks;\n\n    ItemBlock& CreateNewBlock();\n};\n\n#ifndef _VMA_POOL_ALLOCATOR_FUNCTIONS\ntemplate<typename T>\nVmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity)\n    : m_pAllocationCallbacks(pAllocationCallbacks),\n    m_FirstBlockCapacity(firstBlockCapacity),\n    m_ItemBlocks(VmaStlAllocator<ItemBlock>(pAllocationCallbacks))\n{\n    VMA_ASSERT(m_FirstBlockCapacity > 1);\n}\n\ntemplate<typename T>\nVmaPoolAllocator<T>::~VmaPoolAllocator()\n{\n    for (size_t i = m_ItemBlocks.size(); i--;)\n        vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity);\n    m_ItemBlocks.clear();\n}\n\ntemplate<typename T>\ntemplate<typename... Types> T* VmaPoolAllocator<T>::Alloc(Types&&... args)\n{\n    for (size_t i = m_ItemBlocks.size(); i--; )\n    {\n        ItemBlock& block = m_ItemBlocks[i];\n        // This block has some free items: Use first one.\n        if (block.FirstFreeIndex != UINT32_MAX)\n        {\n            Item* const pItem = &block.pItems[block.FirstFreeIndex];\n            block.FirstFreeIndex = pItem->NextFreeIndex;\n            T* result = (T*)&pItem->Value;\n            new(result)T(std::forward<Types>(args)...); // Explicit constructor call.\n            return result;\n        }\n    }\n\n    // No block has free item: Create new one and use it.\n    ItemBlock& newBlock = CreateNewBlock();\n    Item* const pItem = &newBlock.pItems[0];\n    newBlock.FirstFreeIndex = pItem->NextFreeIndex;\n    T* result = (T*)&pItem->Value;\n    new(result) T(std::forward<Types>(args)...); // Explicit constructor call.\n    return result;\n}\n\ntemplate<typename T>\nvoid VmaPoolAllocator<T>::Free(T* ptr)\n{\n    // Search all memory blocks to find ptr.\n    for (size_t i = m_ItemBlocks.size(); i--; )\n    {\n        ItemBlock& block = m_ItemBlocks[i];\n\n        // Casting to union.\n        Item* pItemPtr;\n        memcpy(&pItemPtr, &ptr, sizeof(pItemPtr));\n\n        // Check if pItemPtr is in address range of this block.\n        if ((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity))\n        {\n            ptr->~T(); // Explicit destructor call.\n            const uint32_t index = static_cast<uint32_t>(pItemPtr - block.pItems);\n            pItemPtr->NextFreeIndex = block.FirstFreeIndex;\n            block.FirstFreeIndex = index;\n            return;\n        }\n    }\n    VMA_ASSERT(0 && \"Pointer doesn't belong to this memory pool.\");\n}\n\ntemplate<typename T>\ntypename VmaPoolAllocator<T>::ItemBlock& VmaPoolAllocator<T>::CreateNewBlock()\n{\n    const uint32_t newBlockCapacity = m_ItemBlocks.empty() ?\n        m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2;\n\n    const ItemBlock newBlock =\n    {\n        vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity),\n        newBlockCapacity,\n        0\n    };\n\n    m_ItemBlocks.push_back(newBlock);\n\n    // Setup singly-linked list of all free items in this block.\n    for (uint32_t i = 0; i < newBlockCapacity - 1; ++i)\n        newBlock.pItems[i].NextFreeIndex = i + 1;\n    newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX;\n    return m_ItemBlocks.back();\n}\n#endif // _VMA_POOL_ALLOCATOR_FUNCTIONS\n#endif // _VMA_POOL_ALLOCATOR\n\n#ifndef _VMA_RAW_LIST\ntemplate<typename T>\nstruct VmaListItem\n{\n    VmaListItem* pPrev;\n    VmaListItem* pNext;\n    T Value;\n};\n\n// Doubly linked list.\ntemplate<typename T>\nclass VmaRawList\n{\n    VMA_CLASS_NO_COPY(VmaRawList)\npublic:\n    typedef VmaListItem<T> ItemType;\n\n    VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks);\n    // Intentionally not calling Clear, because that would be unnecessary\n    // computations to return all items to m_ItemAllocator as free.\n    ~VmaRawList() = default;\n\n    size_t GetCount() const { return m_Count; }\n    bool IsEmpty() const { return m_Count == 0; }\n\n    ItemType* Front() { return m_pFront; }\n    ItemType* Back() { return m_pBack; }\n    const ItemType* Front() const { return m_pFront; }\n    const ItemType* Back() const { return m_pBack; }\n\n    ItemType* PushFront();\n    ItemType* PushBack();\n    ItemType* PushFront(const T& value);\n    ItemType* PushBack(const T& value);\n    void PopFront();\n    void PopBack();\n\n    // Item can be null - it means PushBack.\n    ItemType* InsertBefore(ItemType* pItem);\n    // Item can be null - it means PushFront.\n    ItemType* InsertAfter(ItemType* pItem);\n    ItemType* InsertBefore(ItemType* pItem, const T& value);\n    ItemType* InsertAfter(ItemType* pItem, const T& value);\n\n    void Clear();\n    void Remove(ItemType* pItem);\n\nprivate:\n    const VkAllocationCallbacks* const m_pAllocationCallbacks;\n    VmaPoolAllocator<ItemType> m_ItemAllocator;\n    ItemType* m_pFront;\n    ItemType* m_pBack;\n    size_t m_Count;\n};\n\n#ifndef _VMA_RAW_LIST_FUNCTIONS\ntemplate<typename T>\nVmaRawList<T>::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks)\n    : m_pAllocationCallbacks(pAllocationCallbacks),\n    m_ItemAllocator(pAllocationCallbacks, 128),\n    m_pFront(VMA_NULL),\n    m_pBack(VMA_NULL),\n    m_Count(0) {}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::PushFront()\n{\n    ItemType* const pNewItem = m_ItemAllocator.Alloc();\n    pNewItem->pPrev = VMA_NULL;\n    if (IsEmpty())\n    {\n        pNewItem->pNext = VMA_NULL;\n        m_pFront = pNewItem;\n        m_pBack = pNewItem;\n        m_Count = 1;\n    }\n    else\n    {\n        pNewItem->pNext = m_pFront;\n        m_pFront->pPrev = pNewItem;\n        m_pFront = pNewItem;\n        ++m_Count;\n    }\n    return pNewItem;\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::PushBack()\n{\n    ItemType* const pNewItem = m_ItemAllocator.Alloc();\n    pNewItem->pNext = VMA_NULL;\n    if(IsEmpty())\n    {\n        pNewItem->pPrev = VMA_NULL;\n        m_pFront = pNewItem;\n        m_pBack = pNewItem;\n        m_Count = 1;\n    }\n    else\n    {\n        pNewItem->pPrev = m_pBack;\n        m_pBack->pNext = pNewItem;\n        m_pBack = pNewItem;\n        ++m_Count;\n    }\n    return pNewItem;\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::PushFront(const T& value)\n{\n    ItemType* const pNewItem = PushFront();\n    pNewItem->Value = value;\n    return pNewItem;\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::PushBack(const T& value)\n{\n    ItemType* const pNewItem = PushBack();\n    pNewItem->Value = value;\n    return pNewItem;\n}\n\ntemplate<typename T>\nvoid VmaRawList<T>::PopFront()\n{\n    VMA_HEAVY_ASSERT(m_Count > 0);\n    ItemType* const pFrontItem = m_pFront;\n    ItemType* const pNextItem = pFrontItem->pNext;\n    if (pNextItem != VMA_NULL)\n    {\n        pNextItem->pPrev = VMA_NULL;\n    }\n    m_pFront = pNextItem;\n    m_ItemAllocator.Free(pFrontItem);\n    --m_Count;\n}\n\ntemplate<typename T>\nvoid VmaRawList<T>::PopBack()\n{\n    VMA_HEAVY_ASSERT(m_Count > 0);\n    ItemType* const pBackItem = m_pBack;\n    ItemType* const pPrevItem = pBackItem->pPrev;\n    if(pPrevItem != VMA_NULL)\n    {\n        pPrevItem->pNext = VMA_NULL;\n    }\n    m_pBack = pPrevItem;\n    m_ItemAllocator.Free(pBackItem);\n    --m_Count;\n}\n\ntemplate<typename T>\nvoid VmaRawList<T>::Clear()\n{\n    if (IsEmpty() == false)\n    {\n        ItemType* pItem = m_pBack;\n        while (pItem != VMA_NULL)\n        {\n            ItemType* const pPrevItem = pItem->pPrev;\n            m_ItemAllocator.Free(pItem);\n            pItem = pPrevItem;\n        }\n        m_pFront = VMA_NULL;\n        m_pBack = VMA_NULL;\n        m_Count = 0;\n    }\n}\n\ntemplate<typename T>\nvoid VmaRawList<T>::Remove(ItemType* pItem)\n{\n    VMA_HEAVY_ASSERT(pItem != VMA_NULL);\n    VMA_HEAVY_ASSERT(m_Count > 0);\n\n    if(pItem->pPrev != VMA_NULL)\n    {\n        pItem->pPrev->pNext = pItem->pNext;\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(m_pFront == pItem);\n        m_pFront = pItem->pNext;\n    }\n\n    if(pItem->pNext != VMA_NULL)\n    {\n        pItem->pNext->pPrev = pItem->pPrev;\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(m_pBack == pItem);\n        m_pBack = pItem->pPrev;\n    }\n\n    m_ItemAllocator.Free(pItem);\n    --m_Count;\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem)\n{\n    if(pItem != VMA_NULL)\n    {\n        ItemType* const prevItem = pItem->pPrev;\n        ItemType* const newItem = m_ItemAllocator.Alloc();\n        newItem->pPrev = prevItem;\n        newItem->pNext = pItem;\n        pItem->pPrev = newItem;\n        if(prevItem != VMA_NULL)\n        {\n            prevItem->pNext = newItem;\n        }\n        else\n        {\n            VMA_HEAVY_ASSERT(m_pFront == pItem);\n            m_pFront = newItem;\n        }\n        ++m_Count;\n        return newItem;\n    }\n    else\n        return PushBack();\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem)\n{\n    if(pItem != VMA_NULL)\n    {\n        ItemType* const nextItem = pItem->pNext;\n        ItemType* const newItem = m_ItemAllocator.Alloc();\n        newItem->pNext = nextItem;\n        newItem->pPrev = pItem;\n        pItem->pNext = newItem;\n        if(nextItem != VMA_NULL)\n        {\n            nextItem->pPrev = newItem;\n        }\n        else\n        {\n            VMA_HEAVY_ASSERT(m_pBack == pItem);\n            m_pBack = newItem;\n        }\n        ++m_Count;\n        return newItem;\n    }\n    else\n        return PushFront();\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem, const T& value)\n{\n    ItemType* const newItem = InsertBefore(pItem);\n    newItem->Value = value;\n    return newItem;\n}\n\ntemplate<typename T>\nVmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem, const T& value)\n{\n    ItemType* const newItem = InsertAfter(pItem);\n    newItem->Value = value;\n    return newItem;\n}\n#endif // _VMA_RAW_LIST_FUNCTIONS\n#endif // _VMA_RAW_LIST\n\n#ifndef _VMA_LIST\ntemplate<typename T, typename AllocatorT>\nclass VmaList\n{\n    VMA_CLASS_NO_COPY(VmaList)\npublic:\n    class reverse_iterator;\n    class const_iterator;\n    class const_reverse_iterator;\n\n    class iterator\n    {\n        friend class const_iterator;\n        friend class VmaList<T, AllocatorT>;\n    public:\n        iterator() :  m_pList(VMA_NULL), m_pItem(VMA_NULL) {}\n        iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}\n\n        T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }\n        T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }\n\n        bool operator==(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }\n        bool operator!=(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }\n\n        iterator operator++(int) { iterator result = *this; ++*this; return result; }\n        iterator operator--(int) { iterator result = *this; --*this; return result; }\n\n        iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; }\n        iterator& operator--();\n\n    private:\n        VmaRawList<T>* m_pList;\n        VmaListItem<T>* m_pItem;\n\n        iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) : m_pList(pList),  m_pItem(pItem) {}\n    };\n    class reverse_iterator\n    {\n        friend class const_reverse_iterator;\n        friend class VmaList<T, AllocatorT>;\n    public:\n        reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}\n        reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}\n\n        T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }\n        T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }\n\n        bool operator==(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }\n        bool operator!=(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }\n\n        reverse_iterator operator++(int) { reverse_iterator result = *this; ++* this; return result; }\n        reverse_iterator operator--(int) { reverse_iterator result = *this; --* this; return result; }\n\n        reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; }\n        reverse_iterator& operator--();\n\n    private:\n        VmaRawList<T>* m_pList;\n        VmaListItem<T>* m_pItem;\n\n        reverse_iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) : m_pList(pList),  m_pItem(pItem) {}\n    };\n    class const_iterator\n    {\n        friend class VmaList<T, AllocatorT>;\n    public:\n        const_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}\n        const_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}\n        const_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}\n\n        iterator drop_const() { return { const_cast<VmaRawList<T>*>(m_pList), const_cast<VmaListItem<T>*>(m_pItem) }; }\n\n        const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }\n        const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }\n\n        bool operator==(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }\n        bool operator!=(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }\n\n        const_iterator operator++(int) { const_iterator result = *this; ++* this; return result; }\n        const_iterator operator--(int) { const_iterator result = *this; --* this; return result; }\n\n        const_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; }\n        const_iterator& operator--();\n\n    private:\n        const VmaRawList<T>* m_pList;\n        const VmaListItem<T>* m_pItem;\n\n        const_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) : m_pList(pList), m_pItem(pItem) {}\n    };\n    class const_reverse_iterator\n    {\n        friend class VmaList<T, AllocatorT>;\n    public:\n        const_reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}\n        const_reverse_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}\n        const_reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}\n\n        reverse_iterator drop_const() { return { const_cast<VmaRawList<T>*>(m_pList), const_cast<VmaListItem<T>*>(m_pItem) }; }\n\n        const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }\n        const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }\n\n        bool operator==(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }\n        bool operator!=(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }\n\n        const_reverse_iterator operator++(int) { const_reverse_iterator result = *this; ++* this; return result; }\n        const_reverse_iterator operator--(int) { const_reverse_iterator result = *this; --* this; return result; }\n\n        const_reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; }\n        const_reverse_iterator& operator--();\n\n    private:\n        const VmaRawList<T>* m_pList;\n        const VmaListItem<T>* m_pItem;\n\n        const_reverse_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) : m_pList(pList), m_pItem(pItem) {}\n    };\n\n    VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) {}\n\n    bool empty() const { return m_RawList.IsEmpty(); }\n    size_t size() const { return m_RawList.GetCount(); }\n\n    iterator begin() { return iterator(&m_RawList, m_RawList.Front()); }\n    iterator end() { return iterator(&m_RawList, VMA_NULL); }\n\n    const_iterator cbegin() const { return const_iterator(&m_RawList, m_RawList.Front()); }\n    const_iterator cend() const { return const_iterator(&m_RawList, VMA_NULL); }\n\n    const_iterator begin() const { return cbegin(); }\n    const_iterator end() const { return cend(); }\n\n    reverse_iterator rbegin() { return reverse_iterator(&m_RawList, m_RawList.Back()); }\n    reverse_iterator rend() { return reverse_iterator(&m_RawList, VMA_NULL); }\n\n    const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_RawList, m_RawList.Back()); }\n    const_reverse_iterator crend() const { return const_reverse_iterator(&m_RawList, VMA_NULL); }\n\n    const_reverse_iterator rbegin() const { return crbegin(); }\n    const_reverse_iterator rend() const { return crend(); }\n\n    void push_back(const T& value) { m_RawList.PushBack(value); }\n    iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); }\n\n    void clear() { m_RawList.Clear(); }\n    void erase(iterator it) { m_RawList.Remove(it.m_pItem); }\n\nprivate:\n    VmaRawList<T> m_RawList;\n};\n\n#ifndef _VMA_LIST_FUNCTIONS\ntemplate<typename T, typename AllocatorT>\ntypename VmaList<T, AllocatorT>::iterator& VmaList<T, AllocatorT>::iterator::operator--()\n{\n    if (m_pItem != VMA_NULL)\n    {\n        m_pItem = m_pItem->pPrev;\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(!m_pList->IsEmpty());\n        m_pItem = m_pList->Back();\n    }\n    return *this;\n}\n\ntemplate<typename T, typename AllocatorT>\ntypename VmaList<T, AllocatorT>::reverse_iterator& VmaList<T, AllocatorT>::reverse_iterator::operator--()\n{\n    if (m_pItem != VMA_NULL)\n    {\n        m_pItem = m_pItem->pNext;\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(!m_pList->IsEmpty());\n        m_pItem = m_pList->Front();\n    }\n    return *this;\n}\n\ntemplate<typename T, typename AllocatorT>\ntypename VmaList<T, AllocatorT>::const_iterator& VmaList<T, AllocatorT>::const_iterator::operator--()\n{\n    if (m_pItem != VMA_NULL)\n    {\n        m_pItem = m_pItem->pPrev;\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(!m_pList->IsEmpty());\n        m_pItem = m_pList->Back();\n    }\n    return *this;\n}\n\ntemplate<typename T, typename AllocatorT>\ntypename VmaList<T, AllocatorT>::const_reverse_iterator& VmaList<T, AllocatorT>::const_reverse_iterator::operator--()\n{\n    if (m_pItem != VMA_NULL)\n    {\n        m_pItem = m_pItem->pNext;\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(!m_pList->IsEmpty());\n        m_pItem = m_pList->Back();\n    }\n    return *this;\n}\n#endif // _VMA_LIST_FUNCTIONS\n#endif // _VMA_LIST\n\n#ifndef _VMA_INTRUSIVE_LINKED_LIST\n/*\nExpected interface of ItemTypeTraits:\nstruct MyItemTypeTraits\n{\n    typedef MyItem ItemType;\n    static ItemType* GetPrev(const ItemType* item) { return item->myPrevPtr; }\n    static ItemType* GetNext(const ItemType* item) { return item->myNextPtr; }\n    static ItemType*& AccessPrev(ItemType* item) { return item->myPrevPtr; }\n    static ItemType*& AccessNext(ItemType* item) { return item->myNextPtr; }\n};\n*/\ntemplate<typename ItemTypeTraits>\nclass VmaIntrusiveLinkedList\n{\npublic:\n    typedef typename ItemTypeTraits::ItemType ItemType;\n    static ItemType* GetPrev(const ItemType* item) { return ItemTypeTraits::GetPrev(item); }\n    static ItemType* GetNext(const ItemType* item) { return ItemTypeTraits::GetNext(item); }\n\n    // Movable, not copyable.\n    VmaIntrusiveLinkedList() = default;\n    VmaIntrusiveLinkedList(VmaIntrusiveLinkedList && src);\n    VmaIntrusiveLinkedList(const VmaIntrusiveLinkedList&) = delete;\n    VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src);\n    VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete;\n    ~VmaIntrusiveLinkedList() { VMA_HEAVY_ASSERT(IsEmpty()); }\n\n    size_t GetCount() const { return m_Count; }\n    bool IsEmpty() const { return m_Count == 0; }\n    ItemType* Front() { return m_Front; }\n    ItemType* Back() { return m_Back; }\n    const ItemType* Front() const { return m_Front; }\n    const ItemType* Back() const { return m_Back; }\n\n    void PushBack(ItemType* item);\n    void PushFront(ItemType* item);\n    ItemType* PopBack();\n    ItemType* PopFront();\n\n    // MyItem can be null - it means PushBack.\n    void InsertBefore(ItemType* existingItem, ItemType* newItem);\n    // MyItem can be null - it means PushFront.\n    void InsertAfter(ItemType* existingItem, ItemType* newItem);\n    void Remove(ItemType* item);\n    void RemoveAll();\n\nprivate:\n    ItemType* m_Front = VMA_NULL;\n    ItemType* m_Back = VMA_NULL;\n    size_t m_Count = 0;\n};\n\n#ifndef _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS\ntemplate<typename ItemTypeTraits>\nVmaIntrusiveLinkedList<ItemTypeTraits>::VmaIntrusiveLinkedList(VmaIntrusiveLinkedList&& src)\n    : m_Front(src.m_Front), m_Back(src.m_Back), m_Count(src.m_Count)\n{\n    src.m_Front = src.m_Back = VMA_NULL;\n    src.m_Count = 0;\n}\n\ntemplate<typename ItemTypeTraits>\nVmaIntrusiveLinkedList<ItemTypeTraits>& VmaIntrusiveLinkedList<ItemTypeTraits>::operator=(VmaIntrusiveLinkedList&& src)\n{\n    if (&src != this)\n    {\n        VMA_HEAVY_ASSERT(IsEmpty());\n        m_Front = src.m_Front;\n        m_Back = src.m_Back;\n        m_Count = src.m_Count;\n        src.m_Front = src.m_Back = VMA_NULL;\n        src.m_Count = 0;\n    }\n    return *this;\n}\n\ntemplate<typename ItemTypeTraits>\nvoid VmaIntrusiveLinkedList<ItemTypeTraits>::PushBack(ItemType* item)\n{\n    VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL);\n    if (IsEmpty())\n    {\n        m_Front = item;\n        m_Back = item;\n        m_Count = 1;\n    }\n    else\n    {\n        ItemTypeTraits::AccessPrev(item) = m_Back;\n        ItemTypeTraits::AccessNext(m_Back) = item;\n        m_Back = item;\n        ++m_Count;\n    }\n}\n\ntemplate<typename ItemTypeTraits>\nvoid VmaIntrusiveLinkedList<ItemTypeTraits>::PushFront(ItemType* item)\n{\n    VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL);\n    if (IsEmpty())\n    {\n        m_Front = item;\n        m_Back = item;\n        m_Count = 1;\n    }\n    else\n    {\n        ItemTypeTraits::AccessNext(item) = m_Front;\n        ItemTypeTraits::AccessPrev(m_Front) = item;\n        m_Front = item;\n        ++m_Count;\n    }\n}\n\ntemplate<typename ItemTypeTraits>\ntypename VmaIntrusiveLinkedList<ItemTypeTraits>::ItemType* VmaIntrusiveLinkedList<ItemTypeTraits>::PopBack()\n{\n    VMA_HEAVY_ASSERT(m_Count > 0);\n    ItemType* const backItem = m_Back;\n    ItemType* const prevItem = ItemTypeTraits::GetPrev(backItem);\n    if (prevItem != VMA_NULL)\n    {\n        ItemTypeTraits::AccessNext(prevItem) = VMA_NULL;\n    }\n    m_Back = prevItem;\n    --m_Count;\n    ItemTypeTraits::AccessPrev(backItem) = VMA_NULL;\n    ItemTypeTraits::AccessNext(backItem) = VMA_NULL;\n    return backItem;\n}\n\ntemplate<typename ItemTypeTraits>\ntypename VmaIntrusiveLinkedList<ItemTypeTraits>::ItemType* VmaIntrusiveLinkedList<ItemTypeTraits>::PopFront()\n{\n    VMA_HEAVY_ASSERT(m_Count > 0);\n    ItemType* const frontItem = m_Front;\n    ItemType* const nextItem = ItemTypeTraits::GetNext(frontItem);\n    if (nextItem != VMA_NULL)\n    {\n        ItemTypeTraits::AccessPrev(nextItem) = VMA_NULL;\n    }\n    m_Front = nextItem;\n    --m_Count;\n    ItemTypeTraits::AccessPrev(frontItem) = VMA_NULL;\n    ItemTypeTraits::AccessNext(frontItem) = VMA_NULL;\n    return frontItem;\n}\n\ntemplate<typename ItemTypeTraits>\nvoid VmaIntrusiveLinkedList<ItemTypeTraits>::InsertBefore(ItemType* existingItem, ItemType* newItem)\n{\n    VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL);\n    if (existingItem != VMA_NULL)\n    {\n        ItemType* const prevItem = ItemTypeTraits::GetPrev(existingItem);\n        ItemTypeTraits::AccessPrev(newItem) = prevItem;\n        ItemTypeTraits::AccessNext(newItem) = existingItem;\n        ItemTypeTraits::AccessPrev(existingItem) = newItem;\n        if (prevItem != VMA_NULL)\n        {\n            ItemTypeTraits::AccessNext(prevItem) = newItem;\n        }\n        else\n        {\n            VMA_HEAVY_ASSERT(m_Front == existingItem);\n            m_Front = newItem;\n        }\n        ++m_Count;\n    }\n    else\n        PushBack(newItem);\n}\n\ntemplate<typename ItemTypeTraits>\nvoid VmaIntrusiveLinkedList<ItemTypeTraits>::InsertAfter(ItemType* existingItem, ItemType* newItem)\n{\n    VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL);\n    if (existingItem != VMA_NULL)\n    {\n        ItemType* const nextItem = ItemTypeTraits::GetNext(existingItem);\n        ItemTypeTraits::AccessNext(newItem) = nextItem;\n        ItemTypeTraits::AccessPrev(newItem) = existingItem;\n        ItemTypeTraits::AccessNext(existingItem) = newItem;\n        if (nextItem != VMA_NULL)\n        {\n            ItemTypeTraits::AccessPrev(nextItem) = newItem;\n        }\n        else\n        {\n            VMA_HEAVY_ASSERT(m_Back == existingItem);\n            m_Back = newItem;\n        }\n        ++m_Count;\n    }\n    else\n        return PushFront(newItem);\n}\n\ntemplate<typename ItemTypeTraits>\nvoid VmaIntrusiveLinkedList<ItemTypeTraits>::Remove(ItemType* item)\n{\n    VMA_HEAVY_ASSERT(item != VMA_NULL && m_Count > 0);\n    if (ItemTypeTraits::GetPrev(item) != VMA_NULL)\n    {\n        ItemTypeTraits::AccessNext(ItemTypeTraits::AccessPrev(item)) = ItemTypeTraits::GetNext(item);\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(m_Front == item);\n        m_Front = ItemTypeTraits::GetNext(item);\n    }\n\n    if (ItemTypeTraits::GetNext(item) != VMA_NULL)\n    {\n        ItemTypeTraits::AccessPrev(ItemTypeTraits::AccessNext(item)) = ItemTypeTraits::GetPrev(item);\n    }\n    else\n    {\n        VMA_HEAVY_ASSERT(m_Back == item);\n        m_Back = ItemTypeTraits::GetPrev(item);\n    }\n    ItemTypeTraits::AccessPrev(item) = VMA_NULL;\n    ItemTypeTraits::AccessNext(item) = VMA_NULL;\n    --m_Count;\n}\n\ntemplate<typename ItemTypeTraits>\nvoid VmaIntrusiveLinkedList<ItemTypeTraits>::RemoveAll()\n{\n    if (!IsEmpty())\n    {\n        ItemType* item = m_Back;\n        while (item != VMA_NULL)\n        {\n            ItemType* const prevItem = ItemTypeTraits::AccessPrev(item);\n            ItemTypeTraits::AccessPrev(item) = VMA_NULL;\n            ItemTypeTraits::AccessNext(item) = VMA_NULL;\n            item = prevItem;\n        }\n        m_Front = VMA_NULL;\n        m_Back = VMA_NULL;\n        m_Count = 0;\n    }\n}\n#endif // _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS\n#endif // _VMA_INTRUSIVE_LINKED_LIST\n\n// Unused in this version.\n#if 0\n\n#ifndef _VMA_PAIR\ntemplate<typename T1, typename T2>\nstruct VmaPair\n{\n    T1 first;\n    T2 second;\n\n    VmaPair() : first(), second() {}\n    VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) {}\n};\n\ntemplate<typename FirstT, typename SecondT>\nstruct VmaPairFirstLess\n{\n    bool operator()(const VmaPair<FirstT, SecondT>& lhs, const VmaPair<FirstT, SecondT>& rhs) const\n    {\n        return lhs.first < rhs.first;\n    }\n    bool operator()(const VmaPair<FirstT, SecondT>& lhs, const FirstT& rhsFirst) const\n    {\n        return lhs.first < rhsFirst;\n    }\n};\n#endif // _VMA_PAIR\n\n#ifndef _VMA_MAP\n/* Class compatible with subset of interface of std::unordered_map.\nKeyT, ValueT must be POD because they will be stored in VmaVector.\n*/\ntemplate<typename KeyT, typename ValueT>\nclass VmaMap\n{\npublic:\n    typedef VmaPair<KeyT, ValueT> PairType;\n    typedef PairType* iterator;\n\n    VmaMap(const VmaStlAllocator<PairType>& allocator) : m_Vector(allocator) {}\n\n    iterator begin() { return m_Vector.begin(); }\n    iterator end() { return m_Vector.end(); }\n    size_t size() { return m_Vector.size(); }\n\n    void insert(const PairType& pair);\n    iterator find(const KeyT& key);\n    void erase(iterator it);\n\nprivate:\n    VmaVector< PairType, VmaStlAllocator<PairType>> m_Vector;\n};\n\n#ifndef _VMA_MAP_FUNCTIONS\ntemplate<typename KeyT, typename ValueT>\nvoid VmaMap<KeyT, ValueT>::insert(const PairType& pair)\n{\n    const size_t indexToInsert = VmaBinaryFindFirstNotLess(\n        m_Vector.data(),\n        m_Vector.data() + m_Vector.size(),\n        pair,\n        VmaPairFirstLess<KeyT, ValueT>()) - m_Vector.data();\n    VmaVectorInsert(m_Vector, indexToInsert, pair);\n}\n\ntemplate<typename KeyT, typename ValueT>\nVmaPair<KeyT, ValueT>* VmaMap<KeyT, ValueT>::find(const KeyT& key)\n{\n    PairType* it = VmaBinaryFindFirstNotLess(\n        m_Vector.data(),\n        m_Vector.data() + m_Vector.size(),\n        key,\n        VmaPairFirstLess<KeyT, ValueT>());\n    if ((it != m_Vector.end()) && (it->first == key))\n    {\n        return it;\n    }\n    else\n    {\n        return m_Vector.end();\n    }\n}\n\ntemplate<typename KeyT, typename ValueT>\nvoid VmaMap<KeyT, ValueT>::erase(iterator it)\n{\n    VmaVectorRemove(m_Vector, it - m_Vector.begin());\n}\n#endif // _VMA_MAP_FUNCTIONS\n#endif // _VMA_MAP\n\n#endif // #if 0\n\n#if !defined(_VMA_STRING_BUILDER) && VMA_STATS_STRING_ENABLED\nclass VmaStringBuilder\n{\npublic:\n    VmaStringBuilder(const VkAllocationCallbacks* allocationCallbacks) : m_Data(VmaStlAllocator<char>(allocationCallbacks)) {}\n    ~VmaStringBuilder() = default;\n\n    size_t GetLength() const { return m_Data.size(); }\n    const char* GetData() const { return m_Data.data(); }\n    void AddNewLine() { Add('\\n'); }\n    void Add(char ch) { m_Data.push_back(ch); }\n\n    void Add(const char* pStr);\n    void AddNumber(uint32_t num);\n    void AddNumber(uint64_t num);\n    void AddPointer(const void* ptr);\n\nprivate:\n    VmaVector<char, VmaStlAllocator<char>> m_Data;\n};\n\n#ifndef _VMA_STRING_BUILDER_FUNCTIONS\nvoid VmaStringBuilder::Add(const char* pStr)\n{\n    const size_t strLen = strlen(pStr);\n    if (strLen > 0)\n    {\n        const size_t oldCount = m_Data.size();\n        m_Data.resize(oldCount + strLen);\n        memcpy(m_Data.data() + oldCount, pStr, strLen);\n    }\n}\n\nvoid VmaStringBuilder::AddNumber(uint32_t num)\n{\n    char buf[11];\n    buf[10] = '\\0';\n    char* p = &buf[10];\n    do\n    {\n        *--p = '0' + (num % 10);\n        num /= 10;\n    } while (num);\n    Add(p);\n}\n\nvoid VmaStringBuilder::AddNumber(uint64_t num)\n{\n    char buf[21];\n    buf[20] = '\\0';\n    char* p = &buf[20];\n    do\n    {\n        *--p = '0' + (num % 10);\n        num /= 10;\n    } while (num);\n    Add(p);\n}\n\nvoid VmaStringBuilder::AddPointer(const void* ptr)\n{\n    char buf[21];\n    VmaPtrToStr(buf, sizeof(buf), ptr);\n    Add(buf);\n}\n#endif //_VMA_STRING_BUILDER_FUNCTIONS\n#endif // _VMA_STRING_BUILDER\n\n#if !defined(_VMA_JSON_WRITER) && VMA_STATS_STRING_ENABLED\n/*\nAllows to conveniently build a correct JSON document to be written to the\nVmaStringBuilder passed to the constructor.\n*/\nclass VmaJsonWriter\n{\n    VMA_CLASS_NO_COPY(VmaJsonWriter)\npublic:\n    // sb - string builder to write the document to. Must remain alive for the whole lifetime of this object.\n    VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb);\n    ~VmaJsonWriter();\n\n    // Begins object by writing \"{\".\n    // Inside an object, you must call pairs of WriteString and a value, e.g.:\n    // j.BeginObject(true); j.WriteString(\"A\"); j.WriteNumber(1); j.WriteString(\"B\"); j.WriteNumber(2); j.EndObject();\n    // Will write: { \"A\": 1, \"B\": 2 }\n    void BeginObject(bool singleLine = false);\n    // Ends object by writing \"}\".\n    void EndObject();\n\n    // Begins array by writing \"[\".\n    // Inside an array, you can write a sequence of any values.\n    void BeginArray(bool singleLine = false);\n    // Ends array by writing \"[\".\n    void EndArray();\n\n    // Writes a string value inside \"\".\n    // pStr can contain any ANSI characters, including '\"', new line etc. - they will be properly escaped.\n    void WriteString(const char* pStr);\n\n    // Begins writing a string value.\n    // Call BeginString, ContinueString, ContinueString, ..., EndString instead of\n    // WriteString to conveniently build the string content incrementally, made of\n    // parts including numbers.\n    void BeginString(const char* pStr = VMA_NULL);\n    // Posts next part of an open string.\n    void ContinueString(const char* pStr);\n    // Posts next part of an open string. The number is converted to decimal characters.\n    void ContinueString(uint32_t n);\n    void ContinueString(uint64_t n);\n    // Posts next part of an open string. Pointer value is converted to characters\n    // using \"%p\" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00\n    void ContinueString_Pointer(const void* ptr);\n    // Ends writing a string value by writing '\"'.\n    void EndString(const char* pStr = VMA_NULL);\n\n    // Writes a number value.\n    void WriteNumber(uint32_t n);\n    void WriteNumber(uint64_t n);\n    // Writes a boolean value - false or true.\n    void WriteBool(bool b);\n    // Writes a null value.\n    void WriteNull();\n\nprivate:\n    enum COLLECTION_TYPE\n    {\n        COLLECTION_TYPE_OBJECT,\n        COLLECTION_TYPE_ARRAY,\n    };\n    struct StackItem\n    {\n        COLLECTION_TYPE type;\n        uint32_t valueCount;\n        bool singleLineMode;\n    };\n\n    static const char* const INDENT;\n\n    VmaStringBuilder& m_SB;\n    VmaVector< StackItem, VmaStlAllocator<StackItem> > m_Stack;\n    bool m_InsideString;\n\n    void BeginValue(bool isString);\n    void WriteIndent(bool oneLess = false);\n};\nconst char* const VmaJsonWriter::INDENT = \"  \";\n\n#ifndef _VMA_JSON_WRITER_FUNCTIONS\nVmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb)\n    : m_SB(sb),\n    m_Stack(VmaStlAllocator<StackItem>(pAllocationCallbacks)),\n    m_InsideString(false) {}\n\nVmaJsonWriter::~VmaJsonWriter()\n{\n    VMA_ASSERT(!m_InsideString);\n    VMA_ASSERT(m_Stack.empty());\n}\n\nvoid VmaJsonWriter::BeginObject(bool singleLine)\n{\n    VMA_ASSERT(!m_InsideString);\n\n    BeginValue(false);\n    m_SB.Add('{');\n\n    StackItem item;\n    item.type = COLLECTION_TYPE_OBJECT;\n    item.valueCount = 0;\n    item.singleLineMode = singleLine;\n    m_Stack.push_back(item);\n}\n\nvoid VmaJsonWriter::EndObject()\n{\n    VMA_ASSERT(!m_InsideString);\n\n    WriteIndent(true);\n    m_SB.Add('}');\n\n    VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_OBJECT);\n    m_Stack.pop_back();\n}\n\nvoid VmaJsonWriter::BeginArray(bool singleLine)\n{\n    VMA_ASSERT(!m_InsideString);\n\n    BeginValue(false);\n    m_SB.Add('[');\n\n    StackItem item;\n    item.type = COLLECTION_TYPE_ARRAY;\n    item.valueCount = 0;\n    item.singleLineMode = singleLine;\n    m_Stack.push_back(item);\n}\n\nvoid VmaJsonWriter::EndArray()\n{\n    VMA_ASSERT(!m_InsideString);\n\n    WriteIndent(true);\n    m_SB.Add(']');\n\n    VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_ARRAY);\n    m_Stack.pop_back();\n}\n\nvoid VmaJsonWriter::WriteString(const char* pStr)\n{\n    BeginString(pStr);\n    EndString();\n}\n\nvoid VmaJsonWriter::BeginString(const char* pStr)\n{\n    VMA_ASSERT(!m_InsideString);\n\n    BeginValue(true);\n    m_SB.Add('\"');\n    m_InsideString = true;\n    if (pStr != VMA_NULL && pStr[0] != '\\0')\n    {\n        ContinueString(pStr);\n    }\n}\n\nvoid VmaJsonWriter::ContinueString(const char* pStr)\n{\n    VMA_ASSERT(m_InsideString);\n\n    const size_t strLen = strlen(pStr);\n    for (size_t i = 0; i < strLen; ++i)\n    {\n        char ch = pStr[i];\n        if (ch == '\\\\')\n        {\n            m_SB.Add(\"\\\\\\\\\");\n        }\n        else if (ch == '\"')\n        {\n            m_SB.Add(\"\\\\\\\"\");\n        }\n        else if (ch >= 32)\n        {\n            m_SB.Add(ch);\n        }\n        else switch (ch)\n        {\n        case '\\b':\n            m_SB.Add(\"\\\\b\");\n            break;\n        case '\\f':\n            m_SB.Add(\"\\\\f\");\n            break;\n        case '\\n':\n            m_SB.Add(\"\\\\n\");\n            break;\n        case '\\r':\n            m_SB.Add(\"\\\\r\");\n            break;\n        case '\\t':\n            m_SB.Add(\"\\\\t\");\n            break;\n        default:\n            VMA_ASSERT(0 && \"Character not currently supported.\");\n            break;\n        }\n    }\n}\n\nvoid VmaJsonWriter::ContinueString(uint32_t n)\n{\n    VMA_ASSERT(m_InsideString);\n    m_SB.AddNumber(n);\n}\n\nvoid VmaJsonWriter::ContinueString(uint64_t n)\n{\n    VMA_ASSERT(m_InsideString);\n    m_SB.AddNumber(n);\n}\n\nvoid VmaJsonWriter::ContinueString_Pointer(const void* ptr)\n{\n    VMA_ASSERT(m_InsideString);\n    m_SB.AddPointer(ptr);\n}\n\nvoid VmaJsonWriter::EndString(const char* pStr)\n{\n    VMA_ASSERT(m_InsideString);\n    if (pStr != VMA_NULL && pStr[0] != '\\0')\n    {\n        ContinueString(pStr);\n    }\n    m_SB.Add('\"');\n    m_InsideString = false;\n}\n\nvoid VmaJsonWriter::WriteNumber(uint32_t n)\n{\n    VMA_ASSERT(!m_InsideString);\n    BeginValue(false);\n    m_SB.AddNumber(n);\n}\n\nvoid VmaJsonWriter::WriteNumber(uint64_t n)\n{\n    VMA_ASSERT(!m_InsideString);\n    BeginValue(false);\n    m_SB.AddNumber(n);\n}\n\nvoid VmaJsonWriter::WriteBool(bool b)\n{\n    VMA_ASSERT(!m_InsideString);\n    BeginValue(false);\n    m_SB.Add(b ? \"true\" : \"false\");\n}\n\nvoid VmaJsonWriter::WriteNull()\n{\n    VMA_ASSERT(!m_InsideString);\n    BeginValue(false);\n    m_SB.Add(\"null\");\n}\n\nvoid VmaJsonWriter::BeginValue(bool isString)\n{\n    if (!m_Stack.empty())\n    {\n        StackItem& currItem = m_Stack.back();\n        if (currItem.type == COLLECTION_TYPE_OBJECT &&\n            currItem.valueCount % 2 == 0)\n        {\n            VMA_ASSERT(isString);\n        }\n\n        if (currItem.type == COLLECTION_TYPE_OBJECT &&\n            currItem.valueCount % 2 != 0)\n        {\n            m_SB.Add(\": \");\n        }\n        else if (currItem.valueCount > 0)\n        {\n            m_SB.Add(\", \");\n            WriteIndent();\n        }\n        else\n        {\n            WriteIndent();\n        }\n        ++currItem.valueCount;\n    }\n}\n\nvoid VmaJsonWriter::WriteIndent(bool oneLess)\n{\n    if (!m_Stack.empty() && !m_Stack.back().singleLineMode)\n    {\n        m_SB.AddNewLine();\n\n        size_t count = m_Stack.size();\n        if (count > 0 && oneLess)\n        {\n            --count;\n        }\n        for (size_t i = 0; i < count; ++i)\n        {\n            m_SB.Add(INDENT);\n        }\n    }\n}\n#endif // _VMA_JSON_WRITER_FUNCTIONS\n\nstatic void VmaPrintDetailedStatistics(VmaJsonWriter& json, const VmaDetailedStatistics& stat)\n{\n    json.BeginObject();\n\n    json.WriteString(\"BlockCount\");\n    json.WriteNumber(stat.statistics.blockCount);\n    json.WriteString(\"BlockBytes\");\n    json.WriteNumber(stat.statistics.blockBytes);\n    json.WriteString(\"AllocationCount\");\n    json.WriteNumber(stat.statistics.allocationCount);\n    json.WriteString(\"AllocationBytes\");\n    json.WriteNumber(stat.statistics.allocationBytes);\n    json.WriteString(\"UnusedRangeCount\");\n    json.WriteNumber(stat.unusedRangeCount);\n\n    if (stat.statistics.allocationCount > 1)\n    {\n        json.WriteString(\"AllocationSizeMin\");\n        json.WriteNumber(stat.allocationSizeMin);\n        json.WriteString(\"AllocationSizeMax\");\n        json.WriteNumber(stat.allocationSizeMax);\n    }\n    if (stat.unusedRangeCount > 1)\n    {\n        json.WriteString(\"UnusedRangeSizeMin\");\n        json.WriteNumber(stat.unusedRangeSizeMin);\n        json.WriteString(\"UnusedRangeSizeMax\");\n        json.WriteNumber(stat.unusedRangeSizeMax);\n    }\n    json.EndObject();\n}\n#endif // _VMA_JSON_WRITER\n\n#ifndef _VMA_MAPPING_HYSTERESIS\n\nclass VmaMappingHysteresis\n{\n    VMA_CLASS_NO_COPY(VmaMappingHysteresis)\npublic:\n    VmaMappingHysteresis() = default;\n\n    uint32_t GetExtraMapping() const { return m_ExtraMapping; }\n\n    // Call when Map was called.\n    // Returns true if switched to extra +1 mapping reference count.\n    bool PostMap()\n    {\n#if VMA_MAPPING_HYSTERESIS_ENABLED\n        if(m_ExtraMapping == 0)\n        {\n            ++m_MajorCounter;\n            if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING)\n            {\n                m_ExtraMapping = 1;\n                m_MajorCounter = 0;\n                m_MinorCounter = 0;\n                return true;\n            }\n        }\n        else // m_ExtraMapping == 1\n            PostMinorCounter();\n#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED\n        return false;\n    }\n\n    // Call when Unmap was called.\n    void PostUnmap()\n    {\n#if VMA_MAPPING_HYSTERESIS_ENABLED\n        if(m_ExtraMapping == 0)\n            ++m_MajorCounter;\n        else // m_ExtraMapping == 1\n            PostMinorCounter();\n#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED\n    }\n\n    // Call when allocation was made from the memory block.\n    void PostAlloc()\n    {\n#if VMA_MAPPING_HYSTERESIS_ENABLED\n        if(m_ExtraMapping == 1)\n            ++m_MajorCounter;\n        else // m_ExtraMapping == 0\n            PostMinorCounter();\n#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED\n    }\n\n    // Call when allocation was freed from the memory block.\n    // Returns true if switched to extra -1 mapping reference count.\n    bool PostFree()\n    {\n#if VMA_MAPPING_HYSTERESIS_ENABLED\n        if(m_ExtraMapping == 1)\n        {\n            ++m_MajorCounter;\n            if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING &&\n                m_MajorCounter > m_MinorCounter + 1)\n            {\n                m_ExtraMapping = 0;\n                m_MajorCounter = 0;\n                m_MinorCounter = 0;\n                return true;\n            }\n        }\n        else // m_ExtraMapping == 0\n            PostMinorCounter();\n#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED\n        return false;\n    }\n\nprivate:\n    static const int32_t COUNTER_MIN_EXTRA_MAPPING = 7;\n\n    uint32_t m_MinorCounter = 0;\n    uint32_t m_MajorCounter = 0;\n    uint32_t m_ExtraMapping = 0; // 0 or 1.\n\n    void PostMinorCounter()\n    {\n        if(m_MinorCounter < m_MajorCounter)\n        {\n            ++m_MinorCounter;\n        }\n        else if(m_MajorCounter > 0)\n        {\n            --m_MajorCounter;\n            --m_MinorCounter;\n        }\n    }\n};\n\n#endif // _VMA_MAPPING_HYSTERESIS\n\n#ifndef _VMA_DEVICE_MEMORY_BLOCK\n/*\nRepresents a single block of device memory (`VkDeviceMemory`) with all the\ndata about its regions (aka suballocations, #VmaAllocation), assigned and free.\n\nThread-safety:\n- Access to m_pMetadata must be externally synchronized.\n- Map, Unmap, Bind* are synchronized internally.\n*/\nclass VmaDeviceMemoryBlock\n{\n    VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)\npublic:\n    VmaBlockMetadata* m_pMetadata;\n\n    VmaDeviceMemoryBlock(VmaAllocator hAllocator);\n    ~VmaDeviceMemoryBlock();\n\n    // Always call after construction.\n    void Init(\n        VmaAllocator hAllocator,\n        VmaPool hParentPool,\n        uint32_t newMemoryTypeIndex,\n        VkDeviceMemory newMemory,\n        VkDeviceSize newSize,\n        uint32_t id,\n        uint32_t algorithm,\n        VkDeviceSize bufferImageGranularity);\n    // Always call before destruction.\n    void Destroy(VmaAllocator allocator);\n\n    VmaPool GetParentPool() const { return m_hParentPool; }\n    VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }\n    uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }\n    uint32_t GetId() const { return m_Id; }\n    void* GetMappedData() const { return m_pMappedData; }\n    uint32_t GetMapRefCount() const { return m_MapCount; }\n\n    // Call when allocation/free was made from m_pMetadata.\n    // Used for m_MappingHysteresis.\n    void PostAlloc(VmaAllocator hAllocator);\n    void PostFree(VmaAllocator hAllocator);\n\n    // Validates all data structures inside this object. If not valid, returns false.\n    bool Validate() const;\n    VkResult CheckCorruption(VmaAllocator hAllocator);\n\n    // ppData can be null.\n    VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData);\n    void Unmap(VmaAllocator hAllocator, uint32_t count);\n\n    VkResult WriteMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);\n    VkResult ValidateMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);\n\n    VkResult BindBufferMemory(\n        const VmaAllocator hAllocator,\n        const VmaAllocation hAllocation,\n        VkDeviceSize allocationLocalOffset,\n        VkBuffer hBuffer,\n        const void* pNext);\n    VkResult BindImageMemory(\n        const VmaAllocator hAllocator,\n        const VmaAllocation hAllocation,\n        VkDeviceSize allocationLocalOffset,\n        VkImage hImage,\n        const void* pNext);\n\nprivate:\n    VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.\n    uint32_t m_MemoryTypeIndex;\n    uint32_t m_Id;\n    VkDeviceMemory m_hMemory;\n\n    /*\n    Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.\n    Also protects m_MapCount, m_pMappedData.\n    Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.\n    */\n    VMA_MUTEX m_MapAndBindMutex;\n    VmaMappingHysteresis m_MappingHysteresis;\n    uint32_t m_MapCount;\n    void* m_pMappedData;\n};\n#endif // _VMA_DEVICE_MEMORY_BLOCK\n\n#ifndef _VMA_ALLOCATION_T\nstruct VmaAllocation_T\n{\n    friend struct VmaDedicatedAllocationListItemTraits;\n\n    enum FLAGS\n    {\n        FLAG_PERSISTENT_MAP   = 0x01,\n        FLAG_MAPPING_ALLOWED  = 0x02,\n    };\n\npublic:\n    enum ALLOCATION_TYPE\n    {\n        ALLOCATION_TYPE_NONE,\n        ALLOCATION_TYPE_BLOCK,\n        ALLOCATION_TYPE_DEDICATED,\n    };\n\n    // This struct is allocated using VmaPoolAllocator.\n    VmaAllocation_T(bool mappingAllowed);\n    ~VmaAllocation_T();\n\n    void InitBlockAllocation(\n        VmaDeviceMemoryBlock* block,\n        VmaAllocHandle allocHandle,\n        VkDeviceSize alignment,\n        VkDeviceSize size,\n        uint32_t memoryTypeIndex,\n        VmaSuballocationType suballocationType,\n        bool mapped);\n    // pMappedData not null means allocation is created with MAPPED flag.\n    void InitDedicatedAllocation(\n        VmaPool hParentPool,\n        uint32_t memoryTypeIndex,\n        VkDeviceMemory hMemory,\n        VmaSuballocationType suballocationType,\n        void* pMappedData,\n        VkDeviceSize size);\n\n    ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }\n    VkDeviceSize GetAlignment() const { return m_Alignment; }\n    VkDeviceSize GetSize() const { return m_Size; }\n    void* GetUserData() const { return m_pUserData; }\n    const char* GetName() const { return m_pName; }\n    VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; }\n\n    VmaDeviceMemoryBlock* GetBlock() const { VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); return m_BlockAllocation.m_Block; }\n    uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }\n    bool IsPersistentMap() const { return (m_Flags & FLAG_PERSISTENT_MAP) != 0; }\n    bool IsMappingAllowed() const { return (m_Flags & FLAG_MAPPING_ALLOWED) != 0; }\n\n    void SetUserData(VmaAllocator hAllocator, void* pUserData) { m_pUserData = pUserData; }\n    void SetName(VmaAllocator hAllocator, const char* pName);\n    void FreeName(VmaAllocator hAllocator);\n    uint8_t SwapBlockAllocation(VmaAllocator hAllocator, VmaAllocation allocation);\n    VmaAllocHandle GetAllocHandle() const;\n    VkDeviceSize GetOffset() const;\n    VmaPool GetParentPool() const;\n    VkDeviceMemory GetMemory() const;\n    void* GetMappedData() const;\n\n    void BlockAllocMap();\n    void BlockAllocUnmap();\n    VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData);\n    void DedicatedAllocUnmap(VmaAllocator hAllocator);\n\n#if VMA_STATS_STRING_ENABLED\n    uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; }\n\n    void InitBufferImageUsage(uint32_t bufferImageUsage);\n    void PrintParameters(class VmaJsonWriter& json) const;\n#endif\n\nprivate:\n    // Allocation out of VmaDeviceMemoryBlock.\n    struct BlockAllocation\n    {\n        VmaDeviceMemoryBlock* m_Block;\n        VmaAllocHandle m_AllocHandle;\n    };\n    // Allocation for an object that has its own private VkDeviceMemory.\n    struct DedicatedAllocation\n    {\n        VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.\n        VkDeviceMemory m_hMemory;\n        void* m_pMappedData; // Not null means memory is mapped.\n        VmaAllocation_T* m_Prev;\n        VmaAllocation_T* m_Next;\n    };\n    union\n    {\n        // Allocation out of VmaDeviceMemoryBlock.\n        BlockAllocation m_BlockAllocation;\n        // Allocation for an object that has its own private VkDeviceMemory.\n        DedicatedAllocation m_DedicatedAllocation;\n    };\n\n    VkDeviceSize m_Alignment;\n    VkDeviceSize m_Size;\n    void* m_pUserData;\n    char* m_pName;\n    uint32_t m_MemoryTypeIndex;\n    uint8_t m_Type; // ALLOCATION_TYPE\n    uint8_t m_SuballocationType; // VmaSuballocationType\n    // Reference counter for vmaMapMemory()/vmaUnmapMemory().\n    uint8_t m_MapCount;\n    uint8_t m_Flags; // enum FLAGS\n#if VMA_STATS_STRING_ENABLED\n    uint32_t m_BufferImageUsage; // 0 if unknown.\n#endif\n};\n#endif // _VMA_ALLOCATION_T\n\n#ifndef _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS\nstruct VmaDedicatedAllocationListItemTraits\n{\n    typedef VmaAllocation_T ItemType;\n\n    static ItemType* GetPrev(const ItemType* item)\n    {\n        VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);\n        return item->m_DedicatedAllocation.m_Prev;\n    }\n    static ItemType* GetNext(const ItemType* item)\n    {\n        VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);\n        return item->m_DedicatedAllocation.m_Next;\n    }\n    static ItemType*& AccessPrev(ItemType* item)\n    {\n        VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);\n        return item->m_DedicatedAllocation.m_Prev;\n    }\n    static ItemType*& AccessNext(ItemType* item)\n    {\n        VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);\n        return item->m_DedicatedAllocation.m_Next;\n    }\n};\n#endif // _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS\n\n#ifndef _VMA_DEDICATED_ALLOCATION_LIST\n/*\nStores linked list of VmaAllocation_T objects.\nThread-safe, synchronized internally.\n*/\nclass VmaDedicatedAllocationList\n{\npublic:\n    VmaDedicatedAllocationList() {}\n    ~VmaDedicatedAllocationList();\n\n    void Init(bool useMutex) { m_UseMutex = useMutex; }\n    bool Validate();\n\n    void AddDetailedStatistics(VmaDetailedStatistics& inoutStats);\n    void AddStatistics(VmaStatistics& inoutStats);\n#if VMA_STATS_STRING_ENABLED\n    // Writes JSON array with the list of allocations.\n    void BuildStatsString(VmaJsonWriter& json);\n#endif\n\n    bool IsEmpty();\n    void Register(VmaAllocation alloc);\n    void Unregister(VmaAllocation alloc);\n\nprivate:\n    typedef VmaIntrusiveLinkedList<VmaDedicatedAllocationListItemTraits> DedicatedAllocationLinkedList;\n\n    bool m_UseMutex = true;\n    VMA_RW_MUTEX m_Mutex;\n    DedicatedAllocationLinkedList m_AllocationList;\n};\n\n#ifndef _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS\n\nVmaDedicatedAllocationList::~VmaDedicatedAllocationList()\n{\n    VMA_HEAVY_ASSERT(Validate());\n\n    if (!m_AllocationList.IsEmpty())\n    {\n        VMA_ASSERT(false && \"Unfreed dedicated allocations found!\");\n    }\n}\n\nbool VmaDedicatedAllocationList::Validate()\n{\n    const size_t declaredCount = m_AllocationList.GetCount();\n    size_t actualCount = 0;\n    VmaMutexLockRead lock(m_Mutex, m_UseMutex);\n    for (VmaAllocation alloc = m_AllocationList.Front();\n        alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc))\n    {\n        ++actualCount;\n    }\n    VMA_VALIDATE(actualCount == declaredCount);\n\n    return true;\n}\n\nvoid VmaDedicatedAllocationList::AddDetailedStatistics(VmaDetailedStatistics& inoutStats)\n{\n    for(auto* item = m_AllocationList.Front(); item != nullptr; item = DedicatedAllocationLinkedList::GetNext(item))\n    {\n        const VkDeviceSize size = item->GetSize();\n        inoutStats.statistics.blockCount++;\n        inoutStats.statistics.blockBytes += size;\n        VmaAddDetailedStatisticsAllocation(inoutStats, item->GetSize());\n    }\n}\n\nvoid VmaDedicatedAllocationList::AddStatistics(VmaStatistics& inoutStats)\n{\n    VmaMutexLockRead lock(m_Mutex, m_UseMutex);\n\n    const uint32_t allocCount = (uint32_t)m_AllocationList.GetCount();\n    inoutStats.blockCount += allocCount;\n    inoutStats.allocationCount += allocCount;\n\n    for(auto* item = m_AllocationList.Front(); item != nullptr; item = DedicatedAllocationLinkedList::GetNext(item))\n    {\n        const VkDeviceSize size = item->GetSize();\n        inoutStats.blockBytes += size;\n        inoutStats.allocationBytes += size;\n    }\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaDedicatedAllocationList::BuildStatsString(VmaJsonWriter& json)\n{\n    VmaMutexLockRead lock(m_Mutex, m_UseMutex);\n    json.BeginArray();\n    for (VmaAllocation alloc = m_AllocationList.Front();\n        alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc))\n    {\n        json.BeginObject(true);\n        alloc->PrintParameters(json);\n        json.EndObject();\n    }\n    json.EndArray();\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nbool VmaDedicatedAllocationList::IsEmpty()\n{\n    VmaMutexLockRead lock(m_Mutex, m_UseMutex);\n    return m_AllocationList.IsEmpty();\n}\n\nvoid VmaDedicatedAllocationList::Register(VmaAllocation alloc)\n{\n    VmaMutexLockWrite lock(m_Mutex, m_UseMutex);\n    m_AllocationList.PushBack(alloc);\n}\n\nvoid VmaDedicatedAllocationList::Unregister(VmaAllocation alloc)\n{\n    VmaMutexLockWrite lock(m_Mutex, m_UseMutex);\n    m_AllocationList.Remove(alloc);\n}\n#endif // _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS\n#endif // _VMA_DEDICATED_ALLOCATION_LIST\n\n#ifndef _VMA_SUBALLOCATION\n/*\nRepresents a region of VmaDeviceMemoryBlock that is either assigned and returned as\nallocated memory block or free.\n*/\nstruct VmaSuballocation\n{\n    VkDeviceSize offset;\n    VkDeviceSize size;\n    void* userData;\n    VmaSuballocationType type;\n};\n\n// Comparator for offsets.\nstruct VmaSuballocationOffsetLess\n{\n    bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const\n    {\n        return lhs.offset < rhs.offset;\n    }\n};\n\nstruct VmaSuballocationOffsetGreater\n{\n    bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const\n    {\n        return lhs.offset > rhs.offset;\n    }\n};\n\nstruct VmaSuballocationItemSizeLess\n{\n    bool operator()(const VmaSuballocationList::iterator lhs,\n        const VmaSuballocationList::iterator rhs) const\n    {\n        return lhs->size < rhs->size;\n    }\n\n    bool operator()(const VmaSuballocationList::iterator lhs,\n        VkDeviceSize rhsSize) const\n    {\n        return lhs->size < rhsSize;\n    }\n};\n#endif // _VMA_SUBALLOCATION\n\n#ifndef _VMA_ALLOCATION_REQUEST\n/*\nParameters of planned allocation inside a VmaDeviceMemoryBlock.\nitem points to a FREE suballocation.\n*/\nstruct VmaAllocationRequest\n{\n    VmaAllocHandle allocHandle;\n    VkDeviceSize size;\n    VmaSuballocationList::iterator item;\n    void* customData;\n    uint64_t algorithmData;\n    VmaAllocationRequestType type;\n};\n#endif // _VMA_ALLOCATION_REQUEST\n\n#ifndef _VMA_BLOCK_METADATA\n/*\nData structure used for bookkeeping of allocations and unused ranges of memory\nin a single VkDeviceMemory block.\n*/\nclass VmaBlockMetadata\n{\npublic:\n    // pAllocationCallbacks, if not null, must be owned externally - alive and unchanged for the whole lifetime of this object.\n    VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks,\n        VkDeviceSize bufferImageGranularity, bool isVirtual);\n    virtual ~VmaBlockMetadata() = default;\n\n    virtual void Init(VkDeviceSize size) { m_Size = size; }\n    bool IsVirtual() const { return m_IsVirtual; }\n    VkDeviceSize GetSize() const { return m_Size; }\n\n    // Validates all data structures inside this object. If not valid, returns false.\n    virtual bool Validate() const = 0;\n    virtual size_t GetAllocationCount() const = 0;\n    virtual size_t GetFreeRegionsCount() const = 0;\n    virtual VkDeviceSize GetSumFreeSize() const = 0;\n    // Returns true if this block is empty - contains only single free suballocation.\n    virtual bool IsEmpty() const = 0;\n    virtual void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) = 0;\n    virtual VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const = 0;\n    virtual void* GetAllocationUserData(VmaAllocHandle allocHandle) const = 0;\n\n    virtual VmaAllocHandle GetAllocationListBegin() const = 0;\n    virtual VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const = 0;\n    virtual VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const = 0;\n\n    // Shouldn't modify blockCount.\n    virtual void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const = 0;\n    virtual void AddStatistics(VmaStatistics& inoutStats) const = 0;\n\n#if VMA_STATS_STRING_ENABLED\n    virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;\n#endif\n\n    // Tries to find a place for suballocation with given parameters inside this block.\n    // If succeeded, fills pAllocationRequest and returns true.\n    // If failed, returns false.\n    virtual bool CreateAllocationRequest(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        bool upperAddress,\n        VmaSuballocationType allocType,\n        // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest) = 0;\n\n    virtual VkResult CheckCorruption(const void* pBlockData) = 0;\n\n    // Makes actual allocation based on request. Request must already be checked and valid.\n    virtual void Alloc(\n        const VmaAllocationRequest& request,\n        VmaSuballocationType type,\n        void* userData) = 0;\n\n    // Frees suballocation assigned to given memory region.\n    virtual void Free(VmaAllocHandle allocHandle) = 0;\n\n    // Frees all allocations.\n    // Careful! Don't call it if there are VmaAllocation objects owned by userData of cleared allocations!\n    virtual void Clear() = 0;\n\n    virtual void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) = 0;\n    virtual void DebugLogAllAllocations() const = 0;\n\nprotected:\n    const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }\n    VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }\n    VkDeviceSize GetDebugMargin() const { return IsVirtual() ? 0 : VMA_DEBUG_MARGIN; }\n\n    void DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const;\n#if VMA_STATS_STRING_ENABLED\n    // mapRefCount == UINT32_MAX means unspecified.\n    void PrintDetailedMap_Begin(class VmaJsonWriter& json,\n        VkDeviceSize unusedBytes,\n        size_t allocationCount,\n        size_t unusedRangeCount) const;\n    void PrintDetailedMap_Allocation(class VmaJsonWriter& json,\n        VkDeviceSize offset, VkDeviceSize size, void* userData) const;\n    void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,\n        VkDeviceSize offset,\n        VkDeviceSize size) const;\n    void PrintDetailedMap_End(class VmaJsonWriter& json) const;\n#endif\n\nprivate:\n    VkDeviceSize m_Size;\n    const VkAllocationCallbacks* m_pAllocationCallbacks;\n    const VkDeviceSize m_BufferImageGranularity;\n    const bool m_IsVirtual;\n};\n\n#ifndef _VMA_BLOCK_METADATA_FUNCTIONS\nVmaBlockMetadata::VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks,\n    VkDeviceSize bufferImageGranularity, bool isVirtual)\n    : m_Size(0),\n    m_pAllocationCallbacks(pAllocationCallbacks),\n    m_BufferImageGranularity(bufferImageGranularity),\n    m_IsVirtual(isVirtual) {}\n\nvoid VmaBlockMetadata::DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const\n{\n    if (IsVirtual())\n    {\n        VMA_DEBUG_LOG(\"UNFREED VIRTUAL ALLOCATION; Offset: %llu; Size: %llu; UserData: %p\", offset, size, userData);\n    }\n    else\n    {\n        VMA_ASSERT(userData != VMA_NULL);\n        VmaAllocation allocation = reinterpret_cast<VmaAllocation>(userData);\n\n        userData = allocation->GetUserData();\n        const char* name = allocation->GetName();\n\n#if VMA_STATS_STRING_ENABLED\n        VMA_DEBUG_LOG(\"UNFREED ALLOCATION; Offset: %llu; Size: %llu; UserData: %p; Name: %s; Type: %s; Usage: %u\",\n            offset, size, userData, name ? name : \"vma_empty\",\n            VMA_SUBALLOCATION_TYPE_NAMES[allocation->GetSuballocationType()],\n            allocation->GetBufferImageUsage());\n#else\n        VMA_DEBUG_LOG(\"UNFREED ALLOCATION; Offset: %llu; Size: %llu; UserData: %p; Name: %s; Type: %u\",\n            offset, size, userData, name ? name : \"vma_empty\",\n            (uint32_t)allocation->GetSuballocationType());\n#endif // VMA_STATS_STRING_ENABLED\n    }\n\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json,\n    VkDeviceSize unusedBytes, size_t allocationCount, size_t unusedRangeCount) const\n{\n    json.WriteString(\"TotalBytes\");\n    json.WriteNumber(GetSize());\n\n    json.WriteString(\"UnusedBytes\");\n    json.WriteNumber(unusedBytes);\n\n    json.WriteString(\"Allocations\");\n    json.WriteNumber((uint64_t)allocationCount);\n\n    json.WriteString(\"UnusedRanges\");\n    json.WriteNumber((uint64_t)unusedRangeCount);\n\n    json.WriteString(\"Suballocations\");\n    json.BeginArray();\n}\n\nvoid VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json,\n    VkDeviceSize offset, VkDeviceSize size, void* userData) const\n{\n    json.BeginObject(true);\n\n    json.WriteString(\"Offset\");\n    json.WriteNumber(offset);\n\n    if (IsVirtual())\n    {\n        json.WriteString(\"Size\");\n        json.WriteNumber(size);\n        if (userData)\n        {\n            json.WriteString(\"CustomData\");\n            json.BeginString();\n            json.ContinueString_Pointer(userData);\n            json.EndString();\n        }\n    }\n    else\n    {\n        ((VmaAllocation)userData)->PrintParameters(json);\n    }\n\n    json.EndObject();\n}\n\nvoid VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,\n    VkDeviceSize offset, VkDeviceSize size) const\n{\n    json.BeginObject(true);\n\n    json.WriteString(\"Offset\");\n    json.WriteNumber(offset);\n\n    json.WriteString(\"Type\");\n    json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]);\n\n    json.WriteString(\"Size\");\n    json.WriteNumber(size);\n\n    json.EndObject();\n}\n\nvoid VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const\n{\n    json.EndArray();\n}\n#endif // VMA_STATS_STRING_ENABLED\n#endif // _VMA_BLOCK_METADATA_FUNCTIONS\n#endif // _VMA_BLOCK_METADATA\n\n#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY\n// Before deleting object of this class remember to call 'Destroy()'\nclass VmaBlockBufferImageGranularity final\n{\npublic:\n    struct ValidationContext\n    {\n        const VkAllocationCallbacks* allocCallbacks;\n        uint16_t* pageAllocs;\n    };\n\n    VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity);\n    ~VmaBlockBufferImageGranularity();\n\n    bool IsEnabled() const { return m_BufferImageGranularity > MAX_LOW_BUFFER_IMAGE_GRANULARITY; }\n\n    void Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size);\n    // Before destroying object you must call free it's memory\n    void Destroy(const VkAllocationCallbacks* pAllocationCallbacks);\n\n    void RoundupAllocRequest(VmaSuballocationType allocType,\n        VkDeviceSize& inOutAllocSize,\n        VkDeviceSize& inOutAllocAlignment) const;\n\n    bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,\n        VkDeviceSize allocSize,\n        VkDeviceSize blockOffset,\n        VkDeviceSize blockSize,\n        VmaSuballocationType allocType) const;\n\n    void AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size);\n    void FreePages(VkDeviceSize offset, VkDeviceSize size);\n    void Clear();\n\n    ValidationContext StartValidation(const VkAllocationCallbacks* pAllocationCallbacks,\n        bool isVirutal) const;\n    bool Validate(ValidationContext& ctx, VkDeviceSize offset, VkDeviceSize size) const;\n    bool FinishValidation(ValidationContext& ctx) const;\n\nprivate:\n    static const uint16_t MAX_LOW_BUFFER_IMAGE_GRANULARITY = 256;\n\n    struct RegionInfo\n    {\n        uint8_t allocType;\n        uint16_t allocCount;\n    };\n\n    VkDeviceSize m_BufferImageGranularity;\n    uint32_t m_RegionCount;\n    RegionInfo* m_RegionInfo;\n\n    uint32_t GetStartPage(VkDeviceSize offset) const { return OffsetToPageIndex(offset & ~(m_BufferImageGranularity - 1)); }\n    uint32_t GetEndPage(VkDeviceSize offset, VkDeviceSize size) const { return OffsetToPageIndex((offset + size - 1) & ~(m_BufferImageGranularity - 1)); }\n\n    uint32_t OffsetToPageIndex(VkDeviceSize offset) const;\n    void AllocPage(RegionInfo& page, uint8_t allocType);\n};\n\n#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS\nVmaBlockBufferImageGranularity::VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity)\n    : m_BufferImageGranularity(bufferImageGranularity),\n    m_RegionCount(0),\n    m_RegionInfo(VMA_NULL) {}\n\nVmaBlockBufferImageGranularity::~VmaBlockBufferImageGranularity()\n{\n    VMA_ASSERT(m_RegionInfo == VMA_NULL && \"Free not called before destroying object!\");\n}\n\nvoid VmaBlockBufferImageGranularity::Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size)\n{\n    if (IsEnabled())\n    {\n        m_RegionCount = static_cast<uint32_t>(VmaDivideRoundingUp(size, m_BufferImageGranularity));\n        m_RegionInfo = vma_new_array(pAllocationCallbacks, RegionInfo, m_RegionCount);\n        memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo));\n    }\n}\n\nvoid VmaBlockBufferImageGranularity::Destroy(const VkAllocationCallbacks* pAllocationCallbacks)\n{\n    if (m_RegionInfo)\n    {\n        vma_delete_array(pAllocationCallbacks, m_RegionInfo, m_RegionCount);\n        m_RegionInfo = VMA_NULL;\n    }\n}\n\nvoid VmaBlockBufferImageGranularity::RoundupAllocRequest(VmaSuballocationType allocType,\n    VkDeviceSize& inOutAllocSize,\n    VkDeviceSize& inOutAllocAlignment) const\n{\n    if (m_BufferImageGranularity > 1 &&\n        m_BufferImageGranularity <= MAX_LOW_BUFFER_IMAGE_GRANULARITY)\n    {\n        if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||\n            allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||\n            allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)\n        {\n            inOutAllocAlignment = VMA_MAX(inOutAllocAlignment, m_BufferImageGranularity);\n            inOutAllocSize = VmaAlignUp(inOutAllocSize, m_BufferImageGranularity);\n        }\n    }\n}\n\nbool VmaBlockBufferImageGranularity::CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,\n    VkDeviceSize allocSize,\n    VkDeviceSize blockOffset,\n    VkDeviceSize blockSize,\n    VmaSuballocationType allocType) const\n{\n    if (IsEnabled())\n    {\n        uint32_t startPage = GetStartPage(inOutAllocOffset);\n        if (m_RegionInfo[startPage].allocCount > 0 &&\n            VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))\n        {\n            inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);\n            if (blockSize < allocSize + inOutAllocOffset - blockOffset)\n                return true;\n            ++startPage;\n        }\n        uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);\n        if (endPage != startPage &&\n            m_RegionInfo[endPage].allocCount > 0 &&\n            VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))\n        {\n            return true;\n        }\n    }\n    return false;\n}\n\nvoid VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size)\n{\n    if (IsEnabled())\n    {\n        uint32_t startPage = GetStartPage(offset);\n        AllocPage(m_RegionInfo[startPage], allocType);\n\n        uint32_t endPage = GetEndPage(offset, size);\n        if (startPage != endPage)\n            AllocPage(m_RegionInfo[endPage], allocType);\n    }\n}\n\nvoid VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size)\n{\n    if (IsEnabled())\n    {\n        uint32_t startPage = GetStartPage(offset);\n        --m_RegionInfo[startPage].allocCount;\n        if (m_RegionInfo[startPage].allocCount == 0)\n            m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;\n        uint32_t endPage = GetEndPage(offset, size);\n        if (startPage != endPage)\n        {\n            --m_RegionInfo[endPage].allocCount;\n            if (m_RegionInfo[endPage].allocCount == 0)\n                m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;\n        }\n    }\n}\n\nvoid VmaBlockBufferImageGranularity::Clear()\n{\n    if (m_RegionInfo)\n        memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo));\n}\n\nVmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity::StartValidation(\n    const VkAllocationCallbacks* pAllocationCallbacks, bool isVirutal) const\n{\n    ValidationContext ctx{ pAllocationCallbacks, VMA_NULL };\n    if (!isVirutal && IsEnabled())\n    {\n        ctx.pageAllocs = vma_new_array(pAllocationCallbacks, uint16_t, m_RegionCount);\n        memset(ctx.pageAllocs, 0, m_RegionCount * sizeof(uint16_t));\n    }\n    return ctx;\n}\n\nbool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx,\n    VkDeviceSize offset, VkDeviceSize size) const\n{\n    if (IsEnabled())\n    {\n        uint32_t start = GetStartPage(offset);\n        ++ctx.pageAllocs[start];\n        VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);\n\n        uint32_t end = GetEndPage(offset, size);\n        if (start != end)\n        {\n            ++ctx.pageAllocs[end];\n            VMA_VALIDATE(m_RegionInfo[end].allocCount > 0);\n        }\n    }\n    return true;\n}\n\nbool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const\n{\n    // Check proper page structure\n    if (IsEnabled())\n    {\n        VMA_ASSERT(ctx.pageAllocs != VMA_NULL && \"Validation context not initialized!\");\n\n        for (uint32_t page = 0; page < m_RegionCount; ++page)\n        {\n            VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);\n        }\n        vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount);\n        ctx.pageAllocs = VMA_NULL;\n    }\n    return true;\n}\n\nuint32_t VmaBlockBufferImageGranularity::OffsetToPageIndex(VkDeviceSize offset) const\n{\n    return static_cast<uint32_t>(offset >> VMA_BITSCAN_MSB(m_BufferImageGranularity));\n}\n\nvoid VmaBlockBufferImageGranularity::AllocPage(RegionInfo& page, uint8_t allocType)\n{\n    // When current alloc type is free then it can be overridden by new type\n    if (page.allocCount == 0 || (page.allocCount > 0 && page.allocType == VMA_SUBALLOCATION_TYPE_FREE))\n        page.allocType = allocType;\n\n    ++page.allocCount;\n}\n#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS\n#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY\n\n#if 0\n#ifndef _VMA_BLOCK_METADATA_GENERIC\nclass VmaBlockMetadata_Generic : public VmaBlockMetadata\n{\n    friend class VmaDefragmentationAlgorithm_Generic;\n    friend class VmaDefragmentationAlgorithm_Fast;\n    VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)\npublic:\n    VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks,\n        VkDeviceSize bufferImageGranularity, bool isVirtual);\n    virtual ~VmaBlockMetadata_Generic() = default;\n\n    size_t GetAllocationCount() const override { return m_Suballocations.size() - m_FreeCount; }\n    VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; }\n    bool IsEmpty() const override { return (m_Suballocations.size() == 1) && (m_FreeCount == 1); }\n    void Free(VmaAllocHandle allocHandle) override { FreeSuballocation(FindAtOffset((VkDeviceSize)allocHandle - 1)); }\n    VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; }\n\n    void Init(VkDeviceSize size) override;\n    bool Validate() const override;\n\n    void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;\n    void AddStatistics(VmaStatistics& inoutStats) const override;\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const override;\n#endif\n\n    bool CreateAllocationRequest(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        bool upperAddress,\n        VmaSuballocationType allocType,\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest) override;\n\n    VkResult CheckCorruption(const void* pBlockData) override;\n\n    void Alloc(\n        const VmaAllocationRequest& request,\n        VmaSuballocationType type,\n        void* userData) override;\n\n    void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;\n    void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;\n    VmaAllocHandle GetAllocationListBegin() const override;\n    VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;\n    void Clear() override;\n    void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;\n    void DebugLogAllAllocations() const override;\n\nprivate:\n    uint32_t m_FreeCount;\n    VkDeviceSize m_SumFreeSize;\n    VmaSuballocationList m_Suballocations;\n    // Suballocations that are free. Sorted by size, ascending.\n    VmaVector<VmaSuballocationList::iterator, VmaStlAllocator<VmaSuballocationList::iterator>> m_FreeSuballocationsBySize;\n\n    VkDeviceSize AlignAllocationSize(VkDeviceSize size) const { return IsVirtual() ? size : VmaAlignUp(size, (VkDeviceSize)16); }\n\n    VmaSuballocationList::iterator FindAtOffset(VkDeviceSize offset) const;\n    bool ValidateFreeSuballocationList() const;\n\n    // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.\n    // If yes, fills pOffset and returns true. If no, returns false.\n    bool CheckAllocation(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        VmaSuballocationType allocType,\n        VmaSuballocationList::const_iterator suballocItem,\n        VmaAllocHandle* pAllocHandle) const;\n\n    // Given free suballocation, it merges it with following one, which must also be free.\n    void MergeFreeWithNext(VmaSuballocationList::iterator item);\n    // Releases given suballocation, making it free.\n    // Merges it with adjacent free suballocations if applicable.\n    // Returns iterator to new free suballocation at this place.\n    VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);\n    // Given free suballocation, it inserts it into sorted list of\n    // m_FreeSuballocationsBySize if it is suitable.\n    void RegisterFreeSuballocation(VmaSuballocationList::iterator item);\n    // Given free suballocation, it removes it from sorted list of\n    // m_FreeSuballocationsBySize if it is suitable.\n    void UnregisterFreeSuballocation(VmaSuballocationList::iterator item);\n};\n\n#ifndef _VMA_BLOCK_METADATA_GENERIC_FUNCTIONS\nVmaBlockMetadata_Generic::VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks,\n    VkDeviceSize bufferImageGranularity, bool isVirtual)\n    : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),\n    m_FreeCount(0),\n    m_SumFreeSize(0),\n    m_Suballocations(VmaStlAllocator<VmaSuballocation>(pAllocationCallbacks)),\n    m_FreeSuballocationsBySize(VmaStlAllocator<VmaSuballocationList::iterator>(pAllocationCallbacks)) {}\n\nvoid VmaBlockMetadata_Generic::Init(VkDeviceSize size)\n{\n    VmaBlockMetadata::Init(size);\n\n    m_FreeCount = 1;\n    m_SumFreeSize = size;\n\n    VmaSuballocation suballoc = {};\n    suballoc.offset = 0;\n    suballoc.size = size;\n    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;\n\n    m_Suballocations.push_back(suballoc);\n    m_FreeSuballocationsBySize.push_back(m_Suballocations.begin());\n}\n\nbool VmaBlockMetadata_Generic::Validate() const\n{\n    VMA_VALIDATE(!m_Suballocations.empty());\n\n    // Expected offset of new suballocation as calculated from previous ones.\n    VkDeviceSize calculatedOffset = 0;\n    // Expected number of free suballocations as calculated from traversing their list.\n    uint32_t calculatedFreeCount = 0;\n    // Expected sum size of free suballocations as calculated from traversing their list.\n    VkDeviceSize calculatedSumFreeSize = 0;\n    // Expected number of free suballocations that should be registered in\n    // m_FreeSuballocationsBySize calculated from traversing their list.\n    size_t freeSuballocationsToRegister = 0;\n    // True if previous visited suballocation was free.\n    bool prevFree = false;\n\n    const VkDeviceSize debugMargin = GetDebugMargin();\n\n    for (const auto& subAlloc : m_Suballocations)\n    {\n        // Actual offset of this suballocation doesn't match expected one.\n        VMA_VALIDATE(subAlloc.offset == calculatedOffset);\n\n        const bool currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE);\n        // Two adjacent free suballocations are invalid. They should be merged.\n        VMA_VALIDATE(!prevFree || !currFree);\n\n        VmaAllocation alloc = (VmaAllocation)subAlloc.userData;\n        if (!IsVirtual())\n        {\n            VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));\n        }\n\n        if (currFree)\n        {\n            calculatedSumFreeSize += subAlloc.size;\n            ++calculatedFreeCount;\n            ++freeSuballocationsToRegister;\n\n            // Margin required between allocations - every free space must be at least that large.\n            VMA_VALIDATE(subAlloc.size >= debugMargin);\n        }\n        else\n        {\n            if (!IsVirtual())\n            {\n                VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == subAlloc.offset + 1);\n                VMA_VALIDATE(alloc->GetSize() == subAlloc.size);\n            }\n\n            // Margin required between allocations - previous allocation must be free.\n            VMA_VALIDATE(debugMargin == 0 || prevFree);\n        }\n\n        calculatedOffset += subAlloc.size;\n        prevFree = currFree;\n    }\n\n    // Number of free suballocations registered in m_FreeSuballocationsBySize doesn't\n    // match expected one.\n    VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);\n\n    VkDeviceSize lastSize = 0;\n    for (size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)\n    {\n        VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];\n\n        // Only free suballocations can be registered in m_FreeSuballocationsBySize.\n        VMA_VALIDATE(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE);\n        // They must be sorted by size ascending.\n        VMA_VALIDATE(suballocItem->size >= lastSize);\n\n        lastSize = suballocItem->size;\n    }\n\n    // Check if totals match calculated values.\n    VMA_VALIDATE(ValidateFreeSuballocationList());\n    VMA_VALIDATE(calculatedOffset == GetSize());\n    VMA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize);\n    VMA_VALIDATE(calculatedFreeCount == m_FreeCount);\n\n    return true;\n}\n\nvoid VmaBlockMetadata_Generic::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const\n{\n    const uint32_t rangeCount = (uint32_t)m_Suballocations.size();\n    inoutStats.statistics.blockCount++;\n    inoutStats.statistics.blockBytes += GetSize();\n\n    for (const auto& suballoc : m_Suballocations)\n    {\n        if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)\n            VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);\n        else\n            VmaAddDetailedStatisticsUnusedRange(inoutStats, suballoc.size);\n    }\n}\n\nvoid VmaBlockMetadata_Generic::AddStatistics(VmaStatistics& inoutStats) const\n{\n    inoutStats.blockCount++;\n    inoutStats.allocationCount += (uint32_t)m_Suballocations.size() - m_FreeCount;\n    inoutStats.blockBytes += GetSize();\n    inoutStats.allocationBytes += GetSize() - m_SumFreeSize;\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const\n{\n    PrintDetailedMap_Begin(json,\n        m_SumFreeSize, // unusedBytes\n        m_Suballocations.size() - (size_t)m_FreeCount, // allocationCount\n        m_FreeCount, // unusedRangeCount\n        mapRefCount);\n\n    for (const auto& suballoc : m_Suballocations)\n    {\n        if (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            PrintDetailedMap_UnusedRange(json, suballoc.offset, suballoc.size);\n        }\n        else\n        {\n            PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);\n        }\n    }\n\n    PrintDetailedMap_End(json);\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nbool VmaBlockMetadata_Generic::CreateAllocationRequest(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    bool upperAddress,\n    VmaSuballocationType allocType,\n    uint32_t strategy,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    VMA_ASSERT(allocSize > 0);\n    VMA_ASSERT(!upperAddress);\n    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);\n    VMA_ASSERT(pAllocationRequest != VMA_NULL);\n    VMA_HEAVY_ASSERT(Validate());\n\n    allocSize = AlignAllocationSize(allocSize);\n\n    pAllocationRequest->type = VmaAllocationRequestType::Normal;\n    pAllocationRequest->size = allocSize;\n\n    const VkDeviceSize debugMargin = GetDebugMargin();\n\n    // There is not enough total free space in this block to fulfill the request: Early return.\n    if (m_SumFreeSize < allocSize + debugMargin)\n    {\n        return false;\n    }\n\n    // New algorithm, efficiently searching freeSuballocationsBySize.\n    const size_t freeSuballocCount = m_FreeSuballocationsBySize.size();\n    if (freeSuballocCount > 0)\n    {\n        if (strategy == 0 ||\n            strategy == VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT)\n        {\n            // Find first free suballocation with size not less than allocSize + debugMargin.\n            VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(\n                m_FreeSuballocationsBySize.data(),\n                m_FreeSuballocationsBySize.data() + freeSuballocCount,\n                allocSize + debugMargin,\n                VmaSuballocationItemSizeLess());\n            size_t index = it - m_FreeSuballocationsBySize.data();\n            for (; index < freeSuballocCount; ++index)\n            {\n                if (CheckAllocation(\n                    allocSize,\n                    allocAlignment,\n                    allocType,\n                    m_FreeSuballocationsBySize[index],\n                    &pAllocationRequest->allocHandle))\n                {\n                    pAllocationRequest->item = m_FreeSuballocationsBySize[index];\n                    return true;\n                }\n            }\n        }\n        else if (strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)\n        {\n            for (VmaSuballocationList::iterator it = m_Suballocations.begin();\n                it != m_Suballocations.end();\n                ++it)\n            {\n                if (it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation(\n                    allocSize,\n                    allocAlignment,\n                    allocType,\n                    it,\n                    &pAllocationRequest->allocHandle))\n                {\n                    pAllocationRequest->item = it;\n                    return true;\n                }\n            }\n        }\n        else\n        {\n            VMA_ASSERT(strategy & (VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT | VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT ));\n            // Search staring from biggest suballocations.\n            for (size_t index = freeSuballocCount; index--; )\n            {\n                if (CheckAllocation(\n                    allocSize,\n                    allocAlignment,\n                    allocType,\n                    m_FreeSuballocationsBySize[index],\n                    &pAllocationRequest->allocHandle))\n                {\n                    pAllocationRequest->item = m_FreeSuballocationsBySize[index];\n                    return true;\n                }\n            }\n        }\n    }\n\n    return false;\n}\n\nVkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)\n{\n    for (auto& suballoc : m_Suballocations)\n    {\n        if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))\n            {\n                VMA_ASSERT(0 && \"MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!\");\n                return VK_ERROR_UNKNOWN_COPY;\n            }\n        }\n    }\n\n    return VK_SUCCESS;\n}\n\nvoid VmaBlockMetadata_Generic::Alloc(\n    const VmaAllocationRequest& request,\n    VmaSuballocationType type,\n    void* userData)\n{\n    VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);\n    VMA_ASSERT(request.item != m_Suballocations.end());\n    VmaSuballocation& suballoc = *request.item;\n    // Given suballocation is a free block.\n    VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);\n\n    // Given offset is inside this suballocation.\n    VMA_ASSERT((VkDeviceSize)request.allocHandle - 1 >= suballoc.offset);\n    const VkDeviceSize paddingBegin = (VkDeviceSize)request.allocHandle - suballoc.offset - 1;\n    VMA_ASSERT(suballoc.size >= paddingBegin + request.size);\n    const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - request.size;\n\n    // Unregister this free suballocation from m_FreeSuballocationsBySize and update\n    // it to become used.\n    UnregisterFreeSuballocation(request.item);\n\n    suballoc.offset = (VkDeviceSize)request.allocHandle - 1;\n    suballoc.size = request.size;\n    suballoc.type = type;\n    suballoc.userData = userData;\n\n    // If there are any free bytes remaining at the end, insert new free suballocation after current one.\n    if (paddingEnd)\n    {\n        VmaSuballocation paddingSuballoc = {};\n        paddingSuballoc.offset = suballoc.offset + suballoc.size;\n        paddingSuballoc.size = paddingEnd;\n        paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;\n        VmaSuballocationList::iterator next = request.item;\n        ++next;\n        const VmaSuballocationList::iterator paddingEndItem =\n            m_Suballocations.insert(next, paddingSuballoc);\n        RegisterFreeSuballocation(paddingEndItem);\n    }\n\n    // If there are any free bytes remaining at the beginning, insert new free suballocation before current one.\n    if (paddingBegin)\n    {\n        VmaSuballocation paddingSuballoc = {};\n        paddingSuballoc.offset = suballoc.offset - paddingBegin;\n        paddingSuballoc.size = paddingBegin;\n        paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;\n        const VmaSuballocationList::iterator paddingBeginItem =\n            m_Suballocations.insert(request.item, paddingSuballoc);\n        RegisterFreeSuballocation(paddingBeginItem);\n    }\n\n    // Update totals.\n    m_FreeCount = m_FreeCount - 1;\n    if (paddingBegin > 0)\n    {\n        ++m_FreeCount;\n    }\n    if (paddingEnd > 0)\n    {\n        ++m_FreeCount;\n    }\n    m_SumFreeSize -= request.size;\n}\n\nvoid VmaBlockMetadata_Generic::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)\n{\n    outInfo.offset = (VkDeviceSize)allocHandle - 1;\n    const VmaSuballocation& suballoc = *FindAtOffset(outInfo.offset);\n    outInfo.size = suballoc.size;\n    outInfo.pUserData = suballoc.userData;\n}\n\nvoid* VmaBlockMetadata_Generic::GetAllocationUserData(VmaAllocHandle allocHandle) const\n{\n    return FindAtOffset((VkDeviceSize)allocHandle - 1)->userData;\n}\n\nVmaAllocHandle VmaBlockMetadata_Generic::GetAllocationListBegin() const\n{\n    if (IsEmpty())\n        return VK_NULL_HANDLE;\n\n    for (const auto& suballoc : m_Suballocations)\n    {\n        if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)\n            return (VmaAllocHandle)(suballoc.offset + 1);\n    }\n    VMA_ASSERT(false && \"Should contain at least 1 allocation!\");\n    return VK_NULL_HANDLE;\n}\n\nVmaAllocHandle VmaBlockMetadata_Generic::GetNextAllocation(VmaAllocHandle prevAlloc) const\n{\n    VmaSuballocationList::const_iterator prev = FindAtOffset((VkDeviceSize)prevAlloc - 1);\n\n    for (VmaSuballocationList::const_iterator it = ++prev; it != m_Suballocations.end(); ++it)\n    {\n        if (it->type != VMA_SUBALLOCATION_TYPE_FREE)\n            return (VmaAllocHandle)(it->offset + 1);\n    }\n    return VK_NULL_HANDLE;\n}\n\nvoid VmaBlockMetadata_Generic::Clear()\n{\n    const VkDeviceSize size = GetSize();\n\n    VMA_ASSERT(IsVirtual());\n    m_FreeCount = 1;\n    m_SumFreeSize = size;\n    m_Suballocations.clear();\n    m_FreeSuballocationsBySize.clear();\n\n    VmaSuballocation suballoc = {};\n    suballoc.offset = 0;\n    suballoc.size = size;\n    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;\n    m_Suballocations.push_back(suballoc);\n\n    m_FreeSuballocationsBySize.push_back(m_Suballocations.begin());\n}\n\nvoid VmaBlockMetadata_Generic::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)\n{\n    VmaSuballocation& suballoc = *FindAtOffset((VkDeviceSize)allocHandle - 1);\n    suballoc.userData = userData;\n}\n\nvoid VmaBlockMetadata_Generic::DebugLogAllAllocations() const\n{\n    for (const auto& suballoc : m_Suballocations)\n    {\n        if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)\n            DebugLogAllocation(suballoc.offset, suballoc.size, suballoc.userData);\n    }\n}\n\nVmaSuballocationList::iterator VmaBlockMetadata_Generic::FindAtOffset(VkDeviceSize offset) const\n{\n    VMA_HEAVY_ASSERT(!m_Suballocations.empty());\n    const VkDeviceSize last = m_Suballocations.rbegin()->offset;\n    if (last == offset)\n        return m_Suballocations.rbegin().drop_const();\n    const VkDeviceSize first = m_Suballocations.begin()->offset;\n    if (first == offset)\n        return m_Suballocations.begin().drop_const();\n\n    const size_t suballocCount = m_Suballocations.size();\n    const VkDeviceSize step = (last - first + m_Suballocations.begin()->size) / suballocCount;\n    auto findSuballocation = [&](auto begin, auto end) -> VmaSuballocationList::iterator\n    {\n        for (auto suballocItem = begin;\n            suballocItem != end;\n            ++suballocItem)\n        {\n            if (suballocItem->offset == offset)\n                return suballocItem.drop_const();\n        }\n        VMA_ASSERT(false && \"Not found!\");\n        return m_Suballocations.end().drop_const();\n    };\n    // If requested offset is closer to the end of range, search from the end\n    if (offset - first > suballocCount * step / 2)\n    {\n        return findSuballocation(m_Suballocations.rbegin(), m_Suballocations.rend());\n    }\n    return findSuballocation(m_Suballocations.begin(), m_Suballocations.end());\n}\n\nbool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const\n{\n    VkDeviceSize lastSize = 0;\n    for (size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)\n    {\n        const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i];\n\n        VMA_VALIDATE(it->type == VMA_SUBALLOCATION_TYPE_FREE);\n        VMA_VALIDATE(it->size >= lastSize);\n        lastSize = it->size;\n    }\n    return true;\n}\n\nbool VmaBlockMetadata_Generic::CheckAllocation(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    VmaSuballocationType allocType,\n    VmaSuballocationList::const_iterator suballocItem,\n    VmaAllocHandle* pAllocHandle) const\n{\n    VMA_ASSERT(allocSize > 0);\n    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);\n    VMA_ASSERT(suballocItem != m_Suballocations.cend());\n    VMA_ASSERT(pAllocHandle != VMA_NULL);\n\n    const VkDeviceSize debugMargin = GetDebugMargin();\n    const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity();\n\n    const VmaSuballocation& suballoc = *suballocItem;\n    VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);\n\n    // Size of this suballocation is too small for this request: Early return.\n    if (suballoc.size < allocSize)\n    {\n        return false;\n    }\n\n    // Start from offset equal to beginning of this suballocation.\n    VkDeviceSize offset = suballoc.offset + (suballocItem == m_Suballocations.cbegin() ? 0 : GetDebugMargin());\n\n    // Apply debugMargin from the end of previous alloc.\n    if (debugMargin > 0)\n    {\n        offset += debugMargin;\n    }\n\n    // Apply alignment.\n    offset = VmaAlignUp(offset, allocAlignment);\n\n    // Check previous suballocations for BufferImageGranularity conflicts.\n    // Make bigger alignment if necessary.\n    if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment)\n    {\n        bool bufferImageGranularityConflict = false;\n        VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;\n        while (prevSuballocItem != m_Suballocations.cbegin())\n        {\n            --prevSuballocItem;\n            const VmaSuballocation& prevSuballoc = *prevSuballocItem;\n            if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, offset, bufferImageGranularity))\n            {\n                if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))\n                {\n                    bufferImageGranularityConflict = true;\n                    break;\n                }\n            }\n            else\n                // Already on previous page.\n                break;\n        }\n        if (bufferImageGranularityConflict)\n        {\n            offset = VmaAlignUp(offset, bufferImageGranularity);\n        }\n    }\n\n    // Calculate padding at the beginning based on current offset.\n    const VkDeviceSize paddingBegin = offset - suballoc.offset;\n\n    // Fail if requested size plus margin after is bigger than size of this suballocation.\n    if (paddingBegin + allocSize + debugMargin > suballoc.size)\n    {\n        return false;\n    }\n\n    // Check next suballocations for BufferImageGranularity conflicts.\n    // If conflict exists, allocation cannot be made here.\n    if (allocSize % bufferImageGranularity || offset % bufferImageGranularity)\n    {\n        VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;\n        ++nextSuballocItem;\n        while (nextSuballocItem != m_Suballocations.cend())\n        {\n            const VmaSuballocation& nextSuballoc = *nextSuballocItem;\n            if (VmaBlocksOnSamePage(offset, allocSize, nextSuballoc.offset, bufferImageGranularity))\n            {\n                if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))\n                {\n                    return false;\n                }\n            }\n            else\n            {\n                // Already on next page.\n                break;\n            }\n            ++nextSuballocItem;\n        }\n    }\n\n    *pAllocHandle = (VmaAllocHandle)(offset + 1);\n    // All tests passed: Success. pAllocHandle is already filled.\n    return true;\n}\n\nvoid VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item)\n{\n    VMA_ASSERT(item != m_Suballocations.end());\n    VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);\n\n    VmaSuballocationList::iterator nextItem = item;\n    ++nextItem;\n    VMA_ASSERT(nextItem != m_Suballocations.end());\n    VMA_ASSERT(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE);\n\n    item->size += nextItem->size;\n    --m_FreeCount;\n    m_Suballocations.erase(nextItem);\n}\n\nVmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem)\n{\n    // Change this suballocation to be marked as free.\n    VmaSuballocation& suballoc = *suballocItem;\n    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;\n    suballoc.userData = VMA_NULL;\n\n    // Update totals.\n    ++m_FreeCount;\n    m_SumFreeSize += suballoc.size;\n\n    // Merge with previous and/or next suballocation if it's also free.\n    bool mergeWithNext = false;\n    bool mergeWithPrev = false;\n\n    VmaSuballocationList::iterator nextItem = suballocItem;\n    ++nextItem;\n    if ((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE))\n    {\n        mergeWithNext = true;\n    }\n\n    VmaSuballocationList::iterator prevItem = suballocItem;\n    if (suballocItem != m_Suballocations.begin())\n    {\n        --prevItem;\n        if (prevItem->type == VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            mergeWithPrev = true;\n        }\n    }\n\n    if (mergeWithNext)\n    {\n        UnregisterFreeSuballocation(nextItem);\n        MergeFreeWithNext(suballocItem);\n    }\n\n    if (mergeWithPrev)\n    {\n        UnregisterFreeSuballocation(prevItem);\n        MergeFreeWithNext(prevItem);\n        RegisterFreeSuballocation(prevItem);\n        return prevItem;\n    }\n    else\n    {\n        RegisterFreeSuballocation(suballocItem);\n        return suballocItem;\n    }\n}\n\nvoid VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item)\n{\n    VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);\n    VMA_ASSERT(item->size > 0);\n\n    // You may want to enable this validation at the beginning or at the end of\n    // this function, depending on what do you want to check.\n    VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());\n\n    if (m_FreeSuballocationsBySize.empty())\n    {\n        m_FreeSuballocationsBySize.push_back(item);\n    }\n    else\n    {\n        VmaVectorInsertSorted<VmaSuballocationItemSizeLess>(m_FreeSuballocationsBySize, item);\n    }\n\n    //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());\n}\n\nvoid VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)\n{\n    VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);\n    VMA_ASSERT(item->size > 0);\n\n    // You may want to enable this validation at the beginning or at the end of\n    // this function, depending on what do you want to check.\n    VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());\n\n    VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(\n        m_FreeSuballocationsBySize.data(),\n        m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),\n        item,\n        VmaSuballocationItemSizeLess());\n    for (size_t index = it - m_FreeSuballocationsBySize.data();\n        index < m_FreeSuballocationsBySize.size();\n        ++index)\n    {\n        if (m_FreeSuballocationsBySize[index] == item)\n        {\n            VmaVectorRemove(m_FreeSuballocationsBySize, index);\n            return;\n        }\n        VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && \"Not found.\");\n    }\n    VMA_ASSERT(0 && \"Not found.\");\n\n    //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());\n}\n#endif // _VMA_BLOCK_METADATA_GENERIC_FUNCTIONS\n#endif // _VMA_BLOCK_METADATA_GENERIC\n#endif // #if 0\n\n#ifndef _VMA_BLOCK_METADATA_LINEAR\n/*\nAllocations and their references in internal data structure look like this:\n\nif(m_2ndVectorMode == SECOND_VECTOR_EMPTY):\n\n        0 +-------+\n          |       |\n          |       |\n          |       |\n          +-------+\n          | Alloc |  1st[m_1stNullItemsBeginCount]\n          +-------+\n          | Alloc |  1st[m_1stNullItemsBeginCount + 1]\n          +-------+\n          |  ...  |\n          +-------+\n          | Alloc |  1st[1st.size() - 1]\n          +-------+\n          |       |\n          |       |\n          |       |\nGetSize() +-------+\n\nif(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):\n\n        0 +-------+\n          | Alloc |  2nd[0]\n          +-------+\n          | Alloc |  2nd[1]\n          +-------+\n          |  ...  |\n          +-------+\n          | Alloc |  2nd[2nd.size() - 1]\n          +-------+\n          |       |\n          |       |\n          |       |\n          +-------+\n          | Alloc |  1st[m_1stNullItemsBeginCount]\n          +-------+\n          | Alloc |  1st[m_1stNullItemsBeginCount + 1]\n          +-------+\n          |  ...  |\n          +-------+\n          | Alloc |  1st[1st.size() - 1]\n          +-------+\n          |       |\nGetSize() +-------+\n\nif(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):\n\n        0 +-------+\n          |       |\n          |       |\n          |       |\n          +-------+\n          | Alloc |  1st[m_1stNullItemsBeginCount]\n          +-------+\n          | Alloc |  1st[m_1stNullItemsBeginCount + 1]\n          +-------+\n          |  ...  |\n          +-------+\n          | Alloc |  1st[1st.size() - 1]\n          +-------+\n          |       |\n          |       |\n          |       |\n          +-------+\n          | Alloc |  2nd[2nd.size() - 1]\n          +-------+\n          |  ...  |\n          +-------+\n          | Alloc |  2nd[1]\n          +-------+\n          | Alloc |  2nd[0]\nGetSize() +-------+\n\n*/\nclass VmaBlockMetadata_Linear : public VmaBlockMetadata\n{\n    VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)\npublic:\n    VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks,\n        VkDeviceSize bufferImageGranularity, bool isVirtual);\n    virtual ~VmaBlockMetadata_Linear() = default;\n\n    VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; }\n    bool IsEmpty() const override { return GetAllocationCount() == 0; }\n    VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; }\n\n    void Init(VkDeviceSize size) override;\n    bool Validate() const override;\n    size_t GetAllocationCount() const override;\n    size_t GetFreeRegionsCount() const override;\n\n    void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;\n    void AddStatistics(VmaStatistics& inoutStats) const override;\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMap(class VmaJsonWriter& json) const override;\n#endif\n\n    bool CreateAllocationRequest(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        bool upperAddress,\n        VmaSuballocationType allocType,\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest) override;\n\n    VkResult CheckCorruption(const void* pBlockData) override;\n\n    void Alloc(\n        const VmaAllocationRequest& request,\n        VmaSuballocationType type,\n        void* userData) override;\n\n    void Free(VmaAllocHandle allocHandle) override;\n    void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;\n    void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;\n    VmaAllocHandle GetAllocationListBegin() const override;\n    VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;\n    VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const override;\n    void Clear() override;\n    void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;\n    void DebugLogAllAllocations() const override;\n\nprivate:\n    /*\n    There are two suballocation vectors, used in ping-pong way.\n    The one with index m_1stVectorIndex is called 1st.\n    The one with index (m_1stVectorIndex ^ 1) is called 2nd.\n    2nd can be non-empty only when 1st is not empty.\n    When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.\n    */\n    typedef VmaVector<VmaSuballocation, VmaStlAllocator<VmaSuballocation>> SuballocationVectorType;\n\n    enum SECOND_VECTOR_MODE\n    {\n        SECOND_VECTOR_EMPTY,\n        /*\n        Suballocations in 2nd vector are created later than the ones in 1st, but they\n        all have smaller offset.\n        */\n        SECOND_VECTOR_RING_BUFFER,\n        /*\n        Suballocations in 2nd vector are upper side of double stack.\n        They all have offsets higher than those in 1st vector.\n        Top of this stack means smaller offsets, but higher indices in this vector.\n        */\n        SECOND_VECTOR_DOUBLE_STACK,\n    };\n\n    VkDeviceSize m_SumFreeSize;\n    SuballocationVectorType m_Suballocations0, m_Suballocations1;\n    uint32_t m_1stVectorIndex;\n    SECOND_VECTOR_MODE m_2ndVectorMode;\n    // Number of items in 1st vector with hAllocation = null at the beginning.\n    size_t m_1stNullItemsBeginCount;\n    // Number of other items in 1st vector with hAllocation = null somewhere in the middle.\n    size_t m_1stNullItemsMiddleCount;\n    // Number of items in 2nd vector with hAllocation = null.\n    size_t m_2ndNullItemsCount;\n\n    SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }\n    SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }\n    const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }\n    const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }\n\n    VmaSuballocation& FindSuballocation(VkDeviceSize offset) const;\n    bool ShouldCompact1st() const;\n    void CleanupAfterFree();\n\n    bool CreateAllocationRequest_LowerAddress(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        VmaSuballocationType allocType,\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest);\n    bool CreateAllocationRequest_UpperAddress(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        VmaSuballocationType allocType,\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest);\n};\n\n#ifndef _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS\nVmaBlockMetadata_Linear::VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks,\n    VkDeviceSize bufferImageGranularity, bool isVirtual)\n    : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),\n    m_SumFreeSize(0),\n    m_Suballocations0(VmaStlAllocator<VmaSuballocation>(pAllocationCallbacks)),\n    m_Suballocations1(VmaStlAllocator<VmaSuballocation>(pAllocationCallbacks)),\n    m_1stVectorIndex(0),\n    m_2ndVectorMode(SECOND_VECTOR_EMPTY),\n    m_1stNullItemsBeginCount(0),\n    m_1stNullItemsMiddleCount(0),\n    m_2ndNullItemsCount(0) {}\n\nvoid VmaBlockMetadata_Linear::Init(VkDeviceSize size)\n{\n    VmaBlockMetadata::Init(size);\n    m_SumFreeSize = size;\n}\n\nbool VmaBlockMetadata_Linear::Validate() const\n{\n    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n\n    VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY));\n    VMA_VALIDATE(!suballocations1st.empty() ||\n        suballocations2nd.empty() ||\n        m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER);\n\n    if (!suballocations1st.empty())\n    {\n        // Null item at the beginning should be accounted into m_1stNullItemsBeginCount.\n        VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].type != VMA_SUBALLOCATION_TYPE_FREE);\n        // Null item at the end should be just pop_back().\n        VMA_VALIDATE(suballocations1st.back().type != VMA_SUBALLOCATION_TYPE_FREE);\n    }\n    if (!suballocations2nd.empty())\n    {\n        // Null item at the end should be just pop_back().\n        VMA_VALIDATE(suballocations2nd.back().type != VMA_SUBALLOCATION_TYPE_FREE);\n    }\n\n    VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size());\n    VMA_VALIDATE(m_2ndNullItemsCount <= suballocations2nd.size());\n\n    VkDeviceSize sumUsedSize = 0;\n    const size_t suballoc1stCount = suballocations1st.size();\n    const VkDeviceSize debugMargin = GetDebugMargin();\n    VkDeviceSize offset = 0;\n\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        const size_t suballoc2ndCount = suballocations2nd.size();\n        size_t nullItem2ndCount = 0;\n        for (size_t i = 0; i < suballoc2ndCount; ++i)\n        {\n            const VmaSuballocation& suballoc = suballocations2nd[i];\n            const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);\n\n            VmaAllocation const alloc = (VmaAllocation)suballoc.userData;\n            if (!IsVirtual())\n            {\n                VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));\n            }\n            VMA_VALIDATE(suballoc.offset >= offset);\n\n            if (!currFree)\n            {\n                if (!IsVirtual())\n                {\n                    VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1);\n                    VMA_VALIDATE(alloc->GetSize() == suballoc.size);\n                }\n                sumUsedSize += suballoc.size;\n            }\n            else\n            {\n                ++nullItem2ndCount;\n            }\n\n            offset = suballoc.offset + suballoc.size + debugMargin;\n        }\n\n        VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);\n    }\n\n    for (size_t i = 0; i < m_1stNullItemsBeginCount; ++i)\n    {\n        const VmaSuballocation& suballoc = suballocations1st[i];\n        VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE &&\n            suballoc.userData == VMA_NULL);\n    }\n\n    size_t nullItem1stCount = m_1stNullItemsBeginCount;\n\n    for (size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i)\n    {\n        const VmaSuballocation& suballoc = suballocations1st[i];\n        const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);\n\n        VmaAllocation const alloc = (VmaAllocation)suballoc.userData;\n        if (!IsVirtual())\n        {\n            VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));\n        }\n        VMA_VALIDATE(suballoc.offset >= offset);\n        VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree);\n\n        if (!currFree)\n        {\n            if (!IsVirtual())\n            {\n                VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1);\n                VMA_VALIDATE(alloc->GetSize() == suballoc.size);\n            }\n            sumUsedSize += suballoc.size;\n        }\n        else\n        {\n            ++nullItem1stCount;\n        }\n\n        offset = suballoc.offset + suballoc.size + debugMargin;\n    }\n    VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount);\n\n    if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        const size_t suballoc2ndCount = suballocations2nd.size();\n        size_t nullItem2ndCount = 0;\n        for (size_t i = suballoc2ndCount; i--; )\n        {\n            const VmaSuballocation& suballoc = suballocations2nd[i];\n            const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);\n\n            VmaAllocation const alloc = (VmaAllocation)suballoc.userData;\n            if (!IsVirtual())\n            {\n                VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));\n            }\n            VMA_VALIDATE(suballoc.offset >= offset);\n\n            if (!currFree)\n            {\n                if (!IsVirtual())\n                {\n                    VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1);\n                    VMA_VALIDATE(alloc->GetSize() == suballoc.size);\n                }\n                sumUsedSize += suballoc.size;\n            }\n            else\n            {\n                ++nullItem2ndCount;\n            }\n\n            offset = suballoc.offset + suballoc.size + debugMargin;\n        }\n\n        VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);\n    }\n\n    VMA_VALIDATE(offset <= GetSize());\n    VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize);\n\n    return true;\n}\n\nsize_t VmaBlockMetadata_Linear::GetAllocationCount() const\n{\n    return AccessSuballocations1st().size() - m_1stNullItemsBeginCount - m_1stNullItemsMiddleCount +\n        AccessSuballocations2nd().size() - m_2ndNullItemsCount;\n}\n\nsize_t VmaBlockMetadata_Linear::GetFreeRegionsCount() const\n{\n    // Function only used for defragmentation, which is disabled for this algorithm\n    VMA_ASSERT(0);\n    return SIZE_MAX;\n}\n\nvoid VmaBlockMetadata_Linear::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const\n{\n    const VkDeviceSize size = GetSize();\n    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n    const size_t suballoc1stCount = suballocations1st.size();\n    const size_t suballoc2ndCount = suballocations2nd.size();\n\n    inoutStats.statistics.blockCount++;\n    inoutStats.statistics.blockBytes += size;\n\n    VkDeviceSize lastOffset = 0;\n\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;\n        size_t nextAlloc2ndIndex = 0;\n        while (lastOffset < freeSpace2ndTo1stEnd)\n        {\n            // Find next non-null allocation or move nextAllocIndex to the end.\n            while (nextAlloc2ndIndex < suballoc2ndCount &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                ++nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex < suballoc2ndCount)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                    VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                ++nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                // There is free space from lastOffset to freeSpace2ndTo1stEnd.\n                if (lastOffset < freeSpace2ndTo1stEnd)\n                {\n                    const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;\n                    VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);\n                }\n\n                // End of loop.\n                lastOffset = freeSpace2ndTo1stEnd;\n            }\n        }\n    }\n\n    size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;\n    const VkDeviceSize freeSpace1stTo2ndEnd =\n        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;\n    while (lastOffset < freeSpace1stTo2ndEnd)\n    {\n        // Find next non-null allocation or move nextAllocIndex to the end.\n        while (nextAlloc1stIndex < suballoc1stCount &&\n            suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)\n        {\n            ++nextAlloc1stIndex;\n        }\n\n        // Found non-null allocation.\n        if (nextAlloc1stIndex < suballoc1stCount)\n        {\n            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];\n\n            // 1. Process free space before this allocation.\n            if (lastOffset < suballoc.offset)\n            {\n                // There is free space from lastOffset to suballoc.offset.\n                const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);\n            }\n\n            // 2. Process this allocation.\n            // There is allocation with suballoc.offset, suballoc.size.\n            VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);\n\n            // 3. Prepare for next iteration.\n            lastOffset = suballoc.offset + suballoc.size;\n            ++nextAlloc1stIndex;\n        }\n        // We are at the end.\n        else\n        {\n            // There is free space from lastOffset to freeSpace1stTo2ndEnd.\n            if (lastOffset < freeSpace1stTo2ndEnd)\n            {\n                const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;\n                VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);\n            }\n\n            // End of loop.\n            lastOffset = freeSpace1stTo2ndEnd;\n        }\n    }\n\n    if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;\n        while (lastOffset < size)\n        {\n            // Find next non-null allocation or move nextAllocIndex to the end.\n            while (nextAlloc2ndIndex != SIZE_MAX &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                --nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex != SIZE_MAX)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                    VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                --nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                // There is free space from lastOffset to size.\n                if (lastOffset < size)\n                {\n                    const VkDeviceSize unusedRangeSize = size - lastOffset;\n                    VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);\n                }\n\n                // End of loop.\n                lastOffset = size;\n            }\n        }\n    }\n}\n\nvoid VmaBlockMetadata_Linear::AddStatistics(VmaStatistics& inoutStats) const\n{\n    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n    const VkDeviceSize size = GetSize();\n    const size_t suballoc1stCount = suballocations1st.size();\n    const size_t suballoc2ndCount = suballocations2nd.size();\n\n    inoutStats.blockCount++;\n    inoutStats.blockBytes += size;\n    inoutStats.allocationBytes += size - m_SumFreeSize;\n\n    VkDeviceSize lastOffset = 0;\n\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;\n        size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount;\n        while (lastOffset < freeSpace2ndTo1stEnd)\n        {\n            // Find next non-null allocation or move nextAlloc2ndIndex to the end.\n            while (nextAlloc2ndIndex < suballoc2ndCount &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                ++nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex < suballoc2ndCount)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                ++inoutStats.allocationCount;\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                ++nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                if (lastOffset < freeSpace2ndTo1stEnd)\n                {\n                    // There is free space from lastOffset to freeSpace2ndTo1stEnd.\n                    const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;\n                }\n\n                // End of loop.\n                lastOffset = freeSpace2ndTo1stEnd;\n            }\n        }\n    }\n\n    size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;\n    const VkDeviceSize freeSpace1stTo2ndEnd =\n        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;\n    while (lastOffset < freeSpace1stTo2ndEnd)\n    {\n        // Find next non-null allocation or move nextAllocIndex to the end.\n        while (nextAlloc1stIndex < suballoc1stCount &&\n            suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)\n        {\n            ++nextAlloc1stIndex;\n        }\n\n        // Found non-null allocation.\n        if (nextAlloc1stIndex < suballoc1stCount)\n        {\n            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];\n\n            // 1. Process free space before this allocation.\n            if (lastOffset < suballoc.offset)\n            {\n                // There is free space from lastOffset to suballoc.offset.\n                const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n            }\n\n            // 2. Process this allocation.\n            // There is allocation with suballoc.offset, suballoc.size.\n            ++inoutStats.allocationCount;\n\n            // 3. Prepare for next iteration.\n            lastOffset = suballoc.offset + suballoc.size;\n            ++nextAlloc1stIndex;\n        }\n        // We are at the end.\n        else\n        {\n            if (lastOffset < freeSpace1stTo2ndEnd)\n            {\n                // There is free space from lastOffset to freeSpace1stTo2ndEnd.\n                const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;\n            }\n\n            // End of loop.\n            lastOffset = freeSpace1stTo2ndEnd;\n        }\n    }\n\n    if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;\n        while (lastOffset < size)\n        {\n            // Find next non-null allocation or move nextAlloc2ndIndex to the end.\n            while (nextAlloc2ndIndex != SIZE_MAX &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                --nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex != SIZE_MAX)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                ++inoutStats.allocationCount;\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                --nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                if (lastOffset < size)\n                {\n                    // There is free space from lastOffset to size.\n                    const VkDeviceSize unusedRangeSize = size - lastOffset;\n                }\n\n                // End of loop.\n                lastOffset = size;\n            }\n        }\n    }\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const\n{\n    const VkDeviceSize size = GetSize();\n    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n    const size_t suballoc1stCount = suballocations1st.size();\n    const size_t suballoc2ndCount = suballocations2nd.size();\n\n    // FIRST PASS\n\n    size_t unusedRangeCount = 0;\n    VkDeviceSize usedBytes = 0;\n\n    VkDeviceSize lastOffset = 0;\n\n    size_t alloc2ndCount = 0;\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;\n        size_t nextAlloc2ndIndex = 0;\n        while (lastOffset < freeSpace2ndTo1stEnd)\n        {\n            // Find next non-null allocation or move nextAlloc2ndIndex to the end.\n            while (nextAlloc2ndIndex < suballoc2ndCount &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                ++nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex < suballoc2ndCount)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    ++unusedRangeCount;\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                ++alloc2ndCount;\n                usedBytes += suballoc.size;\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                ++nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                if (lastOffset < freeSpace2ndTo1stEnd)\n                {\n                    // There is free space from lastOffset to freeSpace2ndTo1stEnd.\n                    ++unusedRangeCount;\n                }\n\n                // End of loop.\n                lastOffset = freeSpace2ndTo1stEnd;\n            }\n        }\n    }\n\n    size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;\n    size_t alloc1stCount = 0;\n    const VkDeviceSize freeSpace1stTo2ndEnd =\n        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;\n    while (lastOffset < freeSpace1stTo2ndEnd)\n    {\n        // Find next non-null allocation or move nextAllocIndex to the end.\n        while (nextAlloc1stIndex < suballoc1stCount &&\n            suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)\n        {\n            ++nextAlloc1stIndex;\n        }\n\n        // Found non-null allocation.\n        if (nextAlloc1stIndex < suballoc1stCount)\n        {\n            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];\n\n            // 1. Process free space before this allocation.\n            if (lastOffset < suballoc.offset)\n            {\n                // There is free space from lastOffset to suballoc.offset.\n                ++unusedRangeCount;\n            }\n\n            // 2. Process this allocation.\n            // There is allocation with suballoc.offset, suballoc.size.\n            ++alloc1stCount;\n            usedBytes += suballoc.size;\n\n            // 3. Prepare for next iteration.\n            lastOffset = suballoc.offset + suballoc.size;\n            ++nextAlloc1stIndex;\n        }\n        // We are at the end.\n        else\n        {\n            if (lastOffset < size)\n            {\n                // There is free space from lastOffset to freeSpace1stTo2ndEnd.\n                ++unusedRangeCount;\n            }\n\n            // End of loop.\n            lastOffset = freeSpace1stTo2ndEnd;\n        }\n    }\n\n    if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;\n        while (lastOffset < size)\n        {\n            // Find next non-null allocation or move nextAlloc2ndIndex to the end.\n            while (nextAlloc2ndIndex != SIZE_MAX &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                --nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex != SIZE_MAX)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    ++unusedRangeCount;\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                ++alloc2ndCount;\n                usedBytes += suballoc.size;\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                --nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                if (lastOffset < size)\n                {\n                    // There is free space from lastOffset to size.\n                    ++unusedRangeCount;\n                }\n\n                // End of loop.\n                lastOffset = size;\n            }\n        }\n    }\n\n    const VkDeviceSize unusedBytes = size - usedBytes;\n    PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount);\n\n    // SECOND PASS\n    lastOffset = 0;\n\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;\n        size_t nextAlloc2ndIndex = 0;\n        while (lastOffset < freeSpace2ndTo1stEnd)\n        {\n            // Find next non-null allocation or move nextAlloc2ndIndex to the end.\n            while (nextAlloc2ndIndex < suballoc2ndCount &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                ++nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex < suballoc2ndCount)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                ++nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                if (lastOffset < freeSpace2ndTo1stEnd)\n                {\n                    // There is free space from lastOffset to freeSpace2ndTo1stEnd.\n                    const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;\n                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);\n                }\n\n                // End of loop.\n                lastOffset = freeSpace2ndTo1stEnd;\n            }\n        }\n    }\n\n    nextAlloc1stIndex = m_1stNullItemsBeginCount;\n    while (lastOffset < freeSpace1stTo2ndEnd)\n    {\n        // Find next non-null allocation or move nextAllocIndex to the end.\n        while (nextAlloc1stIndex < suballoc1stCount &&\n            suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)\n        {\n            ++nextAlloc1stIndex;\n        }\n\n        // Found non-null allocation.\n        if (nextAlloc1stIndex < suballoc1stCount)\n        {\n            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];\n\n            // 1. Process free space before this allocation.\n            if (lastOffset < suballoc.offset)\n            {\n                // There is free space from lastOffset to suballoc.offset.\n                const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);\n            }\n\n            // 2. Process this allocation.\n            // There is allocation with suballoc.offset, suballoc.size.\n            PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);\n\n            // 3. Prepare for next iteration.\n            lastOffset = suballoc.offset + suballoc.size;\n            ++nextAlloc1stIndex;\n        }\n        // We are at the end.\n        else\n        {\n            if (lastOffset < freeSpace1stTo2ndEnd)\n            {\n                // There is free space from lastOffset to freeSpace1stTo2ndEnd.\n                const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;\n                PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);\n            }\n\n            // End of loop.\n            lastOffset = freeSpace1stTo2ndEnd;\n        }\n    }\n\n    if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;\n        while (lastOffset < size)\n        {\n            // Find next non-null allocation or move nextAlloc2ndIndex to the end.\n            while (nextAlloc2ndIndex != SIZE_MAX &&\n                suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)\n            {\n                --nextAlloc2ndIndex;\n            }\n\n            // Found non-null allocation.\n            if (nextAlloc2ndIndex != SIZE_MAX)\n            {\n                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];\n\n                // 1. Process free space before this allocation.\n                if (lastOffset < suballoc.offset)\n                {\n                    // There is free space from lastOffset to suballoc.offset.\n                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;\n                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);\n                }\n\n                // 2. Process this allocation.\n                // There is allocation with suballoc.offset, suballoc.size.\n                PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);\n\n                // 3. Prepare for next iteration.\n                lastOffset = suballoc.offset + suballoc.size;\n                --nextAlloc2ndIndex;\n            }\n            // We are at the end.\n            else\n            {\n                if (lastOffset < size)\n                {\n                    // There is free space from lastOffset to size.\n                    const VkDeviceSize unusedRangeSize = size - lastOffset;\n                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);\n                }\n\n                // End of loop.\n                lastOffset = size;\n            }\n        }\n    }\n\n    PrintDetailedMap_End(json);\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nbool VmaBlockMetadata_Linear::CreateAllocationRequest(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    bool upperAddress,\n    VmaSuballocationType allocType,\n    uint32_t strategy,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    VMA_ASSERT(allocSize > 0);\n    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);\n    VMA_ASSERT(pAllocationRequest != VMA_NULL);\n    VMA_HEAVY_ASSERT(Validate());\n    pAllocationRequest->size = allocSize;\n    return upperAddress ?\n        CreateAllocationRequest_UpperAddress(\n            allocSize, allocAlignment, allocType, strategy, pAllocationRequest) :\n        CreateAllocationRequest_LowerAddress(\n            allocSize, allocAlignment, allocType, strategy, pAllocationRequest);\n}\n\nVkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData)\n{\n    VMA_ASSERT(!IsVirtual());\n    SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    for (size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)\n    {\n        const VmaSuballocation& suballoc = suballocations1st[i];\n        if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))\n            {\n                VMA_ASSERT(0 && \"MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!\");\n                return VK_ERROR_UNKNOWN_COPY;\n            }\n        }\n    }\n\n    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n    for (size_t i = 0, count = suballocations2nd.size(); i < count; ++i)\n    {\n        const VmaSuballocation& suballoc = suballocations2nd[i];\n        if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))\n            {\n                VMA_ASSERT(0 && \"MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!\");\n                return VK_ERROR_UNKNOWN_COPY;\n            }\n        }\n    }\n\n    return VK_SUCCESS;\n}\n\nvoid VmaBlockMetadata_Linear::Alloc(\n    const VmaAllocationRequest& request,\n    VmaSuballocationType type,\n    void* userData)\n{\n    const VkDeviceSize offset = (VkDeviceSize)request.allocHandle - 1;\n    const VmaSuballocation newSuballoc = { offset, request.size, userData, type };\n\n    switch (request.type)\n    {\n    case VmaAllocationRequestType::UpperAddress:\n    {\n        VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &&\n            \"CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.\");\n        SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n        suballocations2nd.push_back(newSuballoc);\n        m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;\n    }\n    break;\n    case VmaAllocationRequestType::EndOf1st:\n    {\n        SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n\n        VMA_ASSERT(suballocations1st.empty() ||\n            offset >= suballocations1st.back().offset + suballocations1st.back().size);\n        // Check if it fits before the end of the block.\n        VMA_ASSERT(offset + request.size <= GetSize());\n\n        suballocations1st.push_back(newSuballoc);\n    }\n    break;\n    case VmaAllocationRequestType::EndOf2nd:\n    {\n        SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n        // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.\n        VMA_ASSERT(!suballocations1st.empty() &&\n            offset + request.size <= suballocations1st[m_1stNullItemsBeginCount].offset);\n        SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n\n        switch (m_2ndVectorMode)\n        {\n        case SECOND_VECTOR_EMPTY:\n            // First allocation from second part ring buffer.\n            VMA_ASSERT(suballocations2nd.empty());\n            m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;\n            break;\n        case SECOND_VECTOR_RING_BUFFER:\n            // 2-part ring buffer is already started.\n            VMA_ASSERT(!suballocations2nd.empty());\n            break;\n        case SECOND_VECTOR_DOUBLE_STACK:\n            VMA_ASSERT(0 && \"CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.\");\n            break;\n        default:\n            VMA_ASSERT(0);\n        }\n\n        suballocations2nd.push_back(newSuballoc);\n    }\n    break;\n    default:\n        VMA_ASSERT(0 && \"CRITICAL INTERNAL ERROR.\");\n    }\n\n    m_SumFreeSize -= newSuballoc.size;\n}\n\nvoid VmaBlockMetadata_Linear::Free(VmaAllocHandle allocHandle)\n{\n    SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n    VkDeviceSize offset = (VkDeviceSize)allocHandle - 1;\n\n    if (!suballocations1st.empty())\n    {\n        // First allocation: Mark it as next empty at the beginning.\n        VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];\n        if (firstSuballoc.offset == offset)\n        {\n            firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;\n            firstSuballoc.userData = VMA_NULL;\n            m_SumFreeSize += firstSuballoc.size;\n            ++m_1stNullItemsBeginCount;\n            CleanupAfterFree();\n            return;\n        }\n    }\n\n    // Last allocation in 2-part ring buffer or top of upper stack (same logic).\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||\n        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        VmaSuballocation& lastSuballoc = suballocations2nd.back();\n        if (lastSuballoc.offset == offset)\n        {\n            m_SumFreeSize += lastSuballoc.size;\n            suballocations2nd.pop_back();\n            CleanupAfterFree();\n            return;\n        }\n    }\n    // Last allocation in 1st vector.\n    else if (m_2ndVectorMode == SECOND_VECTOR_EMPTY)\n    {\n        VmaSuballocation& lastSuballoc = suballocations1st.back();\n        if (lastSuballoc.offset == offset)\n        {\n            m_SumFreeSize += lastSuballoc.size;\n            suballocations1st.pop_back();\n            CleanupAfterFree();\n            return;\n        }\n    }\n\n    VmaSuballocation refSuballoc;\n    refSuballoc.offset = offset;\n    // Rest of members stays uninitialized intentionally for better performance.\n\n    // Item from the middle of 1st vector.\n    {\n        const SuballocationVectorType::iterator it = VmaBinaryFindSorted(\n            suballocations1st.begin() + m_1stNullItemsBeginCount,\n            suballocations1st.end(),\n            refSuballoc,\n            VmaSuballocationOffsetLess());\n        if (it != suballocations1st.end())\n        {\n            it->type = VMA_SUBALLOCATION_TYPE_FREE;\n            it->userData = VMA_NULL;\n            ++m_1stNullItemsMiddleCount;\n            m_SumFreeSize += it->size;\n            CleanupAfterFree();\n            return;\n        }\n    }\n\n    if (m_2ndVectorMode != SECOND_VECTOR_EMPTY)\n    {\n        // Item from the middle of 2nd vector.\n        const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?\n            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :\n            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());\n        if (it != suballocations2nd.end())\n        {\n            it->type = VMA_SUBALLOCATION_TYPE_FREE;\n            it->userData = VMA_NULL;\n            ++m_2ndNullItemsCount;\n            m_SumFreeSize += it->size;\n            CleanupAfterFree();\n            return;\n        }\n    }\n\n    VMA_ASSERT(0 && \"Allocation to free not found in linear allocator!\");\n}\n\nvoid VmaBlockMetadata_Linear::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)\n{\n    outInfo.offset = (VkDeviceSize)allocHandle - 1;\n    VmaSuballocation& suballoc = FindSuballocation(outInfo.offset);\n    outInfo.size = suballoc.size;\n    outInfo.pUserData = suballoc.userData;\n}\n\nvoid* VmaBlockMetadata_Linear::GetAllocationUserData(VmaAllocHandle allocHandle) const\n{\n    return FindSuballocation((VkDeviceSize)allocHandle - 1).userData;\n}\n\nVmaAllocHandle VmaBlockMetadata_Linear::GetAllocationListBegin() const\n{\n    // Function only used for defragmentation, which is disabled for this algorithm\n    VMA_ASSERT(0);\n    return VK_NULL_HANDLE;\n}\n\nVmaAllocHandle VmaBlockMetadata_Linear::GetNextAllocation(VmaAllocHandle prevAlloc) const\n{\n    // Function only used for defragmentation, which is disabled for this algorithm\n    VMA_ASSERT(0);\n    return VK_NULL_HANDLE;\n}\n\nVkDeviceSize VmaBlockMetadata_Linear::GetNextFreeRegionSize(VmaAllocHandle alloc) const\n{\n    // Function only used for defragmentation, which is disabled for this algorithm\n    VMA_ASSERT(0);\n    return 0;\n}\n\nvoid VmaBlockMetadata_Linear::Clear()\n{\n    m_SumFreeSize = GetSize();\n    m_Suballocations0.clear();\n    m_Suballocations1.clear();\n    // Leaving m_1stVectorIndex unchanged - it doesn't matter.\n    m_2ndVectorMode = SECOND_VECTOR_EMPTY;\n    m_1stNullItemsBeginCount = 0;\n    m_1stNullItemsMiddleCount = 0;\n    m_2ndNullItemsCount = 0;\n}\n\nvoid VmaBlockMetadata_Linear::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)\n{\n    VmaSuballocation& suballoc = FindSuballocation((VkDeviceSize)allocHandle - 1);\n    suballoc.userData = userData;\n}\n\nvoid VmaBlockMetadata_Linear::DebugLogAllAllocations() const\n{\n    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    for (auto it = suballocations1st.begin() + m_1stNullItemsBeginCount; it != suballocations1st.end(); ++it)\n        if (it->type != VMA_SUBALLOCATION_TYPE_FREE)\n            DebugLogAllocation(it->offset, it->size, it->userData);\n\n    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n    for (auto it = suballocations2nd.begin(); it != suballocations2nd.end(); ++it)\n        if (it->type != VMA_SUBALLOCATION_TYPE_FREE)\n            DebugLogAllocation(it->offset, it->size, it->userData);\n}\n\nVmaSuballocation& VmaBlockMetadata_Linear::FindSuballocation(VkDeviceSize offset) const\n{\n    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n\n    VmaSuballocation refSuballoc;\n    refSuballoc.offset = offset;\n    // Rest of members stays uninitialized intentionally for better performance.\n\n    // Item from the 1st vector.\n    {\n        SuballocationVectorType::const_iterator it = VmaBinaryFindSorted(\n            suballocations1st.begin() + m_1stNullItemsBeginCount,\n            suballocations1st.end(),\n            refSuballoc,\n            VmaSuballocationOffsetLess());\n        if (it != suballocations1st.end())\n        {\n            return const_cast<VmaSuballocation&>(*it);\n        }\n    }\n\n    if (m_2ndVectorMode != SECOND_VECTOR_EMPTY)\n    {\n        // Rest of members stays uninitialized intentionally for better performance.\n        SuballocationVectorType::const_iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?\n            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :\n            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());\n        if (it != suballocations2nd.end())\n        {\n            return const_cast<VmaSuballocation&>(*it);\n        }\n    }\n\n    VMA_ASSERT(0 && \"Allocation not found in linear allocator!\");\n    return const_cast<VmaSuballocation&>(suballocations1st.back()); // Should never occur.\n}\n\nbool VmaBlockMetadata_Linear::ShouldCompact1st() const\n{\n    const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;\n    const size_t suballocCount = AccessSuballocations1st().size();\n    return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3;\n}\n\nvoid VmaBlockMetadata_Linear::CleanupAfterFree()\n{\n    SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n\n    if (IsEmpty())\n    {\n        suballocations1st.clear();\n        suballocations2nd.clear();\n        m_1stNullItemsBeginCount = 0;\n        m_1stNullItemsMiddleCount = 0;\n        m_2ndNullItemsCount = 0;\n        m_2ndVectorMode = SECOND_VECTOR_EMPTY;\n    }\n    else\n    {\n        const size_t suballoc1stCount = suballocations1st.size();\n        const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;\n        VMA_ASSERT(nullItem1stCount <= suballoc1stCount);\n\n        // Find more null items at the beginning of 1st vector.\n        while (m_1stNullItemsBeginCount < suballoc1stCount &&\n            suballocations1st[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            ++m_1stNullItemsBeginCount;\n            --m_1stNullItemsMiddleCount;\n        }\n\n        // Find more null items at the end of 1st vector.\n        while (m_1stNullItemsMiddleCount > 0 &&\n            suballocations1st.back().type == VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            --m_1stNullItemsMiddleCount;\n            suballocations1st.pop_back();\n        }\n\n        // Find more null items at the end of 2nd vector.\n        while (m_2ndNullItemsCount > 0 &&\n            suballocations2nd.back().type == VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            --m_2ndNullItemsCount;\n            suballocations2nd.pop_back();\n        }\n\n        // Find more null items at the beginning of 2nd vector.\n        while (m_2ndNullItemsCount > 0 &&\n            suballocations2nd[0].type == VMA_SUBALLOCATION_TYPE_FREE)\n        {\n            --m_2ndNullItemsCount;\n            VmaVectorRemove(suballocations2nd, 0);\n        }\n\n        if (ShouldCompact1st())\n        {\n            const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount;\n            size_t srcIndex = m_1stNullItemsBeginCount;\n            for (size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex)\n            {\n                while (suballocations1st[srcIndex].type == VMA_SUBALLOCATION_TYPE_FREE)\n                {\n                    ++srcIndex;\n                }\n                if (dstIndex != srcIndex)\n                {\n                    suballocations1st[dstIndex] = suballocations1st[srcIndex];\n                }\n                ++srcIndex;\n            }\n            suballocations1st.resize(nonNullItemCount);\n            m_1stNullItemsBeginCount = 0;\n            m_1stNullItemsMiddleCount = 0;\n        }\n\n        // 2nd vector became empty.\n        if (suballocations2nd.empty())\n        {\n            m_2ndVectorMode = SECOND_VECTOR_EMPTY;\n        }\n\n        // 1st vector became empty.\n        if (suballocations1st.size() - m_1stNullItemsBeginCount == 0)\n        {\n            suballocations1st.clear();\n            m_1stNullItemsBeginCount = 0;\n\n            if (!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n            {\n                // Swap 1st with 2nd. Now 2nd is empty.\n                m_2ndVectorMode = SECOND_VECTOR_EMPTY;\n                m_1stNullItemsMiddleCount = m_2ndNullItemsCount;\n                while (m_1stNullItemsBeginCount < suballocations2nd.size() &&\n                    suballocations2nd[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE)\n                {\n                    ++m_1stNullItemsBeginCount;\n                    --m_1stNullItemsMiddleCount;\n                }\n                m_2ndNullItemsCount = 0;\n                m_1stVectorIndex ^= 1;\n            }\n        }\n    }\n\n    VMA_HEAVY_ASSERT(Validate());\n}\n\nbool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    VmaSuballocationType allocType,\n    uint32_t strategy,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    const VkDeviceSize blockSize = GetSize();\n    const VkDeviceSize debugMargin = GetDebugMargin();\n    const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity();\n    SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n\n    if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n    {\n        // Try to allocate at the end of 1st vector.\n\n        VkDeviceSize resultBaseOffset = 0;\n        if (!suballocations1st.empty())\n        {\n            const VmaSuballocation& lastSuballoc = suballocations1st.back();\n            resultBaseOffset = lastSuballoc.offset + lastSuballoc.size + debugMargin;\n        }\n\n        // Start from offset equal to beginning of free space.\n        VkDeviceSize resultOffset = resultBaseOffset;\n\n        // Apply alignment.\n        resultOffset = VmaAlignUp(resultOffset, allocAlignment);\n\n        // Check previous suballocations for BufferImageGranularity conflicts.\n        // Make bigger alignment if necessary.\n        if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations1st.empty())\n        {\n            bool bufferImageGranularityConflict = false;\n            for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )\n            {\n                const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];\n                if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))\n                {\n                    if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))\n                    {\n                        bufferImageGranularityConflict = true;\n                        break;\n                    }\n                }\n                else\n                    // Already on previous page.\n                    break;\n            }\n            if (bufferImageGranularityConflict)\n            {\n                resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);\n            }\n        }\n\n        const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ?\n            suballocations2nd.back().offset : blockSize;\n\n        // There is enough free space at the end after alignment.\n        if (resultOffset + allocSize + debugMargin <= freeSpaceEnd)\n        {\n            // Check next suballocations for BufferImageGranularity conflicts.\n            // If conflict exists, allocation cannot be made here.\n            if ((allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)\n            {\n                for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )\n                {\n                    const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];\n                    if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))\n                    {\n                        if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))\n                        {\n                            return false;\n                        }\n                    }\n                    else\n                    {\n                        // Already on previous page.\n                        break;\n                    }\n                }\n            }\n\n            // All tests passed: Success.\n            pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1);\n            // pAllocationRequest->item, customData unused.\n            pAllocationRequest->type = VmaAllocationRequestType::EndOf1st;\n            return true;\n        }\n    }\n\n    // Wrap-around to end of 2nd vector. Try to allocate there, watching for the\n    // beginning of 1st vector as the end of free space.\n    if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        VMA_ASSERT(!suballocations1st.empty());\n\n        VkDeviceSize resultBaseOffset = 0;\n        if (!suballocations2nd.empty())\n        {\n            const VmaSuballocation& lastSuballoc = suballocations2nd.back();\n            resultBaseOffset = lastSuballoc.offset + lastSuballoc.size + debugMargin;\n        }\n\n        // Start from offset equal to beginning of free space.\n        VkDeviceSize resultOffset = resultBaseOffset;\n\n        // Apply alignment.\n        resultOffset = VmaAlignUp(resultOffset, allocAlignment);\n\n        // Check previous suballocations for BufferImageGranularity conflicts.\n        // Make bigger alignment if necessary.\n        if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty())\n        {\n            bool bufferImageGranularityConflict = false;\n            for (size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )\n            {\n                const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex];\n                if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))\n                {\n                    if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))\n                    {\n                        bufferImageGranularityConflict = true;\n                        break;\n                    }\n                }\n                else\n                    // Already on previous page.\n                    break;\n            }\n            if (bufferImageGranularityConflict)\n            {\n                resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);\n            }\n        }\n\n        size_t index1st = m_1stNullItemsBeginCount;\n\n        // There is enough free space at the end after alignment.\n        if ((index1st == suballocations1st.size() && resultOffset + allocSize + debugMargin <= blockSize) ||\n            (index1st < suballocations1st.size() && resultOffset + allocSize + debugMargin <= suballocations1st[index1st].offset))\n        {\n            // Check next suballocations for BufferImageGranularity conflicts.\n            // If conflict exists, allocation cannot be made here.\n            if (allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity)\n            {\n                for (size_t nextSuballocIndex = index1st;\n                    nextSuballocIndex < suballocations1st.size();\n                    nextSuballocIndex++)\n                {\n                    const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex];\n                    if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))\n                    {\n                        if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))\n                        {\n                            return false;\n                        }\n                    }\n                    else\n                    {\n                        // Already on next page.\n                        break;\n                    }\n                }\n            }\n\n            // All tests passed: Success.\n            pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1);\n            pAllocationRequest->type = VmaAllocationRequestType::EndOf2nd;\n            // pAllocationRequest->item, customData unused.\n            return true;\n        }\n    }\n\n    return false;\n}\n\nbool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    VmaSuballocationType allocType,\n    uint32_t strategy,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    const VkDeviceSize blockSize = GetSize();\n    const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity();\n    SuballocationVectorType& suballocations1st = AccessSuballocations1st();\n    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();\n\n    if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)\n    {\n        VMA_ASSERT(0 && \"Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.\");\n        return false;\n    }\n\n    // Try to allocate before 2nd.back(), or end of block if 2nd.empty().\n    if (allocSize > blockSize)\n    {\n        return false;\n    }\n    VkDeviceSize resultBaseOffset = blockSize - allocSize;\n    if (!suballocations2nd.empty())\n    {\n        const VmaSuballocation& lastSuballoc = suballocations2nd.back();\n        resultBaseOffset = lastSuballoc.offset - allocSize;\n        if (allocSize > lastSuballoc.offset)\n        {\n            return false;\n        }\n    }\n\n    // Start from offset equal to end of free space.\n    VkDeviceSize resultOffset = resultBaseOffset;\n\n    const VkDeviceSize debugMargin = GetDebugMargin();\n\n    // Apply debugMargin at the end.\n    if (debugMargin > 0)\n    {\n        if (resultOffset < debugMargin)\n        {\n            return false;\n        }\n        resultOffset -= debugMargin;\n    }\n\n    // Apply alignment.\n    resultOffset = VmaAlignDown(resultOffset, allocAlignment);\n\n    // Check next suballocations from 2nd for BufferImageGranularity conflicts.\n    // Make bigger alignment if necessary.\n    if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty())\n    {\n        bool bufferImageGranularityConflict = false;\n        for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )\n        {\n            const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];\n            if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))\n            {\n                if (VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))\n                {\n                    bufferImageGranularityConflict = true;\n                    break;\n                }\n            }\n            else\n                // Already on previous page.\n                break;\n        }\n        if (bufferImageGranularityConflict)\n        {\n            resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);\n        }\n    }\n\n    // There is enough free space.\n    const VkDeviceSize endOf1st = !suballocations1st.empty() ?\n        suballocations1st.back().offset + suballocations1st.back().size :\n        0;\n    if (endOf1st + debugMargin <= resultOffset)\n    {\n        // Check previous suballocations for BufferImageGranularity conflicts.\n        // If conflict exists, allocation cannot be made here.\n        if (bufferImageGranularity > 1)\n        {\n            for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )\n            {\n                const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];\n                if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))\n                {\n                    if (VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))\n                    {\n                        return false;\n                    }\n                }\n                else\n                {\n                    // Already on next page.\n                    break;\n                }\n            }\n        }\n\n        // All tests passed: Success.\n        pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1);\n        // pAllocationRequest->item unused.\n        pAllocationRequest->type = VmaAllocationRequestType::UpperAddress;\n        return true;\n    }\n\n    return false;\n}\n#endif // _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS\n#endif // _VMA_BLOCK_METADATA_LINEAR\n\n#if 0\n#ifndef _VMA_BLOCK_METADATA_BUDDY\n/*\n- GetSize() is the original size of allocated memory block.\n- m_UsableSize is this size aligned down to a power of two.\n  All allocations and calculations happen relative to m_UsableSize.\n- GetUnusableSize() is the difference between them.\n  It is reported as separate, unused range, not available for allocations.\n\nNode at level 0 has size = m_UsableSize.\nEach next level contains nodes with size 2 times smaller than current level.\nm_LevelCount is the maximum number of levels to use in the current object.\n*/\nclass VmaBlockMetadata_Buddy : public VmaBlockMetadata\n{\n    VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)\npublic:\n    VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks,\n        VkDeviceSize bufferImageGranularity, bool isVirtual);\n    virtual ~VmaBlockMetadata_Buddy();\n\n    size_t GetAllocationCount() const override { return m_AllocationCount; }\n    VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize + GetUnusableSize(); }\n    bool IsEmpty() const override { return m_Root->type == Node::TYPE_FREE; }\n    VkResult CheckCorruption(const void* pBlockData) override { return VK_ERROR_FEATURE_NOT_PRESENT; }\n    VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; }\n    void DebugLogAllAllocations() const override { DebugLogAllAllocationNode(m_Root, 0); }\n\n    void Init(VkDeviceSize size) override;\n    bool Validate() const override;\n\n    void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;\n    void AddStatistics(VmaStatistics& inoutStats) const override;\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const override;\n#endif\n\n    bool CreateAllocationRequest(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        bool upperAddress,\n        VmaSuballocationType allocType,\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest) override;\n\n    void Alloc(\n        const VmaAllocationRequest& request,\n        VmaSuballocationType type,\n        void* userData) override;\n\n    void Free(VmaAllocHandle allocHandle) override;\n    void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;\n    void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;\n    VmaAllocHandle GetAllocationListBegin() const override;\n    VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;\n    void Clear() override;\n    void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;\n\nprivate:\n    static const size_t MAX_LEVELS = 48;\n\n    struct ValidationContext\n    {\n        size_t calculatedAllocationCount = 0;\n        size_t calculatedFreeCount = 0;\n        VkDeviceSize calculatedSumFreeSize = 0;\n    };\n    struct Node\n    {\n        VkDeviceSize offset;\n        enum TYPE\n        {\n            TYPE_FREE,\n            TYPE_ALLOCATION,\n            TYPE_SPLIT,\n            TYPE_COUNT\n        } type;\n        Node* parent;\n        Node* buddy;\n\n        union\n        {\n            struct\n            {\n                Node* prev;\n                Node* next;\n            } free;\n            struct\n            {\n                void* userData;\n            } allocation;\n            struct\n            {\n                Node* leftChild;\n            } split;\n        };\n    };\n\n    // Size of the memory block aligned down to a power of two.\n    VkDeviceSize m_UsableSize;\n    uint32_t m_LevelCount;\n    VmaPoolAllocator<Node> m_NodeAllocator;\n    Node* m_Root;\n    struct\n    {\n        Node* front;\n        Node* back;\n    } m_FreeList[MAX_LEVELS];\n\n    // Number of nodes in the tree with type == TYPE_ALLOCATION.\n    size_t m_AllocationCount;\n    // Number of nodes in the tree with type == TYPE_FREE.\n    size_t m_FreeCount;\n    // Doesn't include space wasted due to internal fragmentation - allocation sizes are just aligned up to node sizes.\n    // Doesn't include unusable size.\n    VkDeviceSize m_SumFreeSize;\n\n    VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; }\n    VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }\n\n    VkDeviceSize AlignAllocationSize(VkDeviceSize size) const\n    {\n        if (!IsVirtual())\n        {\n            size = VmaAlignUp(size, (VkDeviceSize)16);\n        }\n        return VmaNextPow2(size);\n    }\n    Node* FindAllocationNode(VkDeviceSize offset, uint32_t& outLevel) const;\n    void DeleteNodeChildren(Node* node);\n    bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;\n    uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;\n    void AddNodeToDetailedStatistics(VmaDetailedStatistics& inoutStats, const Node* node, VkDeviceSize levelNodeSize) const;\n    // Adds node to the front of FreeList at given level.\n    // node->type must be FREE.\n    // node->free.prev, next can be undefined.\n    void AddToFreeListFront(uint32_t level, Node* node);\n    // Removes node from FreeList at given level.\n    // node->type must be FREE.\n    // node->free.prev, next stay untouched.\n    void RemoveFromFreeList(uint32_t level, Node* node);\n    void DebugLogAllAllocationNode(Node* node, uint32_t level) const;\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const;\n#endif\n};\n\n#ifndef _VMA_BLOCK_METADATA_BUDDY_FUNCTIONS\nVmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks,\n    VkDeviceSize bufferImageGranularity, bool isVirtual)\n    : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),\n    m_NodeAllocator(pAllocationCallbacks, 32), // firstBlockCapacity\n    m_Root(VMA_NULL),\n    m_AllocationCount(0),\n    m_FreeCount(1),\n    m_SumFreeSize(0)\n{\n    memset(m_FreeList, 0, sizeof(m_FreeList));\n}\n\nVmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy()\n{\n    DeleteNodeChildren(m_Root);\n    m_NodeAllocator.Free(m_Root);\n}\n\nvoid VmaBlockMetadata_Buddy::Init(VkDeviceSize size)\n{\n    VmaBlockMetadata::Init(size);\n\n    m_UsableSize = VmaPrevPow2(size);\n    m_SumFreeSize = m_UsableSize;\n\n    // Calculate m_LevelCount.\n    const VkDeviceSize minNodeSize = IsVirtual() ? 1 : 16;\n    m_LevelCount = 1;\n    while (m_LevelCount < MAX_LEVELS &&\n        LevelToNodeSize(m_LevelCount) >= minNodeSize)\n    {\n        ++m_LevelCount;\n    }\n\n    Node* rootNode = m_NodeAllocator.Alloc();\n    rootNode->offset = 0;\n    rootNode->type = Node::TYPE_FREE;\n    rootNode->parent = VMA_NULL;\n    rootNode->buddy = VMA_NULL;\n\n    m_Root = rootNode;\n    AddToFreeListFront(0, rootNode);\n}\n\nbool VmaBlockMetadata_Buddy::Validate() const\n{\n    // Validate tree.\n    ValidationContext ctx;\n    if (!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))\n    {\n        VMA_VALIDATE(false && \"ValidateNode failed.\");\n    }\n    VMA_VALIDATE(m_AllocationCount == ctx.calculatedAllocationCount);\n    VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize);\n\n    // Validate free node lists.\n    for (uint32_t level = 0; level < m_LevelCount; ++level)\n    {\n        VMA_VALIDATE(m_FreeList[level].front == VMA_NULL ||\n            m_FreeList[level].front->free.prev == VMA_NULL);\n\n        for (Node* node = m_FreeList[level].front;\n            node != VMA_NULL;\n            node = node->free.next)\n        {\n            VMA_VALIDATE(node->type == Node::TYPE_FREE);\n\n            if (node->free.next == VMA_NULL)\n            {\n                VMA_VALIDATE(m_FreeList[level].back == node);\n            }\n            else\n            {\n                VMA_VALIDATE(node->free.next->free.prev == node);\n            }\n        }\n    }\n\n    // Validate that free lists ar higher levels are empty.\n    for (uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level)\n    {\n        VMA_VALIDATE(m_FreeList[level].front == VMA_NULL && m_FreeList[level].back == VMA_NULL);\n    }\n\n    return true;\n}\n\nvoid VmaBlockMetadata_Buddy::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const\n{\n    inoutStats.statistics.blockCount++;\n    inoutStats.statistics.blockBytes += GetSize();\n\n    AddNodeToDetailedStatistics(inoutStats, m_Root, LevelToNodeSize(0));\n\n    const VkDeviceSize unusableSize = GetUnusableSize();\n    if (unusableSize > 0)\n        VmaAddDetailedStatisticsUnusedRange(inoutStats, unusableSize);\n}\n\nvoid VmaBlockMetadata_Buddy::AddStatistics(VmaStatistics& inoutStats) const\n{\n    inoutStats.blockCount++;\n    inoutStats.allocationCount += (uint32_t)m_AllocationCount;\n    inoutStats.blockBytes += GetSize();\n    inoutStats.allocationBytes += GetSize() - m_SumFreeSize;\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const\n{\n    VmaDetailedStatistics stats;\n    VmaClearDetailedStatistics(stats);\n    AddDetailedStatistics(stats);\n\n    PrintDetailedMap_Begin(\n        json,\n        stats.statistics.blockBytes - stats.statistics.allocationBytes,\n        stats.statistics.allocationCount,\n        stats.unusedRangeCount,\n        mapRefCount);\n\n    PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0));\n\n    const VkDeviceSize unusableSize = GetUnusableSize();\n    if (unusableSize > 0)\n    {\n        PrintDetailedMap_UnusedRange(json,\n            m_UsableSize, // offset\n            unusableSize); // size\n    }\n\n    PrintDetailedMap_End(json);\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nbool VmaBlockMetadata_Buddy::CreateAllocationRequest(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    bool upperAddress,\n    VmaSuballocationType allocType,\n    uint32_t strategy,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    VMA_ASSERT(!upperAddress && \"VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.\");\n\n    allocSize = AlignAllocationSize(allocSize);\n\n    // Simple way to respect bufferImageGranularity. May be optimized some day.\n    // Whenever it might be an OPTIMAL image...\n    if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||\n        allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||\n        allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)\n    {\n        allocAlignment = VMA_MAX(allocAlignment, GetBufferImageGranularity());\n        allocSize = VmaAlignUp(allocSize, GetBufferImageGranularity());\n    }\n\n    if (allocSize > m_UsableSize)\n    {\n        return false;\n    }\n\n    const uint32_t targetLevel = AllocSizeToLevel(allocSize);\n    for (uint32_t level = targetLevel; level--; )\n    {\n        for (Node* freeNode = m_FreeList[level].front;\n            freeNode != VMA_NULL;\n            freeNode = freeNode->free.next)\n        {\n            if (freeNode->offset % allocAlignment == 0)\n            {\n                pAllocationRequest->type = VmaAllocationRequestType::Normal;\n                pAllocationRequest->allocHandle = (VmaAllocHandle)(freeNode->offset + 1);\n                pAllocationRequest->size = allocSize;\n                pAllocationRequest->customData = (void*)(uintptr_t)level;\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\nvoid VmaBlockMetadata_Buddy::Alloc(\n    const VmaAllocationRequest& request,\n    VmaSuballocationType type,\n    void* userData)\n{\n    VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);\n\n    const uint32_t targetLevel = AllocSizeToLevel(request.size);\n    uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;\n\n    Node* currNode = m_FreeList[currLevel].front;\n    VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);\n    const VkDeviceSize offset = (VkDeviceSize)request.allocHandle - 1;\n    while (currNode->offset != offset)\n    {\n        currNode = currNode->free.next;\n        VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);\n    }\n\n    // Go down, splitting free nodes.\n    while (currLevel < targetLevel)\n    {\n        // currNode is already first free node at currLevel.\n        // Remove it from list of free nodes at this currLevel.\n        RemoveFromFreeList(currLevel, currNode);\n\n        const uint32_t childrenLevel = currLevel + 1;\n\n        // Create two free sub-nodes.\n        Node* leftChild = m_NodeAllocator.Alloc();\n        Node* rightChild = m_NodeAllocator.Alloc();\n\n        leftChild->offset = currNode->offset;\n        leftChild->type = Node::TYPE_FREE;\n        leftChild->parent = currNode;\n        leftChild->buddy = rightChild;\n\n        rightChild->offset = currNode->offset + LevelToNodeSize(childrenLevel);\n        rightChild->type = Node::TYPE_FREE;\n        rightChild->parent = currNode;\n        rightChild->buddy = leftChild;\n\n        // Convert current currNode to split type.\n        currNode->type = Node::TYPE_SPLIT;\n        currNode->split.leftChild = leftChild;\n\n        // Add child nodes to free list. Order is important!\n        AddToFreeListFront(childrenLevel, rightChild);\n        AddToFreeListFront(childrenLevel, leftChild);\n\n        ++m_FreeCount;\n        ++currLevel;\n        currNode = m_FreeList[currLevel].front;\n\n        /*\n        We can be sure that currNode, as left child of node previously split,\n        also fulfills the alignment requirement.\n        */\n    }\n\n    // Remove from free list.\n    VMA_ASSERT(currLevel == targetLevel &&\n        currNode != VMA_NULL &&\n        currNode->type == Node::TYPE_FREE);\n    RemoveFromFreeList(currLevel, currNode);\n\n    // Convert to allocation node.\n    currNode->type = Node::TYPE_ALLOCATION;\n    currNode->allocation.userData = userData;\n\n    ++m_AllocationCount;\n    --m_FreeCount;\n    m_SumFreeSize -= request.size;\n}\n\nvoid VmaBlockMetadata_Buddy::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)\n{\n    uint32_t level = 0;\n    outInfo.offset = (VkDeviceSize)allocHandle - 1;\n    const Node* const node = FindAllocationNode(outInfo.offset, level);\n    outInfo.size = LevelToNodeSize(level);\n    outInfo.pUserData = node->allocation.userData;\n}\n\nvoid* VmaBlockMetadata_Buddy::GetAllocationUserData(VmaAllocHandle allocHandle) const\n{\n    uint32_t level = 0;\n    const Node* const node = FindAllocationNode((VkDeviceSize)allocHandle - 1, level);\n    return node->allocation.userData;\n}\n\nVmaAllocHandle VmaBlockMetadata_Buddy::GetAllocationListBegin() const\n{\n    // Function only used for defragmentation, which is disabled for this algorithm\n    return VK_NULL_HANDLE;\n}\n\nVmaAllocHandle VmaBlockMetadata_Buddy::GetNextAllocation(VmaAllocHandle prevAlloc) const\n{\n    // Function only used for defragmentation, which is disabled for this algorithm\n    return VK_NULL_HANDLE;\n}\n\nvoid VmaBlockMetadata_Buddy::DeleteNodeChildren(Node* node)\n{\n    if (node->type == Node::TYPE_SPLIT)\n    {\n        DeleteNodeChildren(node->split.leftChild->buddy);\n        DeleteNodeChildren(node->split.leftChild);\n        const VkAllocationCallbacks* allocationCallbacks = GetAllocationCallbacks();\n        m_NodeAllocator.Free(node->split.leftChild->buddy);\n        m_NodeAllocator.Free(node->split.leftChild);\n    }\n}\n\nvoid VmaBlockMetadata_Buddy::Clear()\n{\n    DeleteNodeChildren(m_Root);\n    m_Root->type = Node::TYPE_FREE;\n    m_AllocationCount = 0;\n    m_FreeCount = 1;\n    m_SumFreeSize = m_UsableSize;\n}\n\nvoid VmaBlockMetadata_Buddy::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)\n{\n    uint32_t level = 0;\n    Node* const node = FindAllocationNode((VkDeviceSize)allocHandle - 1, level);\n    node->allocation.userData = userData;\n}\n\nVmaBlockMetadata_Buddy::Node* VmaBlockMetadata_Buddy::FindAllocationNode(VkDeviceSize offset, uint32_t& outLevel) const\n{\n    Node* node = m_Root;\n    VkDeviceSize nodeOffset = 0;\n    outLevel = 0;\n    VkDeviceSize levelNodeSize = LevelToNodeSize(0);\n    while (node->type == Node::TYPE_SPLIT)\n    {\n        const VkDeviceSize nextLevelNodeSize = levelNodeSize >> 1;\n        if (offset < nodeOffset + nextLevelNodeSize)\n        {\n            node = node->split.leftChild;\n        }\n        else\n        {\n            node = node->split.leftChild->buddy;\n            nodeOffset += nextLevelNodeSize;\n        }\n        ++outLevel;\n        levelNodeSize = nextLevelNodeSize;\n    }\n\n    VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION);\n    return node;\n}\n\nbool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const\n{\n    VMA_VALIDATE(level < m_LevelCount);\n    VMA_VALIDATE(curr->parent == parent);\n    VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL));\n    VMA_VALIDATE(curr->buddy == VMA_NULL || curr->buddy->buddy == curr);\n    switch (curr->type)\n    {\n    case Node::TYPE_FREE:\n        // curr->free.prev, next are validated separately.\n        ctx.calculatedSumFreeSize += levelNodeSize;\n        ++ctx.calculatedFreeCount;\n        break;\n    case Node::TYPE_ALLOCATION:\n        ++ctx.calculatedAllocationCount;\n        if (!IsVirtual())\n        {\n            VMA_VALIDATE(curr->allocation.userData != VMA_NULL);\n        }\n        break;\n    case Node::TYPE_SPLIT:\n    {\n        const uint32_t childrenLevel = level + 1;\n        const VkDeviceSize childrenLevelNodeSize = levelNodeSize >> 1;\n        const Node* const leftChild = curr->split.leftChild;\n        VMA_VALIDATE(leftChild != VMA_NULL);\n        VMA_VALIDATE(leftChild->offset == curr->offset);\n        if (!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))\n        {\n            VMA_VALIDATE(false && \"ValidateNode for left child failed.\");\n        }\n        const Node* const rightChild = leftChild->buddy;\n        VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize);\n        if (!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))\n        {\n            VMA_VALIDATE(false && \"ValidateNode for right child failed.\");\n        }\n    }\n    break;\n    default:\n        return false;\n    }\n\n    return true;\n}\n\nuint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const\n{\n    // I know this could be optimized somehow e.g. by using std::log2p1 from C++20.\n    uint32_t level = 0;\n    VkDeviceSize currLevelNodeSize = m_UsableSize;\n    VkDeviceSize nextLevelNodeSize = currLevelNodeSize >> 1;\n    while (allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount)\n    {\n        ++level;\n        currLevelNodeSize >>= 1;\n        nextLevelNodeSize >>= 1;\n    }\n    return level;\n}\n\nvoid VmaBlockMetadata_Buddy::Free(VmaAllocHandle allocHandle)\n{\n    uint32_t level = 0;\n    Node* node = FindAllocationNode((VkDeviceSize)allocHandle - 1, level);\n\n    ++m_FreeCount;\n    --m_AllocationCount;\n    m_SumFreeSize += LevelToNodeSize(level);\n\n    node->type = Node::TYPE_FREE;\n\n    // Join free nodes if possible.\n    while (level > 0 && node->buddy->type == Node::TYPE_FREE)\n    {\n        RemoveFromFreeList(level, node->buddy);\n        Node* const parent = node->parent;\n\n        m_NodeAllocator.Free(node->buddy);\n        m_NodeAllocator.Free(node);\n        parent->type = Node::TYPE_FREE;\n\n        node = parent;\n        --level;\n        --m_FreeCount;\n    }\n\n    AddToFreeListFront(level, node);\n}\n\nvoid VmaBlockMetadata_Buddy::AddNodeToDetailedStatistics(VmaDetailedStatistics& inoutStats, const Node* node, VkDeviceSize levelNodeSize) const\n{\n    switch (node->type)\n    {\n    case Node::TYPE_FREE:\n        VmaAddDetailedStatisticsUnusedRange(inoutStats, levelNodeSize);\n        break;\n    case Node::TYPE_ALLOCATION:\n        VmaAddDetailedStatisticsAllocation(inoutStats, levelNodeSize);\n        break;\n    case Node::TYPE_SPLIT:\n    {\n        const VkDeviceSize childrenNodeSize = levelNodeSize / 2;\n        const Node* const leftChild = node->split.leftChild;\n        AddNodeToDetailedStatistics(inoutStats, leftChild, childrenNodeSize);\n        const Node* const rightChild = leftChild->buddy;\n        AddNodeToDetailedStatistics(inoutStats, rightChild, childrenNodeSize);\n    }\n    break;\n    default:\n        VMA_ASSERT(0);\n    }\n}\n\nvoid VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node)\n{\n    VMA_ASSERT(node->type == Node::TYPE_FREE);\n\n    // List is empty.\n    Node* const frontNode = m_FreeList[level].front;\n    if (frontNode == VMA_NULL)\n    {\n        VMA_ASSERT(m_FreeList[level].back == VMA_NULL);\n        node->free.prev = node->free.next = VMA_NULL;\n        m_FreeList[level].front = m_FreeList[level].back = node;\n    }\n    else\n    {\n        VMA_ASSERT(frontNode->free.prev == VMA_NULL);\n        node->free.prev = VMA_NULL;\n        node->free.next = frontNode;\n        frontNode->free.prev = node;\n        m_FreeList[level].front = node;\n    }\n}\n\nvoid VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)\n{\n    VMA_ASSERT(m_FreeList[level].front != VMA_NULL);\n\n    // It is at the front.\n    if (node->free.prev == VMA_NULL)\n    {\n        VMA_ASSERT(m_FreeList[level].front == node);\n        m_FreeList[level].front = node->free.next;\n    }\n    else\n    {\n        Node* const prevFreeNode = node->free.prev;\n        VMA_ASSERT(prevFreeNode->free.next == node);\n        prevFreeNode->free.next = node->free.next;\n    }\n\n    // It is at the back.\n    if (node->free.next == VMA_NULL)\n    {\n        VMA_ASSERT(m_FreeList[level].back == node);\n        m_FreeList[level].back = node->free.prev;\n    }\n    else\n    {\n        Node* const nextFreeNode = node->free.next;\n        VMA_ASSERT(nextFreeNode->free.prev == node);\n        nextFreeNode->free.prev = node->free.prev;\n    }\n}\n\nvoid VmaBlockMetadata_Buddy::DebugLogAllAllocationNode(Node* node, uint32_t level) const\n{\n    switch (node->type)\n    {\n    case Node::TYPE_FREE:\n        break;\n    case Node::TYPE_ALLOCATION:\n        DebugLogAllocation(node->offset, LevelToNodeSize(level), node->allocation.userData);\n        break;\n    case Node::TYPE_SPLIT:\n    {\n        ++level;\n        DebugLogAllAllocationNode(node->split.leftChild, level);\n        DebugLogAllAllocationNode(node->split.leftChild->buddy, level);\n    }\n    break;\n    default:\n        VMA_ASSERT(0);\n    }\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const\n{\n    switch (node->type)\n    {\n    case Node::TYPE_FREE:\n        PrintDetailedMap_UnusedRange(json, node->offset, levelNodeSize);\n        break;\n    case Node::TYPE_ALLOCATION:\n        PrintDetailedMap_Allocation(json, node->offset, levelNodeSize, node->allocation.userData);\n        break;\n    case Node::TYPE_SPLIT:\n    {\n        const VkDeviceSize childrenNodeSize = levelNodeSize / 2;\n        const Node* const leftChild = node->split.leftChild;\n        PrintDetailedMapNode(json, leftChild, childrenNodeSize);\n        const Node* const rightChild = leftChild->buddy;\n        PrintDetailedMapNode(json, rightChild, childrenNodeSize);\n    }\n    break;\n    default:\n        VMA_ASSERT(0);\n    }\n}\n#endif // VMA_STATS_STRING_ENABLED\n#endif // _VMA_BLOCK_METADATA_BUDDY_FUNCTIONS\n#endif // _VMA_BLOCK_METADATA_BUDDY\n#endif // #if 0\n\n#ifndef _VMA_BLOCK_METADATA_TLSF\n// To not search current larger region if first allocation won't succeed and skip to smaller range\n// use with VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as strategy in CreateAllocationRequest().\n// When fragmentation and reusal of previous blocks doesn't matter then use with\n// VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT for fastest alloc time possible.\nclass VmaBlockMetadata_TLSF : public VmaBlockMetadata\n{\n    VMA_CLASS_NO_COPY(VmaBlockMetadata_TLSF)\npublic:\n    VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks,\n        VkDeviceSize bufferImageGranularity, bool isVirtual);\n    virtual ~VmaBlockMetadata_TLSF();\n\n    size_t GetAllocationCount() const override { return m_AllocCount; }\n    size_t GetFreeRegionsCount() const override { return m_BlocksFreeCount + 1; }\n    VkDeviceSize GetSumFreeSize() const override { return m_BlocksFreeSize + m_NullBlock->size; }\n    bool IsEmpty() const override { return m_NullBlock->offset == 0; }\n    VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return ((Block*)allocHandle)->offset; }\n\n    void Init(VkDeviceSize size) override;\n    bool Validate() const override;\n\n    void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;\n    void AddStatistics(VmaStatistics& inoutStats) const override;\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMap(class VmaJsonWriter& json) const override;\n#endif\n\n    bool CreateAllocationRequest(\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        bool upperAddress,\n        VmaSuballocationType allocType,\n        uint32_t strategy,\n        VmaAllocationRequest* pAllocationRequest) override;\n\n    VkResult CheckCorruption(const void* pBlockData) override;\n    void Alloc(\n        const VmaAllocationRequest& request,\n        VmaSuballocationType type,\n        void* userData) override;\n\n    void Free(VmaAllocHandle allocHandle) override;\n    void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;\n    void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;\n    VmaAllocHandle GetAllocationListBegin() const override;\n    VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;\n    VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const override;\n    void Clear() override;\n    void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;\n    void DebugLogAllAllocations() const override;\n\nprivate:\n    // According to original paper it should be preferable 4 or 5:\n    // M. Masmano, I. Ripoll, A. Crespo, and J. Real \"TLSF: a New Dynamic Memory Allocator for Real-Time Systems\"\n    // http://www.gii.upv.es/tlsf/files/ecrts04_tlsf.pdf\n    static const uint8_t SECOND_LEVEL_INDEX = 5;\n    static const uint16_t SMALL_BUFFER_SIZE = 256;\n    static const uint32_t INITIAL_BLOCK_ALLOC_COUNT = 16;\n    static const uint8_t MEMORY_CLASS_SHIFT = 7;\n    static const uint8_t MAX_MEMORY_CLASSES = 65 - MEMORY_CLASS_SHIFT;\n\n    class Block\n    {\n    public:\n        VkDeviceSize offset;\n        VkDeviceSize size;\n        Block* prevPhysical;\n        Block* nextPhysical;\n\n        void MarkFree() { prevFree = VMA_NULL; }\n        void MarkTaken() { prevFree = this; }\n        bool IsFree() const { return prevFree != this; }\n        void*& UserData() { VMA_HEAVY_ASSERT(!IsFree()); return userData; }\n        Block*& PrevFree() { return prevFree; }\n        Block*& NextFree() { VMA_HEAVY_ASSERT(IsFree()); return nextFree; }\n\n    private:\n        Block* prevFree; // Address of the same block here indicates that block is taken\n        union\n        {\n            Block* nextFree;\n            void* userData;\n        };\n    };\n\n    size_t m_AllocCount;\n    // Total number of free blocks besides null block\n    size_t m_BlocksFreeCount;\n    // Total size of free blocks excluding null block\n    VkDeviceSize m_BlocksFreeSize;\n    uint32_t m_IsFreeBitmap;\n    uint8_t m_MemoryClasses;\n    uint32_t m_InnerIsFreeBitmap[MAX_MEMORY_CLASSES];\n    uint32_t m_ListsCount;\n    /*\n    * 0: 0-3 lists for small buffers\n    * 1+: 0-(2^SLI-1) lists for normal buffers\n    */\n    Block** m_FreeList;\n    VmaPoolAllocator<Block> m_BlockAllocator;\n    Block* m_NullBlock;\n    VmaBlockBufferImageGranularity m_GranularityHandler;\n\n    uint8_t SizeToMemoryClass(VkDeviceSize size) const;\n    uint16_t SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const;\n    uint32_t GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const;\n    uint32_t GetListIndex(VkDeviceSize size) const;\n\n    void RemoveFreeBlock(Block* block);\n    void InsertFreeBlock(Block* block);\n    void MergeBlock(Block* block, Block* prev);\n\n    Block* FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const;\n    bool CheckBlock(\n        Block& block,\n        uint32_t listIndex,\n        VkDeviceSize allocSize,\n        VkDeviceSize allocAlignment,\n        VmaSuballocationType allocType,\n        VmaAllocationRequest* pAllocationRequest);\n};\n\n#ifndef _VMA_BLOCK_METADATA_TLSF_FUNCTIONS\nVmaBlockMetadata_TLSF::VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks,\n    VkDeviceSize bufferImageGranularity, bool isVirtual)\n    : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),\n    m_AllocCount(0),\n    m_BlocksFreeCount(0),\n    m_BlocksFreeSize(0),\n    m_IsFreeBitmap(0),\n    m_MemoryClasses(0),\n    m_ListsCount(0),\n    m_FreeList(VMA_NULL),\n    m_BlockAllocator(pAllocationCallbacks, INITIAL_BLOCK_ALLOC_COUNT),\n    m_NullBlock(VMA_NULL),\n    m_GranularityHandler(bufferImageGranularity) {}\n\nVmaBlockMetadata_TLSF::~VmaBlockMetadata_TLSF()\n{\n    if (m_FreeList)\n        vma_delete_array(GetAllocationCallbacks(), m_FreeList, m_ListsCount);\n    m_GranularityHandler.Destroy(GetAllocationCallbacks());\n}\n\nvoid VmaBlockMetadata_TLSF::Init(VkDeviceSize size)\n{\n    VmaBlockMetadata::Init(size);\n\n    if (!IsVirtual())\n        m_GranularityHandler.Init(GetAllocationCallbacks(), size);\n\n    m_NullBlock = m_BlockAllocator.Alloc();\n    m_NullBlock->size = size;\n    m_NullBlock->offset = 0;\n    m_NullBlock->prevPhysical = VMA_NULL;\n    m_NullBlock->nextPhysical = VMA_NULL;\n    m_NullBlock->MarkFree();\n    m_NullBlock->NextFree() = VMA_NULL;\n    m_NullBlock->PrevFree() = VMA_NULL;\n    uint8_t memoryClass = SizeToMemoryClass(size);\n    uint16_t sli = SizeToSecondIndex(size, memoryClass);\n    m_ListsCount = (memoryClass == 0 ? 0 : (memoryClass - 1) * (1UL << SECOND_LEVEL_INDEX) + sli) + 1;\n    if (IsVirtual())\n        m_ListsCount += 1UL << SECOND_LEVEL_INDEX;\n    else\n        m_ListsCount += 4;\n\n    m_MemoryClasses = memoryClass + 2;\n    memset(m_InnerIsFreeBitmap, 0, MAX_MEMORY_CLASSES * sizeof(uint32_t));\n\n    m_FreeList = vma_new_array(GetAllocationCallbacks(), Block*, m_ListsCount);\n    memset(m_FreeList, 0, m_ListsCount * sizeof(Block*));\n}\n\nbool VmaBlockMetadata_TLSF::Validate() const\n{\n    VMA_VALIDATE(GetSumFreeSize() <= GetSize());\n\n    VkDeviceSize calculatedSize = m_NullBlock->size;\n    VkDeviceSize calculatedFreeSize = m_NullBlock->size;\n    size_t allocCount = 0;\n    size_t freeCount = 0;\n\n    // Check integrity of free lists\n    for (uint32_t list = 0; list < m_ListsCount; ++list)\n    {\n        Block* block = m_FreeList[list];\n        if (block != VMA_NULL)\n        {\n            VMA_VALIDATE(block->IsFree());\n            VMA_VALIDATE(block->PrevFree() == VMA_NULL);\n            while (block->NextFree())\n            {\n                VMA_VALIDATE(block->NextFree()->IsFree());\n                VMA_VALIDATE(block->NextFree()->PrevFree() == block);\n                block = block->NextFree();\n            }\n        }\n    }\n\n    VkDeviceSize nextOffset = m_NullBlock->offset;\n    auto validateCtx = m_GranularityHandler.StartValidation(GetAllocationCallbacks(), IsVirtual());\n\n    VMA_VALIDATE(m_NullBlock->nextPhysical == VMA_NULL);\n    if (m_NullBlock->prevPhysical)\n    {\n        VMA_VALIDATE(m_NullBlock->prevPhysical->nextPhysical == m_NullBlock);\n    }\n    // Check all blocks\n    for (Block* prev = m_NullBlock->prevPhysical; prev != VMA_NULL; prev = prev->prevPhysical)\n    {\n        VMA_VALIDATE(prev->offset + prev->size == nextOffset);\n        nextOffset = prev->offset;\n        calculatedSize += prev->size;\n\n        uint32_t listIndex = GetListIndex(prev->size);\n        if (prev->IsFree())\n        {\n            ++freeCount;\n            // Check if free block belongs to free list\n            Block* freeBlock = m_FreeList[listIndex];\n            VMA_VALIDATE(freeBlock != VMA_NULL);\n\n            bool found = false;\n            do\n            {\n                if (freeBlock == prev)\n                    found = true;\n\n                freeBlock = freeBlock->NextFree();\n            } while (!found && freeBlock != VMA_NULL);\n\n            VMA_VALIDATE(found);\n            calculatedFreeSize += prev->size;\n        }\n        else\n        {\n            ++allocCount;\n            // Check if taken block is not on a free list\n            Block* freeBlock = m_FreeList[listIndex];\n            while (freeBlock)\n            {\n                VMA_VALIDATE(freeBlock != prev);\n                freeBlock = freeBlock->NextFree();\n            }\n\n            if (!IsVirtual())\n            {\n                VMA_VALIDATE(m_GranularityHandler.Validate(validateCtx, prev->offset, prev->size));\n            }\n        }\n\n        if (prev->prevPhysical)\n        {\n            VMA_VALIDATE(prev->prevPhysical->nextPhysical == prev);\n        }\n    }\n\n    if (!IsVirtual())\n    {\n        VMA_VALIDATE(m_GranularityHandler.FinishValidation(validateCtx));\n    }\n\n    VMA_VALIDATE(nextOffset == 0);\n    VMA_VALIDATE(calculatedSize == GetSize());\n    VMA_VALIDATE(calculatedFreeSize == GetSumFreeSize());\n    VMA_VALIDATE(allocCount == m_AllocCount);\n    VMA_VALIDATE(freeCount == m_BlocksFreeCount);\n\n    return true;\n}\n\nvoid VmaBlockMetadata_TLSF::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const\n{\n    inoutStats.statistics.blockCount++;\n    inoutStats.statistics.blockBytes += GetSize();\n    if (m_NullBlock->size > 0)\n        VmaAddDetailedStatisticsUnusedRange(inoutStats, m_NullBlock->size);\n\n    for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)\n    {\n        if (block->IsFree())\n            VmaAddDetailedStatisticsUnusedRange(inoutStats, block->size);\n        else\n            VmaAddDetailedStatisticsAllocation(inoutStats, block->size);\n    }\n}\n\nvoid VmaBlockMetadata_TLSF::AddStatistics(VmaStatistics& inoutStats) const\n{\n    inoutStats.blockCount++;\n    inoutStats.allocationCount += (uint32_t)m_AllocCount;\n    inoutStats.blockBytes += GetSize();\n    inoutStats.allocationBytes += GetSize() - GetSumFreeSize();\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockMetadata_TLSF::PrintDetailedMap(class VmaJsonWriter& json) const\n{\n    size_t blockCount = m_AllocCount + m_BlocksFreeCount;\n    VmaStlAllocator<Block*> allocator(GetAllocationCallbacks());\n    VmaVector<Block*, VmaStlAllocator<Block*>> blockList(blockCount, allocator);\n\n    size_t i = blockCount;\n    for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)\n    {\n        blockList[--i] = block;\n    }\n    VMA_ASSERT(i == 0);\n\n    VmaDetailedStatistics stats;\n    VmaClearDetailedStatistics(stats);\n    AddDetailedStatistics(stats);\n\n    PrintDetailedMap_Begin(json,\n        stats.statistics.blockBytes - stats.statistics.allocationBytes,\n        stats.statistics.allocationCount,\n        stats.unusedRangeCount);\n\n    for (; i < blockCount; ++i)\n    {\n        Block* block = blockList[i];\n        if (block->IsFree())\n            PrintDetailedMap_UnusedRange(json, block->offset, block->size);\n        else\n            PrintDetailedMap_Allocation(json, block->offset, block->size, block->UserData());\n    }\n    if (m_NullBlock->size > 0)\n        PrintDetailedMap_UnusedRange(json, m_NullBlock->offset, m_NullBlock->size);\n\n    PrintDetailedMap_End(json);\n}\n#endif\n\nbool VmaBlockMetadata_TLSF::CreateAllocationRequest(\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    bool upperAddress,\n    VmaSuballocationType allocType,\n    uint32_t strategy,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    VMA_ASSERT(allocSize > 0 && \"Cannot allocate empty block!\");\n    VMA_ASSERT(!upperAddress && \"VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.\");\n\n    // For small granularity round up\n    if (!IsVirtual())\n        m_GranularityHandler.RoundupAllocRequest(allocType, allocSize, allocAlignment);\n\n    allocSize += GetDebugMargin();\n    // Quick check for too small pool\n    if (allocSize > GetSumFreeSize())\n        return false;\n\n    // If no free blocks in pool then check only null block\n    if (m_BlocksFreeCount == 0)\n        return CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest);\n\n    // Round up to the next block\n    VkDeviceSize sizeForNextList = allocSize;\n    VkDeviceSize smallSizeStep = SMALL_BUFFER_SIZE / (IsVirtual() ? 1 << SECOND_LEVEL_INDEX : 4);\n    if (allocSize > SMALL_BUFFER_SIZE)\n    {\n        sizeForNextList += (1ULL << (VMA_BITSCAN_MSB(allocSize) - SECOND_LEVEL_INDEX));\n    }\n    else if (allocSize > SMALL_BUFFER_SIZE - smallSizeStep)\n        sizeForNextList = SMALL_BUFFER_SIZE + 1;\n    else\n        sizeForNextList += smallSizeStep;\n\n    uint32_t nextListIndex = 0;\n    uint32_t prevListIndex = 0;\n    Block* nextListBlock = VMA_NULL;\n    Block* prevListBlock = VMA_NULL;\n\n    // Check blocks according to strategies\n    if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT)\n    {\n        // Quick check for larger block first\n        nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex);\n        if (nextListBlock != VMA_NULL && CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n            return true;\n\n        // If not fitted then null block\n        if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))\n            return true;\n\n        // Null block failed, search larger bucket\n        while (nextListBlock)\n        {\n            if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            nextListBlock = nextListBlock->NextFree();\n        }\n\n        // Failed again, check best fit bucket\n        prevListBlock = FindFreeBlock(allocSize, prevListIndex);\n        while (prevListBlock)\n        {\n            if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            prevListBlock = prevListBlock->NextFree();\n        }\n    }\n    else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT)\n    {\n        // Check best fit bucket\n        prevListBlock = FindFreeBlock(allocSize, prevListIndex);\n        while (prevListBlock)\n        {\n            if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            prevListBlock = prevListBlock->NextFree();\n        }\n\n        // If failed check null block\n        if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))\n            return true;\n\n        // Check larger bucket\n        nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex);\n        while (nextListBlock)\n        {\n            if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            nextListBlock = nextListBlock->NextFree();\n        }\n    }\n    else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT )\n    {\n        // Perform search from the start\n        VmaStlAllocator<Block*> allocator(GetAllocationCallbacks());\n        VmaVector<Block*, VmaStlAllocator<Block*>> blockList(m_BlocksFreeCount, allocator);\n\n        size_t i = m_BlocksFreeCount;\n        for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)\n        {\n            if (block->IsFree() && block->size >= allocSize)\n                blockList[--i] = block;\n        }\n\n        for (; i < m_BlocksFreeCount; ++i)\n        {\n            Block& block = *blockList[i];\n            if (CheckBlock(block, GetListIndex(block.size), allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n        }\n\n        // If failed check null block\n        if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))\n            return true;\n\n        // Whole range searched, no more memory\n        return false;\n    }\n    else\n    {\n        // Check larger bucket\n        nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex);\n        while (nextListBlock)\n        {\n            if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            nextListBlock = nextListBlock->NextFree();\n        }\n\n        // If failed check null block\n        if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))\n            return true;\n\n        // Check best fit bucket\n        prevListBlock = FindFreeBlock(allocSize, prevListIndex);\n        while (prevListBlock)\n        {\n            if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            prevListBlock = prevListBlock->NextFree();\n        }\n    }\n\n    // Worst case, full search has to be done\n    while (++nextListIndex < m_ListsCount)\n    {\n        nextListBlock = m_FreeList[nextListIndex];\n        while (nextListBlock)\n        {\n            if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))\n                return true;\n            nextListBlock = nextListBlock->NextFree();\n        }\n    }\n\n    // No more memory sadly\n    return false;\n}\n\nVkResult VmaBlockMetadata_TLSF::CheckCorruption(const void* pBlockData)\n{\n    for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)\n    {\n        if (!block->IsFree())\n        {\n            if (!VmaValidateMagicValue(pBlockData, block->offset + block->size))\n            {\n                VMA_ASSERT(0 && \"MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!\");\n                return VK_ERROR_UNKNOWN_COPY;\n            }\n        }\n    }\n\n    return VK_SUCCESS;\n}\n\nvoid VmaBlockMetadata_TLSF::Alloc(\n    const VmaAllocationRequest& request,\n    VmaSuballocationType type,\n    void* userData)\n{\n    VMA_ASSERT(request.type == VmaAllocationRequestType::TLSF);\n\n    // Get block and pop it from the free list\n    Block* currentBlock = (Block*)request.allocHandle;\n    VkDeviceSize offset = request.algorithmData;\n    VMA_ASSERT(currentBlock != VMA_NULL);\n    VMA_ASSERT(currentBlock->offset <= offset);\n\n    if (currentBlock != m_NullBlock)\n        RemoveFreeBlock(currentBlock);\n\n    VkDeviceSize debugMargin = GetDebugMargin();\n    VkDeviceSize misssingAlignment = offset - currentBlock->offset;\n\n    // Append missing alignment to prev block or create new one\n    if (misssingAlignment)\n    {\n        Block* prevBlock = currentBlock->prevPhysical;\n        VMA_ASSERT(prevBlock != VMA_NULL && \"There should be no missing alignment at offset 0!\");\n\n        if (prevBlock->IsFree() && prevBlock->size != debugMargin)\n        {\n            uint32_t oldList = GetListIndex(prevBlock->size);\n            prevBlock->size += misssingAlignment;\n            // Check if new size crosses list bucket\n            if (oldList != GetListIndex(prevBlock->size))\n            {\n                prevBlock->size -= misssingAlignment;\n                RemoveFreeBlock(prevBlock);\n                prevBlock->size += misssingAlignment;\n                InsertFreeBlock(prevBlock);\n            }\n            else\n                m_BlocksFreeSize += misssingAlignment;\n        }\n        else\n        {\n            Block* newBlock = m_BlockAllocator.Alloc();\n            currentBlock->prevPhysical = newBlock;\n            prevBlock->nextPhysical = newBlock;\n            newBlock->prevPhysical = prevBlock;\n            newBlock->nextPhysical = currentBlock;\n            newBlock->size = misssingAlignment;\n            newBlock->offset = currentBlock->offset;\n            newBlock->MarkTaken();\n\n            InsertFreeBlock(newBlock);\n        }\n\n        currentBlock->size -= misssingAlignment;\n        currentBlock->offset += misssingAlignment;\n    }\n\n    VkDeviceSize size = request.size + debugMargin;\n    if (currentBlock->size == size)\n    {\n        if (currentBlock == m_NullBlock)\n        {\n            // Setup new null block\n            m_NullBlock = m_BlockAllocator.Alloc();\n            m_NullBlock->size = 0;\n            m_NullBlock->offset = currentBlock->offset + size;\n            m_NullBlock->prevPhysical = currentBlock;\n            m_NullBlock->nextPhysical = VMA_NULL;\n            m_NullBlock->MarkFree();\n            m_NullBlock->PrevFree() = VMA_NULL;\n            m_NullBlock->NextFree() = VMA_NULL;\n            currentBlock->nextPhysical = m_NullBlock;\n            currentBlock->MarkTaken();\n        }\n    }\n    else\n    {\n        VMA_ASSERT(currentBlock->size > size && \"Proper block already found, shouldn't find smaller one!\");\n\n        // Create new free block\n        Block* newBlock = m_BlockAllocator.Alloc();\n        newBlock->size = currentBlock->size - size;\n        newBlock->offset = currentBlock->offset + size;\n        newBlock->prevPhysical = currentBlock;\n        newBlock->nextPhysical = currentBlock->nextPhysical;\n        currentBlock->nextPhysical = newBlock;\n        currentBlock->size = size;\n\n        if (currentBlock == m_NullBlock)\n        {\n            m_NullBlock = newBlock;\n            m_NullBlock->MarkFree();\n            m_NullBlock->NextFree() = VMA_NULL;\n            m_NullBlock->PrevFree() = VMA_NULL;\n            currentBlock->MarkTaken();\n        }\n        else\n        {\n            newBlock->nextPhysical->prevPhysical = newBlock;\n            newBlock->MarkTaken();\n            InsertFreeBlock(newBlock);\n        }\n    }\n    currentBlock->UserData() = userData;\n\n    if (debugMargin > 0)\n    {\n        currentBlock->size -= debugMargin;\n        Block* newBlock = m_BlockAllocator.Alloc();\n        newBlock->size = debugMargin;\n        newBlock->offset = currentBlock->offset + currentBlock->size;\n        newBlock->prevPhysical = currentBlock;\n        newBlock->nextPhysical = currentBlock->nextPhysical;\n        newBlock->MarkTaken();\n        currentBlock->nextPhysical->prevPhysical = newBlock;\n        currentBlock->nextPhysical = newBlock;\n        InsertFreeBlock(newBlock);\n    }\n\n    if (!IsVirtual())\n        m_GranularityHandler.AllocPages((uint8_t)(uintptr_t)request.customData,\n            currentBlock->offset, currentBlock->size);\n    ++m_AllocCount;\n}\n\nvoid VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle)\n{\n    Block* block = (Block*)allocHandle;\n    Block* next = block->nextPhysical;\n    VMA_ASSERT(!block->IsFree() && \"Block is already free!\");\n\n    if (!IsVirtual())\n        m_GranularityHandler.FreePages(block->offset, block->size);\n    --m_AllocCount;\n\n    VkDeviceSize debugMargin = GetDebugMargin();\n    if (debugMargin > 0)\n    {\n        RemoveFreeBlock(next);\n        MergeBlock(next, block);\n        block = next;\n        next = next->nextPhysical;\n    }\n\n    // Try merging\n    Block* prev = block->prevPhysical;\n    if (prev != VMA_NULL && prev->IsFree() && prev->size != debugMargin)\n    {\n        RemoveFreeBlock(prev);\n        MergeBlock(block, prev);\n    }\n\n    if (!next->IsFree())\n        InsertFreeBlock(block);\n    else if (next == m_NullBlock)\n        MergeBlock(m_NullBlock, block);\n    else\n    {\n        RemoveFreeBlock(next);\n        MergeBlock(next, block);\n        InsertFreeBlock(next);\n    }\n}\n\nvoid VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)\n{\n    Block* block = (Block*)allocHandle;\n    VMA_ASSERT(!block->IsFree() && \"Cannot get allocation info for free block!\");\n    outInfo.offset = block->offset;\n    outInfo.size = block->size;\n    outInfo.pUserData = block->UserData();\n}\n\nvoid* VmaBlockMetadata_TLSF::GetAllocationUserData(VmaAllocHandle allocHandle) const\n{\n    Block* block = (Block*)allocHandle;\n    VMA_ASSERT(!block->IsFree() && \"Cannot get user data for free block!\");\n    return block->UserData();\n}\n\nVmaAllocHandle VmaBlockMetadata_TLSF::GetAllocationListBegin() const\n{\n    if (m_AllocCount == 0)\n        return VK_NULL_HANDLE;\n\n    for (Block* block = m_NullBlock->prevPhysical; block; block = block->prevPhysical)\n    {\n        if (!block->IsFree())\n            return (VmaAllocHandle)block;\n    }\n    VMA_ASSERT(false && \"If m_AllocCount > 0 then should find any allocation!\");\n    return VK_NULL_HANDLE;\n}\n\nVmaAllocHandle VmaBlockMetadata_TLSF::GetNextAllocation(VmaAllocHandle prevAlloc) const\n{\n    Block* startBlock = (Block*)prevAlloc;\n    VMA_ASSERT(!startBlock->IsFree() && \"Incorrect block!\");\n\n    for (Block* block = startBlock->prevPhysical; block; block = block->prevPhysical)\n    {\n        if (!block->IsFree())\n            return (VmaAllocHandle)block;\n    }\n    return VK_NULL_HANDLE;\n}\n\nVkDeviceSize VmaBlockMetadata_TLSF::GetNextFreeRegionSize(VmaAllocHandle alloc) const\n{\n    Block* block = (Block*)alloc;\n    VMA_ASSERT(!block->IsFree() && \"Incorrect block!\");\n\n    if (block->prevPhysical)\n        return block->prevPhysical->IsFree() ? block->prevPhysical->size : 0;\n    return 0;\n}\n\nvoid VmaBlockMetadata_TLSF::Clear()\n{\n    m_AllocCount = 0;\n    m_BlocksFreeCount = 0;\n    m_BlocksFreeSize = 0;\n    m_IsFreeBitmap = 0;\n    m_NullBlock->offset = 0;\n    m_NullBlock->size = GetSize();\n    Block* block = m_NullBlock->prevPhysical;\n    m_NullBlock->prevPhysical = VMA_NULL;\n    while (block)\n    {\n        Block* prev = block->prevPhysical;\n        m_BlockAllocator.Free(block);\n        block = prev;\n    }\n    memset(m_FreeList, 0, m_ListsCount * sizeof(Block*));\n    memset(m_InnerIsFreeBitmap, 0, m_MemoryClasses * sizeof(uint32_t));\n    m_GranularityHandler.Clear();\n}\n\nvoid VmaBlockMetadata_TLSF::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)\n{\n    Block* block = (Block*)allocHandle;\n    VMA_ASSERT(!block->IsFree() && \"Trying to set user data for not allocated block!\");\n    block->UserData() = userData;\n}\n\nvoid VmaBlockMetadata_TLSF::DebugLogAllAllocations() const\n{\n    for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)\n        if (!block->IsFree())\n            DebugLogAllocation(block->offset, block->size, block->UserData());\n}\n\nuint8_t VmaBlockMetadata_TLSF::SizeToMemoryClass(VkDeviceSize size) const\n{\n    if (size > SMALL_BUFFER_SIZE)\n        return VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT;\n    return 0;\n}\n\nuint16_t VmaBlockMetadata_TLSF::SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const\n{\n    if (memoryClass == 0)\n    {\n        if (IsVirtual())\n            return static_cast<uint16_t>((size - 1) / 8);\n        else\n            return static_cast<uint16_t>((size - 1) / 64);\n    }\n    return static_cast<uint16_t>((size >> (memoryClass + MEMORY_CLASS_SHIFT - SECOND_LEVEL_INDEX)) ^ (1U << SECOND_LEVEL_INDEX));\n}\n\nuint32_t VmaBlockMetadata_TLSF::GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const\n{\n    if (memoryClass == 0)\n        return secondIndex;\n\n    const uint32_t index = static_cast<uint32_t>(memoryClass - 1) * (1 << SECOND_LEVEL_INDEX) + secondIndex;\n    if (IsVirtual())\n        return index + (1 << SECOND_LEVEL_INDEX);\n    else\n        return index + 4;\n}\n\nuint32_t VmaBlockMetadata_TLSF::GetListIndex(VkDeviceSize size) const\n{\n    uint8_t memoryClass = SizeToMemoryClass(size);\n    return GetListIndex(memoryClass, SizeToSecondIndex(size, memoryClass));\n}\n\nvoid VmaBlockMetadata_TLSF::RemoveFreeBlock(Block* block)\n{\n    VMA_ASSERT(block != m_NullBlock);\n    VMA_ASSERT(block->IsFree());\n\n    if (block->NextFree() != VMA_NULL)\n        block->NextFree()->PrevFree() = block->PrevFree();\n    if (block->PrevFree() != VMA_NULL)\n        block->PrevFree()->NextFree() = block->NextFree();\n    else\n    {\n        uint8_t memClass = SizeToMemoryClass(block->size);\n        uint16_t secondIndex = SizeToSecondIndex(block->size, memClass);\n        uint32_t index = GetListIndex(memClass, secondIndex);\n        VMA_ASSERT(m_FreeList[index] == block);\n        m_FreeList[index] = block->NextFree();\n        if (block->NextFree() == VMA_NULL)\n        {\n            m_InnerIsFreeBitmap[memClass] &= ~(1U << secondIndex);\n            if (m_InnerIsFreeBitmap[memClass] == 0)\n                m_IsFreeBitmap &= ~(1UL << memClass);\n        }\n    }\n    block->MarkTaken();\n    block->UserData() = VMA_NULL;\n    --m_BlocksFreeCount;\n    m_BlocksFreeSize -= block->size;\n}\n\nvoid VmaBlockMetadata_TLSF::InsertFreeBlock(Block* block)\n{\n    VMA_ASSERT(block != m_NullBlock);\n    VMA_ASSERT(!block->IsFree() && \"Cannot insert block twice!\");\n\n    uint8_t memClass = SizeToMemoryClass(block->size);\n    uint16_t secondIndex = SizeToSecondIndex(block->size, memClass);\n    uint32_t index = GetListIndex(memClass, secondIndex);\n    VMA_ASSERT(index < m_ListsCount);\n    block->PrevFree() = VMA_NULL;\n    block->NextFree() = m_FreeList[index];\n    m_FreeList[index] = block;\n    if (block->NextFree() != VMA_NULL)\n        block->NextFree()->PrevFree() = block;\n    else\n    {\n        m_InnerIsFreeBitmap[memClass] |= 1U << secondIndex;\n        m_IsFreeBitmap |= 1UL << memClass;\n    }\n    ++m_BlocksFreeCount;\n    m_BlocksFreeSize += block->size;\n}\n\nvoid VmaBlockMetadata_TLSF::MergeBlock(Block* block, Block* prev)\n{\n    VMA_ASSERT(block->prevPhysical == prev && \"Cannot merge separate physical regions!\");\n    VMA_ASSERT(!prev->IsFree() && \"Cannot merge block that belongs to free list!\");\n\n    block->offset = prev->offset;\n    block->size += prev->size;\n    block->prevPhysical = prev->prevPhysical;\n    if (block->prevPhysical)\n        block->prevPhysical->nextPhysical = block;\n    m_BlockAllocator.Free(prev);\n}\n\nVmaBlockMetadata_TLSF::Block* VmaBlockMetadata_TLSF::FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const\n{\n    uint8_t memoryClass = SizeToMemoryClass(size);\n    uint32_t innerFreeMap = m_InnerIsFreeBitmap[memoryClass] & (~0U << SizeToSecondIndex(size, memoryClass));\n    if (!innerFreeMap)\n    {\n        // Check higher levels for available blocks\n        uint32_t freeMap = m_IsFreeBitmap & (~0UL << (memoryClass + 1));\n        if (!freeMap)\n            return VMA_NULL; // No more memory available\n\n        // Find lowest free region\n        memoryClass = VMA_BITSCAN_LSB(freeMap);\n        innerFreeMap = m_InnerIsFreeBitmap[memoryClass];\n        VMA_ASSERT(innerFreeMap != 0);\n    }\n    // Find lowest free subregion\n    listIndex = GetListIndex(memoryClass, VMA_BITSCAN_LSB(innerFreeMap));\n    VMA_ASSERT(m_FreeList[listIndex]);\n    return m_FreeList[listIndex];\n}\n\nbool VmaBlockMetadata_TLSF::CheckBlock(\n    Block& block,\n    uint32_t listIndex,\n    VkDeviceSize allocSize,\n    VkDeviceSize allocAlignment,\n    VmaSuballocationType allocType,\n    VmaAllocationRequest* pAllocationRequest)\n{\n    VMA_ASSERT(block.IsFree() && \"Block is already taken!\");\n\n    VkDeviceSize alignedOffset = VmaAlignUp(block.offset, allocAlignment);\n    if (block.size < allocSize + alignedOffset - block.offset)\n        return false;\n\n    // Check for granularity conflicts\n    if (!IsVirtual() &&\n        m_GranularityHandler.CheckConflictAndAlignUp(alignedOffset, allocSize, block.offset, block.size, allocType))\n        return false;\n\n    // Alloc successful\n    pAllocationRequest->type = VmaAllocationRequestType::TLSF;\n    pAllocationRequest->allocHandle = (VmaAllocHandle)&block;\n    pAllocationRequest->size = allocSize - GetDebugMargin();\n    pAllocationRequest->customData = (void*)allocType;\n    pAllocationRequest->algorithmData = alignedOffset;\n\n    // Place block at the start of list if it's normal block\n    if (listIndex != m_ListsCount && block.PrevFree())\n    {\n        block.PrevFree()->NextFree() = block.NextFree();\n        if (block.NextFree())\n            block.NextFree()->PrevFree() = block.PrevFree();\n        block.PrevFree() = VMA_NULL;\n        block.NextFree() = m_FreeList[listIndex];\n        m_FreeList[listIndex] = &block;\n        if (block.NextFree())\n            block.NextFree()->PrevFree() = &block;\n    }\n\n    return true;\n}\n#endif // _VMA_BLOCK_METADATA_TLSF_FUNCTIONS\n#endif // _VMA_BLOCK_METADATA_TLSF\n\n#ifndef _VMA_BLOCK_VECTOR\n/*\nSequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific\nVulkan memory type.\n\nSynchronized internally with a mutex.\n*/\nclass VmaBlockVector\n{\n    friend struct VmaDefragmentationContext_T;\n    VMA_CLASS_NO_COPY(VmaBlockVector)\npublic:\n    VmaBlockVector(\n        VmaAllocator hAllocator,\n        VmaPool hParentPool,\n        uint32_t memoryTypeIndex,\n        VkDeviceSize preferredBlockSize,\n        size_t minBlockCount,\n        size_t maxBlockCount,\n        VkDeviceSize bufferImageGranularity,\n        bool explicitBlockSize,\n        uint32_t algorithm,\n        float priority,\n        VkDeviceSize minAllocationAlignment,\n        void* pMemoryAllocateNext);\n    ~VmaBlockVector();\n\n    VmaAllocator GetAllocator() const { return m_hAllocator; }\n    VmaPool GetParentPool() const { return m_hParentPool; }\n    bool IsCustomPool() const { return m_hParentPool != VMA_NULL; }\n    uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }\n    VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }\n    VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }\n    uint32_t GetAlgorithm() const { return m_Algorithm; }\n    bool HasExplicitBlockSize() const { return m_ExplicitBlockSize; }\n    float GetPriority() const { return m_Priority; }\n    const void* GetAllocationNextPtr() const { return m_pMemoryAllocateNext; }\n    // To be used only while the m_Mutex is locked. Used during defragmentation.\n    size_t GetBlockCount() const { return m_Blocks.size(); }\n    // To be used only while the m_Mutex is locked. Used during defragmentation.\n    VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; }\n    VMA_RW_MUTEX &GetMutex() { return m_Mutex; }\n\n    VkResult CreateMinBlocks();\n    void AddStatistics(VmaStatistics& inoutStats);\n    void AddDetailedStatistics(VmaDetailedStatistics& inoutStats);\n    bool IsEmpty();\n    bool IsCorruptionDetectionEnabled() const;\n\n    VkResult Allocate(\n        VkDeviceSize size,\n        VkDeviceSize alignment,\n        const VmaAllocationCreateInfo& createInfo,\n        VmaSuballocationType suballocType,\n        size_t allocationCount,\n        VmaAllocation* pAllocations);\n\n    void Free(const VmaAllocation hAllocation);\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMap(class VmaJsonWriter& json);\n#endif\n\n    VkResult CheckCorruption();\n\nprivate:\n    const VmaAllocator m_hAllocator;\n    const VmaPool m_hParentPool;\n    const uint32_t m_MemoryTypeIndex;\n    const VkDeviceSize m_PreferredBlockSize;\n    const size_t m_MinBlockCount;\n    const size_t m_MaxBlockCount;\n    const VkDeviceSize m_BufferImageGranularity;\n    const bool m_ExplicitBlockSize;\n    const uint32_t m_Algorithm;\n    const float m_Priority;\n    const VkDeviceSize m_MinAllocationAlignment;\n\n    void* const m_pMemoryAllocateNext;\n    VMA_RW_MUTEX m_Mutex;\n    // Incrementally sorted by sumFreeSize, ascending.\n    VmaVector<VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*>> m_Blocks;\n    uint32_t m_NextBlockId;\n    bool m_IncrementalSort = true;\n\n    void SetIncrementalSort(bool val) { m_IncrementalSort = val; }\n\n    VkDeviceSize CalcMaxBlockSize() const;\n    // Finds and removes given block from vector.\n    void Remove(VmaDeviceMemoryBlock* pBlock);\n    // Performs single step in sorting m_Blocks. They may not be fully sorted\n    // after this call.\n    void IncrementallySortBlocks();\n    void SortByFreeSize();\n\n    VkResult AllocatePage(\n        VkDeviceSize size,\n        VkDeviceSize alignment,\n        const VmaAllocationCreateInfo& createInfo,\n        VmaSuballocationType suballocType,\n        VmaAllocation* pAllocation);\n\n    VkResult AllocateFromBlock(\n        VmaDeviceMemoryBlock* pBlock,\n        VkDeviceSize size,\n        VkDeviceSize alignment,\n        VmaAllocationCreateFlags allocFlags,\n        void* pUserData,\n        VmaSuballocationType suballocType,\n        uint32_t strategy,\n        VmaAllocation* pAllocation);\n\n    VkResult CommitAllocationRequest(\n        VmaAllocationRequest& allocRequest,\n        VmaDeviceMemoryBlock* pBlock,\n        VkDeviceSize alignment,\n        VmaAllocationCreateFlags allocFlags,\n        void* pUserData,\n        VmaSuballocationType suballocType,\n        VmaAllocation* pAllocation);\n\n    VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex);\n    bool HasEmptyBlock();\n};\n#endif // _VMA_BLOCK_VECTOR\n\n#ifndef _VMA_DEFRAGMENTATION_CONTEXT\nstruct VmaDefragmentationContext_T\n{\n    VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)\npublic:\n    VmaDefragmentationContext_T(\n        VmaAllocator hAllocator,\n        const VmaDefragmentationInfo& info);\n    ~VmaDefragmentationContext_T();\n\n    void GetStats(VmaDefragmentationStats& outStats) { outStats = m_GlobalStats; }\n\n    VkResult DefragmentPassBegin(VmaDefragmentationPassMoveInfo& moveInfo);\n    VkResult DefragmentPassEnd(VmaDefragmentationPassMoveInfo& moveInfo);\n\nprivate:\n    // Max number of allocations to ignore due to size constraints before ending single pass\n    static const uint8_t MAX_ALLOCS_TO_IGNORE = 16;\n    enum class CounterStatus { Pass, Ignore, End };\n\n    struct FragmentedBlock\n    {\n        uint32_t data;\n        VmaDeviceMemoryBlock* block;\n    };\n    struct StateBalanced\n    {\n        VkDeviceSize avgFreeSize = 0;\n        VkDeviceSize avgAllocSize = UINT64_MAX;\n    };\n    struct StateExtensive\n    {\n        enum class Operation : uint8_t\n        {\n            FindFreeBlockBuffer, FindFreeBlockTexture, FindFreeBlockAll,\n            MoveBuffers, MoveTextures, MoveAll,\n            Cleanup, Done\n        };\n\n        Operation operation = Operation::FindFreeBlockTexture;\n        size_t firstFreeBlock = SIZE_MAX;\n    };\n    struct MoveAllocationData\n    {\n        VkDeviceSize size;\n        VkDeviceSize alignment;\n        VmaSuballocationType type;\n        VmaAllocationCreateFlags flags;\n        VmaDefragmentationMove move = {};\n    };\n\n    const VkDeviceSize m_MaxPassBytes;\n    const uint32_t m_MaxPassAllocations;\n\n    VmaStlAllocator<VmaDefragmentationMove> m_MoveAllocator;\n    VmaVector<VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove>> m_Moves;\n\n    uint8_t m_IgnoredAllocs = 0;\n    uint32_t m_Algorithm;\n    uint32_t m_BlockVectorCount;\n    VmaBlockVector* m_PoolBlockVector;\n    VmaBlockVector** m_pBlockVectors;\n    size_t m_ImmovableBlockCount = 0;\n    VmaDefragmentationStats m_GlobalStats = { 0 };\n    VmaDefragmentationStats m_PassStats = { 0 };\n    void* m_AlgorithmState = VMA_NULL;\n\n    static MoveAllocationData GetMoveData(VmaAllocHandle handle, VmaBlockMetadata* metadata);\n    CounterStatus CheckCounters(VkDeviceSize bytes);\n    bool IncrementCounters(VkDeviceSize bytes);\n    bool ReallocWithinBlock(VmaBlockVector& vector, VmaDeviceMemoryBlock* block);\n    bool AllocInOtherBlock(size_t start, size_t end, MoveAllocationData& data, VmaBlockVector& vector);\n\n    bool ComputeDefragmentation(VmaBlockVector& vector, size_t index);\n    bool ComputeDefragmentation_Fast(VmaBlockVector& vector);\n    bool ComputeDefragmentation_Balanced(VmaBlockVector& vector, size_t index, bool update);\n    bool ComputeDefragmentation_Full(VmaBlockVector& vector);\n    bool ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index);\n\n    void UpdateVectorStatistics(VmaBlockVector& vector, StateBalanced& state);\n    bool MoveDataToFreeBlocks(VmaSuballocationType currentType,\n        VmaBlockVector& vector, size_t firstFreeBlock,\n        bool& texturePresent, bool& bufferPresent, bool& otherPresent);\n};\n#endif // _VMA_DEFRAGMENTATION_CONTEXT\n\n#ifndef _VMA_POOL_T\nstruct VmaPool_T\n{\n    friend struct VmaPoolListItemTraits;\n    VMA_CLASS_NO_COPY(VmaPool_T)\npublic:\n    VmaBlockVector m_BlockVector;\n    VmaDedicatedAllocationList m_DedicatedAllocations;\n\n    VmaPool_T(\n        VmaAllocator hAllocator,\n        const VmaPoolCreateInfo& createInfo,\n        VkDeviceSize preferredBlockSize);\n    ~VmaPool_T();\n\n    uint32_t GetId() const { return m_Id; }\n    void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }\n\n    const char* GetName() const { return m_Name; }\n    void SetName(const char* pName);\n\n#if VMA_STATS_STRING_ENABLED\n    //void PrintDetailedMap(class VmaStringBuilder& sb);\n#endif\n\nprivate:\n    uint32_t m_Id;\n    char* m_Name;\n    VmaPool_T* m_PrevPool = VMA_NULL;\n    VmaPool_T* m_NextPool = VMA_NULL;\n};\n\nstruct VmaPoolListItemTraits\n{\n    typedef VmaPool_T ItemType;\n\n    static ItemType* GetPrev(const ItemType* item) { return item->m_PrevPool; }\n    static ItemType* GetNext(const ItemType* item) { return item->m_NextPool; }\n    static ItemType*& AccessPrev(ItemType* item) { return item->m_PrevPool; }\n    static ItemType*& AccessNext(ItemType* item) { return item->m_NextPool; }\n};\n#endif // _VMA_POOL_T\n\n#ifndef _VMA_CURRENT_BUDGET_DATA\nstruct VmaCurrentBudgetData\n{\n    VMA_ATOMIC_UINT32 m_BlockCount[VK_MAX_MEMORY_HEAPS];\n    VMA_ATOMIC_UINT32 m_AllocationCount[VK_MAX_MEMORY_HEAPS];\n    VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];\n    VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS];\n\n#if VMA_MEMORY_BUDGET\n    VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch;\n    VMA_RW_MUTEX m_BudgetMutex;\n    uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS];\n    uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS];\n    uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS];\n#endif // VMA_MEMORY_BUDGET\n\n    VmaCurrentBudgetData();\n\n    void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize);\n    void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize);\n};\n\n#ifndef _VMA_CURRENT_BUDGET_DATA_FUNCTIONS\nVmaCurrentBudgetData::VmaCurrentBudgetData()\n{\n    for (uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex)\n    {\n        m_BlockCount[heapIndex] = 0;\n        m_AllocationCount[heapIndex] = 0;\n        m_BlockBytes[heapIndex] = 0;\n        m_AllocationBytes[heapIndex] = 0;\n#if VMA_MEMORY_BUDGET\n        m_VulkanUsage[heapIndex] = 0;\n        m_VulkanBudget[heapIndex] = 0;\n        m_BlockBytesAtBudgetFetch[heapIndex] = 0;\n#endif\n    }\n\n#if VMA_MEMORY_BUDGET\n    m_OperationsSinceBudgetFetch = 0;\n#endif\n}\n\nvoid VmaCurrentBudgetData::AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)\n{\n    m_AllocationBytes[heapIndex] += allocationSize;\n    ++m_AllocationCount[heapIndex];\n#if VMA_MEMORY_BUDGET\n    ++m_OperationsSinceBudgetFetch;\n#endif\n}\n\nvoid VmaCurrentBudgetData::RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)\n{\n    VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize);\n    m_AllocationBytes[heapIndex] -= allocationSize;\n    VMA_ASSERT(m_AllocationCount[heapIndex] > 0);\n    --m_AllocationCount[heapIndex];\n#if VMA_MEMORY_BUDGET\n    ++m_OperationsSinceBudgetFetch;\n#endif\n}\n#endif // _VMA_CURRENT_BUDGET_DATA_FUNCTIONS\n#endif // _VMA_CURRENT_BUDGET_DATA\n\n#ifndef _VMA_ALLOCATION_OBJECT_ALLOCATOR\n/*\nThread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects.\n*/\nclass VmaAllocationObjectAllocator\n{\n    VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)\npublic:\n    VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks)\n        : m_Allocator(pAllocationCallbacks, 1024) {}\n\n    template<typename... Types> VmaAllocation Allocate(Types&&... args);\n    void Free(VmaAllocation hAlloc);\n\nprivate:\n    VMA_MUTEX m_Mutex;\n    VmaPoolAllocator<VmaAllocation_T> m_Allocator;\n};\n\ntemplate<typename... Types>\nVmaAllocation VmaAllocationObjectAllocator::Allocate(Types&&... args)\n{\n    VmaMutexLock mutexLock(m_Mutex);\n    return m_Allocator.Alloc<Types...>(std::forward<Types>(args)...);\n}\n\nvoid VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc)\n{\n    VmaMutexLock mutexLock(m_Mutex);\n    m_Allocator.Free(hAlloc);\n}\n#endif // _VMA_ALLOCATION_OBJECT_ALLOCATOR\n\n#ifndef _VMA_VIRTUAL_BLOCK_T\nstruct VmaVirtualBlock_T\n{\n    VMA_CLASS_NO_COPY(VmaVirtualBlock_T)\npublic:\n    const bool m_AllocationCallbacksSpecified;\n    const VkAllocationCallbacks m_AllocationCallbacks;\n\n    VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo);\n    ~VmaVirtualBlock_T();\n\n    VkResult Init() { return VK_SUCCESS; }\n    bool IsEmpty() const { return m_Metadata->IsEmpty(); }\n    void Free(VmaVirtualAllocation allocation) { m_Metadata->Free((VmaAllocHandle)allocation); }\n    void SetAllocationUserData(VmaVirtualAllocation allocation, void* userData) { m_Metadata->SetAllocationUserData((VmaAllocHandle)allocation, userData); }\n    void Clear() { m_Metadata->Clear(); }\n\n    const VkAllocationCallbacks* GetAllocationCallbacks() const;\n    void GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo);\n    VkResult Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation,\n        VkDeviceSize* outOffset);\n    void GetStatistics(VmaStatistics& outStats) const;\n    void CalculateDetailedStatistics(VmaDetailedStatistics& outStats) const;\n#if VMA_STATS_STRING_ENABLED\n    void BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const;\n#endif\n\nprivate:\n    VmaBlockMetadata* m_Metadata;\n};\n\n#ifndef _VMA_VIRTUAL_BLOCK_T_FUNCTIONS\nVmaVirtualBlock_T::VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo)\n    : m_AllocationCallbacksSpecified(createInfo.pAllocationCallbacks != VMA_NULL),\n    m_AllocationCallbacks(createInfo.pAllocationCallbacks != VMA_NULL ? *createInfo.pAllocationCallbacks : VmaEmptyAllocationCallbacks)\n{\n    const uint32_t algorithm = createInfo.flags & VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK;\n    switch (algorithm)\n    {\n    default:\n        VMA_ASSERT(0);\n    case 0:\n        m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_TLSF)(VK_NULL_HANDLE, 1, true);\n        break;\n    case VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT:\n        m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Linear)(VK_NULL_HANDLE, 1, true);\n        break;\n    }\n\n    m_Metadata->Init(createInfo.size);\n}\n\nVmaVirtualBlock_T::~VmaVirtualBlock_T()\n{\n    // Define macro VMA_DEBUG_LOG to receive the list of the unfreed allocations\n    if (!m_Metadata->IsEmpty())\n        m_Metadata->DebugLogAllAllocations();\n    // This is the most important assert in the entire library.\n    // Hitting it means you have some memory leak - unreleased virtual allocations.\n    VMA_ASSERT(m_Metadata->IsEmpty() && \"Some virtual allocations were not freed before destruction of this virtual block!\");\n\n    vma_delete(GetAllocationCallbacks(), m_Metadata);\n}\n\nconst VkAllocationCallbacks* VmaVirtualBlock_T::GetAllocationCallbacks() const\n{\n    return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL;\n}\n\nvoid VmaVirtualBlock_T::GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo)\n{\n    m_Metadata->GetAllocationInfo((VmaAllocHandle)allocation, outInfo);\n}\n\nVkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation,\n    VkDeviceSize* outOffset)\n{\n    VmaAllocationRequest request = {};\n    if (m_Metadata->CreateAllocationRequest(\n        createInfo.size, // allocSize\n        VMA_MAX(createInfo.alignment, (VkDeviceSize)1), // allocAlignment\n        (createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0, // upperAddress\n        VMA_SUBALLOCATION_TYPE_UNKNOWN, // allocType - unimportant\n        createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK, // strategy\n        &request))\n    {\n        m_Metadata->Alloc(request,\n            VMA_SUBALLOCATION_TYPE_UNKNOWN, // type - unimportant\n            createInfo.pUserData);\n        outAllocation = (VmaVirtualAllocation)request.allocHandle;\n        if(outOffset)\n            *outOffset = m_Metadata->GetAllocationOffset(request.allocHandle);\n        return VK_SUCCESS;\n    }\n    outAllocation = (VmaVirtualAllocation)VK_NULL_HANDLE;\n    if (outOffset)\n        *outOffset = UINT64_MAX;\n    return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n}\n\nvoid VmaVirtualBlock_T::GetStatistics(VmaStatistics& outStats) const\n{\n    VmaClearStatistics(outStats);\n    m_Metadata->AddStatistics(outStats);\n}\n\nvoid VmaVirtualBlock_T::CalculateDetailedStatistics(VmaDetailedStatistics& outStats) const\n{\n    VmaClearDetailedStatistics(outStats);\n    m_Metadata->AddDetailedStatistics(outStats);\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaVirtualBlock_T::BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const\n{\n    VmaJsonWriter json(GetAllocationCallbacks(), sb);\n    json.BeginObject();\n\n    VmaDetailedStatistics stats;\n    CalculateDetailedStatistics(stats);\n\n    json.WriteString(\"Stats\");\n    VmaPrintDetailedStatistics(json, stats);\n\n    if (detailedMap)\n    {\n        json.WriteString(\"Details\");\n        json.BeginObject();\n        m_Metadata->PrintDetailedMap(json);\n        json.EndObject();\n    }\n\n    json.EndObject();\n}\n#endif // VMA_STATS_STRING_ENABLED\n#endif // _VMA_VIRTUAL_BLOCK_T_FUNCTIONS\n#endif // _VMA_VIRTUAL_BLOCK_T\n\n\n// Main allocator object.\nstruct VmaAllocator_T\n{\n    VMA_CLASS_NO_COPY(VmaAllocator_T)\npublic:\n    bool m_UseMutex;\n    uint32_t m_VulkanApiVersion;\n    bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).\n    bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).\n    bool m_UseExtMemoryBudget;\n    bool m_UseAmdDeviceCoherentMemory;\n    bool m_UseKhrBufferDeviceAddress;\n    bool m_UseExtMemoryPriority;\n    VkDevice m_hDevice;\n    VkInstance m_hInstance;\n    bool m_AllocationCallbacksSpecified;\n    VkAllocationCallbacks m_AllocationCallbacks;\n    VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks;\n    VmaAllocationObjectAllocator m_AllocationObjectAllocator;\n\n    // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size.\n    uint32_t m_HeapSizeLimitMask;\n\n    VkPhysicalDeviceProperties m_PhysicalDeviceProperties;\n    VkPhysicalDeviceMemoryProperties m_MemProps;\n\n    // Default pools.\n    VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];\n    VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES];\n\n    VmaCurrentBudgetData m_Budget;\n    VMA_ATOMIC_UINT32 m_DeviceMemoryCount; // Total number of VkDeviceMemory objects.\n\n    VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);\n    VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo);\n    ~VmaAllocator_T();\n\n    const VkAllocationCallbacks* GetAllocationCallbacks() const\n    {\n        return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL;\n    }\n    const VmaVulkanFunctions& GetVulkanFunctions() const\n    {\n        return m_VulkanFunctions;\n    }\n\n    VkPhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; }\n\n    VkDeviceSize GetBufferImageGranularity() const\n    {\n        return VMA_MAX(\n            static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),\n            m_PhysicalDeviceProperties.limits.bufferImageGranularity);\n    }\n\n    uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; }\n    uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; }\n\n    uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const\n    {\n        VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);\n        return m_MemProps.memoryTypes[memTypeIndex].heapIndex;\n    }\n    // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.\n    bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const\n    {\n        return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==\n            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;\n    }\n    // Minimum alignment for all allocations in specific memory type.\n    VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const\n    {\n        return IsMemoryTypeNonCoherent(memTypeIndex) ?\n            VMA_MAX((VkDeviceSize)VMA_MIN_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :\n            (VkDeviceSize)VMA_MIN_ALIGNMENT;\n    }\n\n    bool IsIntegratedGpu() const\n    {\n        return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;\n    }\n\n    uint32_t GetGlobalMemoryTypeBits() const { return m_GlobalMemoryTypeBits; }\n\n    void GetBufferMemoryRequirements(\n        VkBuffer hBuffer,\n        VkMemoryRequirements& memReq,\n        bool& requiresDedicatedAllocation,\n        bool& prefersDedicatedAllocation) const;\n    void GetImageMemoryRequirements(\n        VkImage hImage,\n        VkMemoryRequirements& memReq,\n        bool& requiresDedicatedAllocation,\n        bool& prefersDedicatedAllocation) const;\n    VkResult FindMemoryTypeIndex(\n        uint32_t memoryTypeBits,\n        const VmaAllocationCreateInfo* pAllocationCreateInfo,\n        VkFlags bufImgUsage, // VkBufferCreateInfo::usage or VkImageCreateInfo::usage. UINT32_MAX if unknown.\n        uint32_t* pMemoryTypeIndex) const;\n\n    // Main allocation function.\n    VkResult AllocateMemory(\n        const VkMemoryRequirements& vkMemReq,\n        bool requiresDedicatedAllocation,\n        bool prefersDedicatedAllocation,\n        VkBuffer dedicatedBuffer,\n        VkImage dedicatedImage,\n        VkFlags dedicatedBufferImageUsage, // UINT32_MAX if unknown.\n        const VmaAllocationCreateInfo& createInfo,\n        VmaSuballocationType suballocType,\n        size_t allocationCount,\n        VmaAllocation* pAllocations);\n\n    // Main deallocation function.\n    void FreeMemory(\n        size_t allocationCount,\n        const VmaAllocation* pAllocations);\n\n    void CalculateStatistics(VmaTotalStatistics* pStats);\n\n    void GetHeapBudgets(\n        VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount);\n\n#if VMA_STATS_STRING_ENABLED\n    void PrintDetailedMap(class VmaJsonWriter& json);\n#endif\n\n    void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo);\n\n    VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool);\n    void DestroyPool(VmaPool pool);\n    void GetPoolStatistics(VmaPool pool, VmaStatistics* pPoolStats);\n    void CalculatePoolStatistics(VmaPool pool, VmaDetailedStatistics* pPoolStats);\n\n    void SetCurrentFrameIndex(uint32_t frameIndex);\n    uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }\n\n    VkResult CheckPoolCorruption(VmaPool hPool);\n    VkResult CheckCorruption(uint32_t memoryTypeBits);\n\n    // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping.\n    VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);\n    // Call to Vulkan function vkFreeMemory with accompanying bookkeeping.\n    void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);\n    // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR.\n    VkResult BindVulkanBuffer(\n        VkDeviceMemory memory,\n        VkDeviceSize memoryOffset,\n        VkBuffer buffer,\n        const void* pNext);\n    // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR.\n    VkResult BindVulkanImage(\n        VkDeviceMemory memory,\n        VkDeviceSize memoryOffset,\n        VkImage image,\n        const void* pNext);\n\n    VkResult Map(VmaAllocation hAllocation, void** ppData);\n    void Unmap(VmaAllocation hAllocation);\n\n    VkResult BindBufferMemory(\n        VmaAllocation hAllocation,\n        VkDeviceSize allocationLocalOffset,\n        VkBuffer hBuffer,\n        const void* pNext);\n    VkResult BindImageMemory(\n        VmaAllocation hAllocation,\n        VkDeviceSize allocationLocalOffset,\n        VkImage hImage,\n        const void* pNext);\n\n    VkResult FlushOrInvalidateAllocation(\n        VmaAllocation hAllocation,\n        VkDeviceSize offset, VkDeviceSize size,\n        VMA_CACHE_OPERATION op);\n    VkResult FlushOrInvalidateAllocations(\n        uint32_t allocationCount,\n        const VmaAllocation* allocations,\n        const VkDeviceSize* offsets, const VkDeviceSize* sizes,\n        VMA_CACHE_OPERATION op);\n\n    void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);\n\n    /*\n    Returns bit mask of memory types that can support defragmentation on GPU as\n    they support creation of required buffer for copy operations.\n    */\n    uint32_t GetGpuDefragmentationMemoryTypeBits();\n\n#if VMA_EXTERNAL_MEMORY\n    VkExternalMemoryHandleTypeFlagsKHR GetExternalMemoryHandleTypeFlags(uint32_t memTypeIndex) const\n    {\n        return m_TypeExternalMemoryHandleTypes[memTypeIndex];\n    }\n#endif // #if VMA_EXTERNAL_MEMORY\n\nprivate:\n    VkDeviceSize m_PreferredLargeHeapBlockSize;\n\n    VkPhysicalDevice m_PhysicalDevice;\n    VMA_ATOMIC_UINT32 m_CurrentFrameIndex;\n    VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.\n#if VMA_EXTERNAL_MEMORY\n    VkExternalMemoryHandleTypeFlagsKHR m_TypeExternalMemoryHandleTypes[VK_MAX_MEMORY_TYPES];\n#endif // #if VMA_EXTERNAL_MEMORY\n\n    VMA_RW_MUTEX m_PoolsMutex;\n    typedef VmaIntrusiveLinkedList<VmaPoolListItemTraits> PoolList;\n    // Protected by m_PoolsMutex.\n    PoolList m_Pools;\n    uint32_t m_NextPoolId;\n\n    VmaVulkanFunctions m_VulkanFunctions;\n\n    // Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types.\n    uint32_t m_GlobalMemoryTypeBits;\n\n    void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions);\n\n#if VMA_STATIC_VULKAN_FUNCTIONS == 1\n    void ImportVulkanFunctions_Static();\n#endif\n\n    void ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions);\n\n#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1\n    void ImportVulkanFunctions_Dynamic();\n#endif\n\n    void ValidateVulkanFunctions();\n\n    VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);\n\n    VkResult AllocateMemoryOfType(\n        VmaPool pool,\n        VkDeviceSize size,\n        VkDeviceSize alignment,\n        bool dedicatedPreferred,\n        VkBuffer dedicatedBuffer,\n        VkImage dedicatedImage,\n        VkFlags dedicatedBufferImageUsage,\n        const VmaAllocationCreateInfo& createInfo,\n        uint32_t memTypeIndex,\n        VmaSuballocationType suballocType,\n        VmaDedicatedAllocationList& dedicatedAllocations,\n        VmaBlockVector& blockVector,\n        size_t allocationCount,\n        VmaAllocation* pAllocations);\n\n    // Helper function only to be used inside AllocateDedicatedMemory.\n    VkResult AllocateDedicatedMemoryPage(\n        VmaPool pool,\n        VkDeviceSize size,\n        VmaSuballocationType suballocType,\n        uint32_t memTypeIndex,\n        const VkMemoryAllocateInfo& allocInfo,\n        bool map,\n        bool isUserDataString,\n        bool isMappingAllowed,\n        void* pUserData,\n        VmaAllocation* pAllocation);\n\n    // Allocates and registers new VkDeviceMemory specifically for dedicated allocations.\n    VkResult AllocateDedicatedMemory(\n        VmaPool pool,\n        VkDeviceSize size,\n        VmaSuballocationType suballocType,\n        VmaDedicatedAllocationList& dedicatedAllocations,\n        uint32_t memTypeIndex,\n        bool map,\n        bool isUserDataString,\n        bool isMappingAllowed,\n        bool canAliasMemory,\n        void* pUserData,\n        float priority,\n        VkBuffer dedicatedBuffer,\n        VkImage dedicatedImage,\n        VkFlags dedicatedBufferImageUsage,\n        size_t allocationCount,\n        VmaAllocation* pAllocations,\n        const void* pNextChain = nullptr);\n\n    void FreeDedicatedMemory(const VmaAllocation allocation);\n\n    VkResult CalcMemTypeParams(\n        VmaAllocationCreateInfo& outCreateInfo,\n        uint32_t memTypeIndex,\n        VkDeviceSize size,\n        size_t allocationCount);\n    VkResult CalcAllocationParams(\n        VmaAllocationCreateInfo& outCreateInfo,\n        bool dedicatedRequired,\n        bool dedicatedPreferred);\n\n    /*\n    Calculates and returns bit mask of memory types that can support defragmentation\n    on GPU as they support creation of required buffer for copy operations.\n    */\n    uint32_t CalculateGpuDefragmentationMemoryTypeBits() const;\n    uint32_t CalculateGlobalMemoryTypeBits() const;\n\n    bool GetFlushOrInvalidateRange(\n        VmaAllocation allocation,\n        VkDeviceSize offset, VkDeviceSize size,\n        VkMappedMemoryRange& outRange) const;\n\n#if VMA_MEMORY_BUDGET\n    void UpdateVulkanBudget();\n#endif // #if VMA_MEMORY_BUDGET\n};\n\n\n#ifndef _VMA_MEMORY_FUNCTIONS\nstatic void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment)\n{\n    return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment);\n}\n\nstatic void VmaFree(VmaAllocator hAllocator, void* ptr)\n{\n    VmaFree(&hAllocator->m_AllocationCallbacks, ptr);\n}\n\ntemplate<typename T>\nstatic T* VmaAllocate(VmaAllocator hAllocator)\n{\n    return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T));\n}\n\ntemplate<typename T>\nstatic T* VmaAllocateArray(VmaAllocator hAllocator, size_t count)\n{\n    return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T));\n}\n\ntemplate<typename T>\nstatic void vma_delete(VmaAllocator hAllocator, T* ptr)\n{\n    if(ptr != VMA_NULL)\n    {\n        ptr->~T();\n        VmaFree(hAllocator, ptr);\n    }\n}\n\ntemplate<typename T>\nstatic void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count)\n{\n    if(ptr != VMA_NULL)\n    {\n        for(size_t i = count; i--; )\n            ptr[i].~T();\n        VmaFree(hAllocator, ptr);\n    }\n}\n#endif // _VMA_MEMORY_FUNCTIONS\n\n#ifndef _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS\nVmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator)\n    : m_pMetadata(VMA_NULL),\n    m_MemoryTypeIndex(UINT32_MAX),\n    m_Id(0),\n    m_hMemory(VK_NULL_HANDLE),\n    m_MapCount(0),\n    m_pMappedData(VMA_NULL) {}\n\nVmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()\n{\n    VMA_ASSERT(m_MapCount == 0 && \"VkDeviceMemory block is being destroyed while it is still mapped.\");\n    VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);\n}\n\nvoid VmaDeviceMemoryBlock::Init(\n    VmaAllocator hAllocator,\n    VmaPool hParentPool,\n    uint32_t newMemoryTypeIndex,\n    VkDeviceMemory newMemory,\n    VkDeviceSize newSize,\n    uint32_t id,\n    uint32_t algorithm,\n    VkDeviceSize bufferImageGranularity)\n{\n    VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);\n\n    m_hParentPool = hParentPool;\n    m_MemoryTypeIndex = newMemoryTypeIndex;\n    m_Id = id;\n    m_hMemory = newMemory;\n\n    switch (algorithm)\n    {\n    case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:\n        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator->GetAllocationCallbacks(),\n            bufferImageGranularity, false); // isVirtual\n        break;\n    default:\n        VMA_ASSERT(0);\n        // Fall-through.\n    case 0:\n        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_TLSF)(hAllocator->GetAllocationCallbacks(),\n            bufferImageGranularity, false); // isVirtual\n    }\n    m_pMetadata->Init(newSize);\n}\n\nvoid VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)\n{\n    // Define macro VMA_DEBUG_LOG to receive the list of the unfreed allocations\n    if (!m_pMetadata->IsEmpty())\n        m_pMetadata->DebugLogAllAllocations();\n    // This is the most important assert in the entire library.\n    // Hitting it means you have some memory leak - unreleased VmaAllocation objects.\n    VMA_ASSERT(m_pMetadata->IsEmpty() && \"Some allocations were not freed before destruction of this memory block!\");\n\n    VMA_ASSERT(m_hMemory != VK_NULL_HANDLE);\n    allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);\n    m_hMemory = VK_NULL_HANDLE;\n\n    vma_delete(allocator, m_pMetadata);\n    m_pMetadata = VMA_NULL;\n}\n\nvoid VmaDeviceMemoryBlock::PostAlloc(VmaAllocator hAllocator)\n{\n    VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);\n    m_MappingHysteresis.PostAlloc();\n}\n\nvoid VmaDeviceMemoryBlock::PostFree(VmaAllocator hAllocator)\n{\n    VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);\n    if(m_MappingHysteresis.PostFree())\n    {\n        VMA_ASSERT(m_MappingHysteresis.GetExtraMapping() == 0);\n        if (m_MapCount == 0)\n        {\n            m_pMappedData = VMA_NULL;\n            (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);\n        }\n    }\n}\n\nbool VmaDeviceMemoryBlock::Validate() const\n{\n    VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) &&\n        (m_pMetadata->GetSize() != 0));\n\n    return m_pMetadata->Validate();\n}\n\nVkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)\n{\n    void* pData = nullptr;\n    VkResult res = Map(hAllocator, 1, &pData);\n    if (res != VK_SUCCESS)\n    {\n        return res;\n    }\n\n    res = m_pMetadata->CheckCorruption(pData);\n\n    Unmap(hAllocator, 1);\n\n    return res;\n}\n\nVkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData)\n{\n    if (count == 0)\n    {\n        return VK_SUCCESS;\n    }\n\n    VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);\n    const uint32_t oldTotalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping();\n    m_MappingHysteresis.PostMap();\n    if (oldTotalMapCount != 0)\n    {\n        m_MapCount += count;\n        VMA_ASSERT(m_pMappedData != VMA_NULL);\n        if (ppData != VMA_NULL)\n        {\n            *ppData = m_pMappedData;\n        }\n        return VK_SUCCESS;\n    }\n    else\n    {\n        VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(\n            hAllocator->m_hDevice,\n            m_hMemory,\n            0, // offset\n            VK_WHOLE_SIZE,\n            0, // flags\n            &m_pMappedData);\n        if (result == VK_SUCCESS)\n        {\n            if (ppData != VMA_NULL)\n            {\n                *ppData = m_pMappedData;\n            }\n            m_MapCount = count;\n        }\n        return result;\n    }\n}\n\nvoid VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)\n{\n    if (count == 0)\n    {\n        return;\n    }\n\n    VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);\n    if (m_MapCount >= count)\n    {\n        m_MapCount -= count;\n        const uint32_t totalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping();\n        if (totalMapCount == 0)\n        {\n            m_pMappedData = VMA_NULL;\n            (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);\n        }\n        m_MappingHysteresis.PostUnmap();\n    }\n    else\n    {\n        VMA_ASSERT(0 && \"VkDeviceMemory block is being unmapped while it was not previously mapped.\");\n    }\n}\n\nVkResult VmaDeviceMemoryBlock::WriteMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)\n{\n    VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);\n\n    void* pData;\n    VkResult res = Map(hAllocator, 1, &pData);\n    if (res != VK_SUCCESS)\n    {\n        return res;\n    }\n\n    VmaWriteMagicValue(pData, allocOffset + allocSize);\n\n    Unmap(hAllocator, 1);\n    return VK_SUCCESS;\n}\n\nVkResult VmaDeviceMemoryBlock::ValidateMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)\n{\n    VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);\n\n    void* pData;\n    VkResult res = Map(hAllocator, 1, &pData);\n    if (res != VK_SUCCESS)\n    {\n        return res;\n    }\n\n    if (!VmaValidateMagicValue(pData, allocOffset + allocSize))\n    {\n        VMA_ASSERT(0 && \"MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!\");\n    }\n\n    Unmap(hAllocator, 1);\n    return VK_SUCCESS;\n}\n\nVkResult VmaDeviceMemoryBlock::BindBufferMemory(\n    const VmaAllocator hAllocator,\n    const VmaAllocation hAllocation,\n    VkDeviceSize allocationLocalOffset,\n    VkBuffer hBuffer,\n    const void* pNext)\n{\n    VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&\n        hAllocation->GetBlock() == this);\n    VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&\n        \"Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?\");\n    const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;\n    // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.\n    VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);\n    return hAllocator->BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext);\n}\n\nVkResult VmaDeviceMemoryBlock::BindImageMemory(\n    const VmaAllocator hAllocator,\n    const VmaAllocation hAllocation,\n    VkDeviceSize allocationLocalOffset,\n    VkImage hImage,\n    const void* pNext)\n{\n    VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&\n        hAllocation->GetBlock() == this);\n    VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&\n        \"Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?\");\n    const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;\n    // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.\n    VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);\n    return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);\n}\n#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS\n\n#ifndef _VMA_ALLOCATION_T_FUNCTIONS\nVmaAllocation_T::VmaAllocation_T(bool mappingAllowed)\n    : m_Alignment{ 1 },\n    m_Size{ 0 },\n    m_pUserData{ VMA_NULL },\n    m_pName{ VMA_NULL },\n    m_MemoryTypeIndex{ 0 },\n    m_Type{ (uint8_t)ALLOCATION_TYPE_NONE },\n    m_SuballocationType{ (uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN },\n    m_MapCount{ 0 },\n    m_Flags{ 0 }\n{\n    if(mappingAllowed)\n        m_Flags |= (uint8_t)FLAG_MAPPING_ALLOWED;\n\n#if VMA_STATS_STRING_ENABLED\n    m_BufferImageUsage = 0;\n#endif\n}\n\nVmaAllocation_T::~VmaAllocation_T()\n{\n    VMA_ASSERT(m_MapCount == 0 && \"Allocation was not unmapped before destruction.\");\n\n    // Check if owned string was freed.\n    VMA_ASSERT(m_pName == VMA_NULL);\n}\n\nvoid VmaAllocation_T::InitBlockAllocation(\n    VmaDeviceMemoryBlock* block,\n    VmaAllocHandle allocHandle,\n    VkDeviceSize alignment,\n    VkDeviceSize size,\n    uint32_t memoryTypeIndex,\n    VmaSuballocationType suballocationType,\n    bool mapped)\n{\n    VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);\n    VMA_ASSERT(block != VMA_NULL);\n    m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;\n    m_Alignment = alignment;\n    m_Size = size;\n    m_MemoryTypeIndex = memoryTypeIndex;\n    if(mapped)\n    {\n        VMA_ASSERT(IsMappingAllowed() && \"Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.\");\n        m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;\n    }\n    m_SuballocationType = (uint8_t)suballocationType;\n    m_BlockAllocation.m_Block = block;\n    m_BlockAllocation.m_AllocHandle = allocHandle;\n}\n\nvoid VmaAllocation_T::InitDedicatedAllocation(\n    VmaPool hParentPool,\n    uint32_t memoryTypeIndex,\n    VkDeviceMemory hMemory,\n    VmaSuballocationType suballocationType,\n    void* pMappedData,\n    VkDeviceSize size)\n{\n    VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);\n    VMA_ASSERT(hMemory != VK_NULL_HANDLE);\n    m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;\n    m_Alignment = 0;\n    m_Size = size;\n    m_MemoryTypeIndex = memoryTypeIndex;\n    m_SuballocationType = (uint8_t)suballocationType;\n    if(pMappedData != VMA_NULL)\n    {\n        VMA_ASSERT(IsMappingAllowed() && \"Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.\");\n        m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;\n    }\n    m_DedicatedAllocation.m_hParentPool = hParentPool;\n    m_DedicatedAllocation.m_hMemory = hMemory;\n    m_DedicatedAllocation.m_pMappedData = pMappedData;\n    m_DedicatedAllocation.m_Prev = VMA_NULL;\n    m_DedicatedAllocation.m_Next = VMA_NULL;\n}\n\nvoid VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)\n{\n    VMA_ASSERT(pName == VMA_NULL || pName != m_pName);\n\n    FreeName(hAllocator);\n\n    if (pName != VMA_NULL)\n        m_pName = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), pName);\n}\n\nuint8_t VmaAllocation_T::SwapBlockAllocation(VmaAllocator hAllocator, VmaAllocation allocation)\n{\n    VMA_ASSERT(allocation != VMA_NULL);\n    VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);\n    VMA_ASSERT(allocation->m_Type == ALLOCATION_TYPE_BLOCK);\n\n    if (m_MapCount != 0)\n        m_BlockAllocation.m_Block->Unmap(hAllocator, m_MapCount);\n\n    m_BlockAllocation.m_Block->m_pMetadata->SetAllocationUserData(m_BlockAllocation.m_AllocHandle, allocation);\n    VMA_SWAP(m_BlockAllocation, allocation->m_BlockAllocation);\n    m_BlockAllocation.m_Block->m_pMetadata->SetAllocationUserData(m_BlockAllocation.m_AllocHandle, this);\n\n#if VMA_STATS_STRING_ENABLED\n    VMA_SWAP(m_BufferImageUsage, allocation->m_BufferImageUsage);\n#endif\n    return m_MapCount;\n}\n\nVmaAllocHandle VmaAllocation_T::GetAllocHandle() const\n{\n    switch (m_Type)\n    {\n    case ALLOCATION_TYPE_BLOCK:\n        return m_BlockAllocation.m_AllocHandle;\n    case ALLOCATION_TYPE_DEDICATED:\n        return VK_NULL_HANDLE;\n    default:\n        VMA_ASSERT(0);\n        return VK_NULL_HANDLE;\n    }\n}\n\nVkDeviceSize VmaAllocation_T::GetOffset() const\n{\n    switch (m_Type)\n    {\n    case ALLOCATION_TYPE_BLOCK:\n        return m_BlockAllocation.m_Block->m_pMetadata->GetAllocationOffset(m_BlockAllocation.m_AllocHandle);\n    case ALLOCATION_TYPE_DEDICATED:\n        return 0;\n    default:\n        VMA_ASSERT(0);\n        return 0;\n    }\n}\n\nVmaPool VmaAllocation_T::GetParentPool() const\n{\n    switch (m_Type)\n    {\n    case ALLOCATION_TYPE_BLOCK:\n        return m_BlockAllocation.m_Block->GetParentPool();\n    case ALLOCATION_TYPE_DEDICATED:\n        return m_DedicatedAllocation.m_hParentPool;\n    default:\n        VMA_ASSERT(0);\n        return VK_NULL_HANDLE;\n    }\n}\n\nVkDeviceMemory VmaAllocation_T::GetMemory() const\n{\n    switch (m_Type)\n    {\n    case ALLOCATION_TYPE_BLOCK:\n        return m_BlockAllocation.m_Block->GetDeviceMemory();\n    case ALLOCATION_TYPE_DEDICATED:\n        return m_DedicatedAllocation.m_hMemory;\n    default:\n        VMA_ASSERT(0);\n        return VK_NULL_HANDLE;\n    }\n}\n\nvoid* VmaAllocation_T::GetMappedData() const\n{\n    switch (m_Type)\n    {\n    case ALLOCATION_TYPE_BLOCK:\n        if (m_MapCount != 0 || IsPersistentMap())\n        {\n            void* pBlockData = m_BlockAllocation.m_Block->GetMappedData();\n            VMA_ASSERT(pBlockData != VMA_NULL);\n            return (char*)pBlockData + GetOffset();\n        }\n        else\n        {\n            return VMA_NULL;\n        }\n        break;\n    case ALLOCATION_TYPE_DEDICATED:\n        VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0 || IsPersistentMap()));\n        return m_DedicatedAllocation.m_pMappedData;\n    default:\n        VMA_ASSERT(0);\n        return VMA_NULL;\n    }\n}\n\nvoid VmaAllocation_T::BlockAllocMap()\n{\n    VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);\n    VMA_ASSERT(IsMappingAllowed() && \"Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.\");\n\n    if (m_MapCount < 0xFF)\n    {\n        ++m_MapCount;\n    }\n    else\n    {\n        VMA_ASSERT(0 && \"Allocation mapped too many times simultaneously.\");\n    }\n}\n\nvoid VmaAllocation_T::BlockAllocUnmap()\n{\n    VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);\n\n    if (m_MapCount > 0)\n    {\n        --m_MapCount;\n    }\n    else\n    {\n        VMA_ASSERT(0 && \"Unmapping allocation not previously mapped.\");\n    }\n}\n\nVkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData)\n{\n    VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);\n    VMA_ASSERT(IsMappingAllowed() && \"Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.\");\n\n    if (m_MapCount != 0 || IsPersistentMap())\n    {\n        if (m_MapCount < 0xFF)\n        {\n            VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);\n            *ppData = m_DedicatedAllocation.m_pMappedData;\n            ++m_MapCount;\n            return VK_SUCCESS;\n        }\n        else\n        {\n            VMA_ASSERT(0 && \"Dedicated allocation mapped too many times simultaneously.\");\n            return VK_ERROR_MEMORY_MAP_FAILED;\n        }\n    }\n    else\n    {\n        VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(\n            hAllocator->m_hDevice,\n            m_DedicatedAllocation.m_hMemory,\n            0, // offset\n            VK_WHOLE_SIZE,\n            0, // flags\n            ppData);\n        if (result == VK_SUCCESS)\n        {\n            m_DedicatedAllocation.m_pMappedData = *ppData;\n            m_MapCount = 1;\n        }\n        return result;\n    }\n}\n\nvoid VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)\n{\n    VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);\n\n    if (m_MapCount > 0)\n    {\n        --m_MapCount;\n        if (m_MapCount == 0 && !IsPersistentMap())\n        {\n            m_DedicatedAllocation.m_pMappedData = VMA_NULL;\n            (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(\n                hAllocator->m_hDevice,\n                m_DedicatedAllocation.m_hMemory);\n        }\n    }\n    else\n    {\n        VMA_ASSERT(0 && \"Unmapping dedicated allocation not previously mapped.\");\n    }\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaAllocation_T::InitBufferImageUsage(uint32_t bufferImageUsage)\n{\n    VMA_ASSERT(m_BufferImageUsage == 0);\n    m_BufferImageUsage = bufferImageUsage;\n}\n\nvoid VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const\n{\n    json.WriteString(\"Type\");\n    json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);\n\n    json.WriteString(\"Size\");\n    json.WriteNumber(m_Size);\n    json.WriteString(\"Usage\");\n    json.WriteNumber(m_BufferImageUsage);\n\n    if (m_pUserData != VMA_NULL)\n    {\n        json.WriteString(\"CustomData\");\n        json.BeginString();\n        json.ContinueString_Pointer(m_pUserData);\n        json.EndString();\n    }\n    if (m_pName != VMA_NULL)\n    {\n        json.WriteString(\"Name\");\n        json.WriteString(m_pName);\n    }\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nvoid VmaAllocation_T::FreeName(VmaAllocator hAllocator)\n{\n    if(m_pName)\n    {\n        VmaFreeString(hAllocator->GetAllocationCallbacks(), m_pName);\n        m_pName = VMA_NULL;\n    }\n}\n#endif // _VMA_ALLOCATION_T_FUNCTIONS\n\n#ifndef _VMA_BLOCK_VECTOR_FUNCTIONS\nVmaBlockVector::VmaBlockVector(\n    VmaAllocator hAllocator,\n    VmaPool hParentPool,\n    uint32_t memoryTypeIndex,\n    VkDeviceSize preferredBlockSize,\n    size_t minBlockCount,\n    size_t maxBlockCount,\n    VkDeviceSize bufferImageGranularity,\n    bool explicitBlockSize,\n    uint32_t algorithm,\n    float priority,\n    VkDeviceSize minAllocationAlignment,\n    void* pMemoryAllocateNext)\n    : m_hAllocator(hAllocator),\n    m_hParentPool(hParentPool),\n    m_MemoryTypeIndex(memoryTypeIndex),\n    m_PreferredBlockSize(preferredBlockSize),\n    m_MinBlockCount(minBlockCount),\n    m_MaxBlockCount(maxBlockCount),\n    m_BufferImageGranularity(bufferImageGranularity),\n    m_ExplicitBlockSize(explicitBlockSize),\n    m_Algorithm(algorithm),\n    m_Priority(priority),\n    m_MinAllocationAlignment(minAllocationAlignment),\n    m_pMemoryAllocateNext(pMemoryAllocateNext),\n    m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),\n    m_NextBlockId(0) {}\n\nVmaBlockVector::~VmaBlockVector()\n{\n    for (size_t i = m_Blocks.size(); i--; )\n    {\n        m_Blocks[i]->Destroy(m_hAllocator);\n        vma_delete(m_hAllocator, m_Blocks[i]);\n    }\n}\n\nVkResult VmaBlockVector::CreateMinBlocks()\n{\n    for (size_t i = 0; i < m_MinBlockCount; ++i)\n    {\n        VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL);\n        if (res != VK_SUCCESS)\n        {\n            return res;\n        }\n    }\n    return VK_SUCCESS;\n}\n\nvoid VmaBlockVector::AddStatistics(VmaStatistics& inoutStats)\n{\n    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);\n\n    const size_t blockCount = m_Blocks.size();\n    for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)\n    {\n        const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];\n        VMA_ASSERT(pBlock);\n        VMA_HEAVY_ASSERT(pBlock->Validate());\n        pBlock->m_pMetadata->AddStatistics(inoutStats);\n    }\n}\n\nvoid VmaBlockVector::AddDetailedStatistics(VmaDetailedStatistics& inoutStats)\n{\n    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);\n\n    const size_t blockCount = m_Blocks.size();\n    for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)\n    {\n        const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];\n        VMA_ASSERT(pBlock);\n        VMA_HEAVY_ASSERT(pBlock->Validate());\n        pBlock->m_pMetadata->AddDetailedStatistics(inoutStats);\n    }\n}\n\nbool VmaBlockVector::IsEmpty()\n{\n    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);\n    return m_Blocks.empty();\n}\n\nbool VmaBlockVector::IsCorruptionDetectionEnabled() const\n{\n    const uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;\n    return (VMA_DEBUG_DETECT_CORRUPTION != 0) &&\n        (VMA_DEBUG_MARGIN > 0) &&\n        (m_Algorithm == 0 || m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) &&\n        (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags;\n}\n\nVkResult VmaBlockVector::Allocate(\n    VkDeviceSize size,\n    VkDeviceSize alignment,\n    const VmaAllocationCreateInfo& createInfo,\n    VmaSuballocationType suballocType,\n    size_t allocationCount,\n    VmaAllocation* pAllocations)\n{\n    size_t allocIndex;\n    VkResult res = VK_SUCCESS;\n\n    alignment = VMA_MAX(alignment, m_MinAllocationAlignment);\n\n    if (IsCorruptionDetectionEnabled())\n    {\n        size = VmaAlignUp<VkDeviceSize>(size, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));\n        alignment = VmaAlignUp<VkDeviceSize>(alignment, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));\n    }\n\n    {\n        VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);\n        for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex)\n        {\n            res = AllocatePage(\n                size,\n                alignment,\n                createInfo,\n                suballocType,\n                pAllocations + allocIndex);\n            if (res != VK_SUCCESS)\n            {\n                break;\n            }\n        }\n    }\n\n    if (res != VK_SUCCESS)\n    {\n        // Free all already created allocations.\n        while (allocIndex--)\n            Free(pAllocations[allocIndex]);\n        memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);\n    }\n\n    return res;\n}\n\nVkResult VmaBlockVector::AllocatePage(\n    VkDeviceSize size,\n    VkDeviceSize alignment,\n    const VmaAllocationCreateInfo& createInfo,\n    VmaSuballocationType suballocType,\n    VmaAllocation* pAllocation)\n{\n    const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;\n\n    VkDeviceSize freeMemory;\n    {\n        const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);\n        VmaBudget heapBudget = {};\n        m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1);\n        freeMemory = (heapBudget.usage < heapBudget.budget) ? (heapBudget.budget - heapBudget.usage) : 0;\n    }\n\n    const bool canFallbackToDedicated = !HasExplicitBlockSize() &&\n        (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0;\n    const bool canCreateNewBlock =\n        ((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) &&\n        (m_Blocks.size() < m_MaxBlockCount) &&\n        (freeMemory >= size || !canFallbackToDedicated);\n    uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK;\n\n    // Upper address can only be used with linear allocator and within single memory block.\n    if (isUpperAddress &&\n        (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1))\n    {\n        return VK_ERROR_FEATURE_NOT_PRESENT;\n    }\n\n    // Early reject: requested allocation size is larger that maximum block size for this block vector.\n    if (size + VMA_DEBUG_MARGIN > m_PreferredBlockSize)\n    {\n        return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n    }\n\n    // 1. Search existing allocations. Try to allocate.\n    if (m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)\n    {\n        // Use only last block.\n        if (!m_Blocks.empty())\n        {\n            VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back();\n            VMA_ASSERT(pCurrBlock);\n            VkResult res = AllocateFromBlock(\n                pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);\n            if (res == VK_SUCCESS)\n            {\n                VMA_DEBUG_LOG(\"    Returned from last block #%u\", pCurrBlock->GetId());\n                IncrementallySortBlocks();\n                return VK_SUCCESS;\n            }\n        }\n    }\n    else\n    {\n        if (strategy != VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT) // MIN_MEMORY or default\n        {\n            const bool isHostVisible =\n                (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;\n            if(isHostVisible)\n            {\n                const bool isMappingAllowed = (createInfo.flags &\n                    (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0;\n                /*\n                For non-mappable allocations, check blocks that are not mapped first.\n                For mappable allocations, check blocks that are already mapped first.\n                This way, having many blocks, we will separate mappable and non-mappable allocations,\n                hopefully limiting the number of blocks that are mapped, which will help tools like RenderDoc.\n                */\n                for(size_t mappingI = 0; mappingI < 2; ++mappingI)\n                {\n                    // Forward order in m_Blocks - prefer blocks with smallest amount of free space.\n                    for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)\n                    {\n                        VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];\n                        VMA_ASSERT(pCurrBlock);\n                        const bool isBlockMapped = pCurrBlock->GetMappedData() != VMA_NULL;\n                        if((mappingI == 0) == (isMappingAllowed == isBlockMapped))\n                        {\n                            VkResult res = AllocateFromBlock(\n                                pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);\n                            if (res == VK_SUCCESS)\n                            {\n                                VMA_DEBUG_LOG(\"    Returned from existing block #%u\", pCurrBlock->GetId());\n                                IncrementallySortBlocks();\n                                return VK_SUCCESS;\n                            }\n                        }\n                    }\n                }\n            }\n            else\n            {\n                // Forward order in m_Blocks - prefer blocks with smallest amount of free space.\n                for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)\n                {\n                    VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];\n                    VMA_ASSERT(pCurrBlock);\n                    VkResult res = AllocateFromBlock(\n                        pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);\n                    if (res == VK_SUCCESS)\n                    {\n                        VMA_DEBUG_LOG(\"    Returned from existing block #%u\", pCurrBlock->GetId());\n                        IncrementallySortBlocks();\n                        return VK_SUCCESS;\n                    }\n                }\n            }\n        }\n        else // VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT\n        {\n            // Backward order in m_Blocks - prefer blocks with largest amount of free space.\n            for (size_t blockIndex = m_Blocks.size(); blockIndex--; )\n            {\n                VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];\n                VMA_ASSERT(pCurrBlock);\n                VkResult res = AllocateFromBlock(pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);\n                if (res == VK_SUCCESS)\n                {\n                    VMA_DEBUG_LOG(\"    Returned from existing block #%u\", pCurrBlock->GetId());\n                    IncrementallySortBlocks();\n                    return VK_SUCCESS;\n                }\n            }\n        }\n    }\n\n    // 2. Try to create new block.\n    if (canCreateNewBlock)\n    {\n        // Calculate optimal size for new block.\n        VkDeviceSize newBlockSize = m_PreferredBlockSize;\n        uint32_t newBlockSizeShift = 0;\n        const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;\n\n        if (!m_ExplicitBlockSize)\n        {\n            // Allocate 1/8, 1/4, 1/2 as first blocks.\n            const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();\n            for (uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)\n            {\n                const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;\n                if (smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)\n                {\n                    newBlockSize = smallerNewBlockSize;\n                    ++newBlockSizeShift;\n                }\n                else\n                {\n                    break;\n                }\n            }\n        }\n\n        size_t newBlockIndex = 0;\n        VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?\n            CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;\n        // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.\n        if (!m_ExplicitBlockSize)\n        {\n            while (res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)\n            {\n                const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;\n                if (smallerNewBlockSize >= size)\n                {\n                    newBlockSize = smallerNewBlockSize;\n                    ++newBlockSizeShift;\n                    res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?\n                        CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;\n                }\n                else\n                {\n                    break;\n                }\n            }\n        }\n\n        if (res == VK_SUCCESS)\n        {\n            VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];\n            VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);\n\n            res = AllocateFromBlock(\n                pBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);\n            if (res == VK_SUCCESS)\n            {\n                VMA_DEBUG_LOG(\"    Created new block #%u Size=%llu\", pBlock->GetId(), newBlockSize);\n                IncrementallySortBlocks();\n                return VK_SUCCESS;\n            }\n            else\n            {\n                // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.\n                return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n            }\n        }\n    }\n\n    return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n}\n\nvoid VmaBlockVector::Free(const VmaAllocation hAllocation)\n{\n    VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;\n\n    bool budgetExceeded = false;\n    {\n        const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);\n        VmaBudget heapBudget = {};\n        m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1);\n        budgetExceeded = heapBudget.usage >= heapBudget.budget;\n    }\n\n    // Scope for lock.\n    {\n        VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);\n\n        VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();\n\n        if (IsCorruptionDetectionEnabled())\n        {\n            VkResult res = pBlock->ValidateMagicValueAfterAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());\n            VMA_ASSERT(res == VK_SUCCESS && \"Couldn't map block memory to validate magic value.\");\n        }\n\n        if (hAllocation->IsPersistentMap())\n        {\n            pBlock->Unmap(m_hAllocator, 1);\n        }\n\n        const bool hadEmptyBlockBeforeFree = HasEmptyBlock();\n        pBlock->m_pMetadata->Free(hAllocation->GetAllocHandle());\n        pBlock->PostFree(m_hAllocator);\n        VMA_HEAVY_ASSERT(pBlock->Validate());\n\n        VMA_DEBUG_LOG(\"  Freed from MemoryTypeIndex=%u\", m_MemoryTypeIndex);\n\n        const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount;\n        // pBlock became empty after this deallocation.\n        if (pBlock->m_pMetadata->IsEmpty())\n        {\n            // Already had empty block. We don't want to have two, so delete this one.\n            if ((hadEmptyBlockBeforeFree || budgetExceeded) && canDeleteBlock)\n            {\n                pBlockToDelete = pBlock;\n                Remove(pBlock);\n            }\n            // else: We now have one empty block - leave it. A hysteresis to avoid allocating whole block back and forth.\n        }\n        // pBlock didn't become empty, but we have another empty block - find and free that one.\n        // (This is optional, heuristics.)\n        else if (hadEmptyBlockBeforeFree && canDeleteBlock)\n        {\n            VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();\n            if (pLastBlock->m_pMetadata->IsEmpty())\n            {\n                pBlockToDelete = pLastBlock;\n                m_Blocks.pop_back();\n            }\n        }\n\n        IncrementallySortBlocks();\n    }\n\n    // Destruction of a free block. Deferred until this point, outside of mutex\n    // lock, for performance reason.\n    if (pBlockToDelete != VMA_NULL)\n    {\n        VMA_DEBUG_LOG(\"    Deleted empty block #%u\", pBlockToDelete->GetId());\n        pBlockToDelete->Destroy(m_hAllocator);\n        vma_delete(m_hAllocator, pBlockToDelete);\n    }\n\n    m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());\n    m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);\n}\n\nVkDeviceSize VmaBlockVector::CalcMaxBlockSize() const\n{\n    VkDeviceSize result = 0;\n    for (size_t i = m_Blocks.size(); i--; )\n    {\n        result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize());\n        if (result >= m_PreferredBlockSize)\n        {\n            break;\n        }\n    }\n    return result;\n}\n\nvoid VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)\n{\n    for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)\n    {\n        if (m_Blocks[blockIndex] == pBlock)\n        {\n            VmaVectorRemove(m_Blocks, blockIndex);\n            return;\n        }\n    }\n    VMA_ASSERT(0);\n}\n\nvoid VmaBlockVector::IncrementallySortBlocks()\n{\n    if (!m_IncrementalSort)\n        return;\n    if (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)\n    {\n        // Bubble sort only until first swap.\n        for (size_t i = 1; i < m_Blocks.size(); ++i)\n        {\n            if (m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())\n            {\n                VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);\n                return;\n            }\n        }\n    }\n}\n\nvoid VmaBlockVector::SortByFreeSize()\n{\n    VMA_SORT(m_Blocks.begin(), m_Blocks.end(),\n        [](VmaDeviceMemoryBlock* b1, VmaDeviceMemoryBlock* b2) -> bool\n        {\n            return b1->m_pMetadata->GetSumFreeSize() < b2->m_pMetadata->GetSumFreeSize();\n        });\n}\n\nVkResult VmaBlockVector::AllocateFromBlock(\n    VmaDeviceMemoryBlock* pBlock,\n    VkDeviceSize size,\n    VkDeviceSize alignment,\n    VmaAllocationCreateFlags allocFlags,\n    void* pUserData,\n    VmaSuballocationType suballocType,\n    uint32_t strategy,\n    VmaAllocation* pAllocation)\n{\n    const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;\n\n    VmaAllocationRequest currRequest = {};\n    if (pBlock->m_pMetadata->CreateAllocationRequest(\n        size,\n        alignment,\n        isUpperAddress,\n        suballocType,\n        strategy,\n        &currRequest))\n    {\n        return CommitAllocationRequest(currRequest, pBlock, alignment, allocFlags, pUserData, suballocType, pAllocation);\n    }\n    return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n}\n\nVkResult VmaBlockVector::CommitAllocationRequest(\n    VmaAllocationRequest& allocRequest,\n    VmaDeviceMemoryBlock* pBlock,\n    VkDeviceSize alignment,\n    VmaAllocationCreateFlags allocFlags,\n    void* pUserData,\n    VmaSuballocationType suballocType,\n    VmaAllocation* pAllocation)\n{\n    const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;\n    const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;\n    const bool isMappingAllowed = (allocFlags &\n        (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0;\n\n    pBlock->PostAlloc(m_hAllocator);\n    // Allocate from pCurrBlock.\n    if (mapped)\n    {\n        VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL);\n        if (res != VK_SUCCESS)\n        {\n            return res;\n        }\n    }\n\n    *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(isMappingAllowed);\n    pBlock->m_pMetadata->Alloc(allocRequest, suballocType, *pAllocation);\n    (*pAllocation)->InitBlockAllocation(\n        pBlock,\n        allocRequest.allocHandle,\n        alignment,\n        allocRequest.size, // Not size, as actual allocation size may be larger than requested!\n        m_MemoryTypeIndex,\n        suballocType,\n        mapped);\n    VMA_HEAVY_ASSERT(pBlock->Validate());\n    if (isUserDataString)\n        (*pAllocation)->SetName(m_hAllocator, (const char*)pUserData);\n    else\n        (*pAllocation)->SetUserData(m_hAllocator, pUserData);\n    m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), allocRequest.size);\n    if (VMA_DEBUG_INITIALIZE_ALLOCATIONS)\n    {\n        m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);\n    }\n    if (IsCorruptionDetectionEnabled())\n    {\n        VkResult res = pBlock->WriteMagicValueAfterAllocation(m_hAllocator, (*pAllocation)->GetOffset(), allocRequest.size);\n        VMA_ASSERT(res == VK_SUCCESS && \"Couldn't map block memory to write magic value.\");\n    }\n    return VK_SUCCESS;\n}\n\nVkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex)\n{\n    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };\n    allocInfo.pNext = m_pMemoryAllocateNext;\n    allocInfo.memoryTypeIndex = m_MemoryTypeIndex;\n    allocInfo.allocationSize = blockSize;\n\n#if VMA_BUFFER_DEVICE_ADDRESS\n    // Every standalone block can potentially contain a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - always enable the feature.\n    VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };\n    if (m_hAllocator->m_UseKhrBufferDeviceAddress)\n    {\n        allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;\n        VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo);\n    }\n#endif // VMA_BUFFER_DEVICE_ADDRESS\n\n#if VMA_MEMORY_PRIORITY\n    VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT };\n    if (m_hAllocator->m_UseExtMemoryPriority)\n    {\n        VMA_ASSERT(m_Priority >= 0.f && m_Priority <= 1.f);\n        priorityInfo.priority = m_Priority;\n        VmaPnextChainPushFront(&allocInfo, &priorityInfo);\n    }\n#endif // VMA_MEMORY_PRIORITY\n\n#if VMA_EXTERNAL_MEMORY\n    // Attach VkExportMemoryAllocateInfoKHR if necessary.\n    VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR };\n    exportMemoryAllocInfo.handleTypes = m_hAllocator->GetExternalMemoryHandleTypeFlags(m_MemoryTypeIndex);\n    if (exportMemoryAllocInfo.handleTypes != 0)\n    {\n        VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo);\n    }\n#endif // VMA_EXTERNAL_MEMORY\n\n    VkDeviceMemory mem = VK_NULL_HANDLE;\n    VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);\n    if (res < 0)\n    {\n        return res;\n    }\n\n    // New VkDeviceMemory successfully created.\n\n    // Create new Allocation for it.\n    VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);\n    pBlock->Init(\n        m_hAllocator,\n        m_hParentPool,\n        m_MemoryTypeIndex,\n        mem,\n        allocInfo.allocationSize,\n        m_NextBlockId++,\n        m_Algorithm,\n        m_BufferImageGranularity);\n\n    m_Blocks.push_back(pBlock);\n    if (pNewBlockIndex != VMA_NULL)\n    {\n        *pNewBlockIndex = m_Blocks.size() - 1;\n    }\n\n    return VK_SUCCESS;\n}\n\nbool VmaBlockVector::HasEmptyBlock()\n{\n    for (size_t index = 0, count = m_Blocks.size(); index < count; ++index)\n    {\n        VmaDeviceMemoryBlock* const pBlock = m_Blocks[index];\n        if (pBlock->m_pMetadata->IsEmpty())\n        {\n            return true;\n        }\n    }\n    return false;\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)\n{\n    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);\n\n\n    json.BeginObject();\n    for (size_t i = 0; i < m_Blocks.size(); ++i)\n    {\n        json.BeginString();\n        json.ContinueString(m_Blocks[i]->GetId());\n        json.EndString();\n\n        json.BeginObject();\n        json.WriteString(\"MapRefCount\");\n        json.WriteNumber(m_Blocks[i]->GetMapRefCount());\n\n        m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);\n        json.EndObject();\n    }\n    json.EndObject();\n}\n#endif // VMA_STATS_STRING_ENABLED\n\nVkResult VmaBlockVector::CheckCorruption()\n{\n    if (!IsCorruptionDetectionEnabled())\n    {\n        return VK_ERROR_FEATURE_NOT_PRESENT;\n    }\n\n    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);\n    for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)\n    {\n        VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];\n        VMA_ASSERT(pBlock);\n        VkResult res = pBlock->CheckCorruption(m_hAllocator);\n        if (res != VK_SUCCESS)\n        {\n            return res;\n        }\n    }\n    return VK_SUCCESS;\n}\n\n#endif // _VMA_BLOCK_VECTOR_FUNCTIONS\n\n#ifndef _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS\nVmaDefragmentationContext_T::VmaDefragmentationContext_T(\n    VmaAllocator hAllocator,\n    const VmaDefragmentationInfo& info)\n    : m_MaxPassBytes(info.maxBytesPerPass == 0 ? VK_WHOLE_SIZE : info.maxBytesPerPass),\n    m_MaxPassAllocations(info.maxAllocationsPerPass == 0 ? UINT32_MAX : info.maxAllocationsPerPass),\n    m_MoveAllocator(hAllocator->GetAllocationCallbacks()),\n    m_Moves(m_MoveAllocator)\n{\n    m_Algorithm = info.flags & VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK;\n\n    if (info.pool != VMA_NULL)\n    {\n        m_BlockVectorCount = 1;\n        m_PoolBlockVector = &info.pool->m_BlockVector;\n        m_pBlockVectors = &m_PoolBlockVector;\n        m_PoolBlockVector->SetIncrementalSort(false);\n        m_PoolBlockVector->SortByFreeSize();\n    }\n    else\n    {\n        m_BlockVectorCount = hAllocator->GetMemoryTypeCount();\n        m_PoolBlockVector = VMA_NULL;\n        m_pBlockVectors = hAllocator->m_pBlockVectors;\n        for (uint32_t i = 0; i < m_BlockVectorCount; ++i)\n        {\n            VmaBlockVector* vector = m_pBlockVectors[i];\n            if (vector != VMA_NULL)\n            {\n                vector->SetIncrementalSort(false);\n                vector->SortByFreeSize();\n            }\n        }\n    }\n\n    switch (m_Algorithm)\n    {\n    case 0: // Default algorithm\n        m_Algorithm = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT;\n    case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT:\n    {\n        m_AlgorithmState = vma_new_array(hAllocator, StateBalanced, m_BlockVectorCount);\n        break;\n    }\n    case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:\n    {\n        if (hAllocator->GetBufferImageGranularity() > 1)\n        {\n            m_AlgorithmState = vma_new_array(hAllocator, StateExtensive, m_BlockVectorCount);\n        }\n        break;\n    }\n    }\n}\n\nVmaDefragmentationContext_T::~VmaDefragmentationContext_T()\n{\n    if (m_PoolBlockVector != VMA_NULL)\n    {\n        m_PoolBlockVector->SetIncrementalSort(true);\n    }\n    else\n    {\n        for (uint32_t i = 0; i < m_BlockVectorCount; ++i)\n        {\n            VmaBlockVector* vector = m_pBlockVectors[i];\n            if (vector != VMA_NULL)\n                vector->SetIncrementalSort(true);\n        }\n    }\n\n    if (m_AlgorithmState)\n    {\n        switch (m_Algorithm)\n        {\n        case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT:\n            vma_delete_array(m_MoveAllocator.m_pCallbacks, reinterpret_cast<StateBalanced*>(m_AlgorithmState), m_BlockVectorCount);\n            break;\n        case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:\n            vma_delete_array(m_MoveAllocator.m_pCallbacks, reinterpret_cast<StateExtensive*>(m_AlgorithmState), m_BlockVectorCount);\n            break;\n        default:\n            VMA_ASSERT(0);\n        }\n    }\n}\n\nVkResult VmaDefragmentationContext_T::DefragmentPassBegin(VmaDefragmentationPassMoveInfo& moveInfo)\n{\n    if (m_PoolBlockVector != VMA_NULL)\n    {\n        VmaMutexLockWrite lock(m_PoolBlockVector->GetMutex(), m_PoolBlockVector->GetAllocator()->m_UseMutex);\n\n        if (m_PoolBlockVector->GetBlockCount() > 1)\n            ComputeDefragmentation(*m_PoolBlockVector, 0);\n        else if (m_PoolBlockVector->GetBlockCount() == 1)\n            ReallocWithinBlock(*m_PoolBlockVector, m_PoolBlockVector->GetBlock(0));\n    }\n    else\n    {\n        for (uint32_t i = 0; i < m_BlockVectorCount; ++i)\n        {\n            if (m_pBlockVectors[i] != VMA_NULL)\n            {\n                VmaMutexLockWrite lock(m_pBlockVectors[i]->GetMutex(), m_pBlockVectors[i]->GetAllocator()->m_UseMutex);\n\n                if (m_pBlockVectors[i]->GetBlockCount() > 1)\n                {\n                    if (ComputeDefragmentation(*m_pBlockVectors[i], i))\n                        break;\n                }\n                else if (m_pBlockVectors[i]->GetBlockCount() == 1)\n                {\n                    if (ReallocWithinBlock(*m_pBlockVectors[i], m_pBlockVectors[i]->GetBlock(0)))\n                        break;\n                }\n            }\n        }\n    }\n\n    moveInfo.moveCount = static_cast<uint32_t>(m_Moves.size());\n    if (moveInfo.moveCount > 0)\n    {\n        moveInfo.pMoves = m_Moves.data();\n        return VK_INCOMPLETE;\n    }\n\n    moveInfo.pMoves = VMA_NULL;\n    return VK_SUCCESS;\n}\n\nVkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMoveInfo& moveInfo)\n{\n    VMA_ASSERT(moveInfo.moveCount > 0 ? moveInfo.pMoves != VMA_NULL : true);\n\n    VkResult result = VK_SUCCESS;\n    VmaStlAllocator<FragmentedBlock> blockAllocator(m_MoveAllocator.m_pCallbacks);\n    VmaVector<FragmentedBlock, VmaStlAllocator<FragmentedBlock>> immovableBlocks(blockAllocator);\n    VmaVector<FragmentedBlock, VmaStlAllocator<FragmentedBlock>> mappedBlocks(blockAllocator);\n\n    VmaAllocator allocator = VMA_NULL;\n    for (uint32_t i = 0; i < moveInfo.moveCount; ++i)\n    {\n        VmaDefragmentationMove& move = moveInfo.pMoves[i];\n        size_t prevCount = 0, currentCount = 0;\n        VkDeviceSize freedBlockSize = 0;\n\n        uint32_t vectorIndex;\n        VmaBlockVector* vector;\n        if (m_PoolBlockVector != VMA_NULL)\n        {\n            vectorIndex = 0;\n            vector = m_PoolBlockVector;\n        }\n        else\n        {\n            vectorIndex = move.srcAllocation->GetMemoryTypeIndex();\n            vector = m_pBlockVectors[vectorIndex];\n            VMA_ASSERT(vector != VMA_NULL);\n        }\n\n        switch (move.operation)\n        {\n        case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY:\n        {\n            uint8_t mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation);\n            if (mapCount > 0)\n            {\n                allocator = vector->m_hAllocator;\n                VmaDeviceMemoryBlock* newMapBlock = move.srcAllocation->GetBlock();\n                bool notPresent = true;\n                for (FragmentedBlock& block : mappedBlocks)\n                {\n                    if (block.block == newMapBlock)\n                    {\n                        notPresent = false;\n                        block.data += mapCount;\n                        break;\n                    }\n                }\n                if (notPresent)\n                    mappedBlocks.push_back({ mapCount, newMapBlock });\n            }\n\n            // Scope for locks, Free have it's own lock\n            {\n                VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n                prevCount = vector->GetBlockCount();\n                freedBlockSize = move.dstTmpAllocation->GetBlock()->m_pMetadata->GetSize();\n            }\n            vector->Free(move.dstTmpAllocation);\n            {\n                VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n                currentCount = vector->GetBlockCount();\n            }\n\n            result = VK_INCOMPLETE;\n            break;\n        }\n        case VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE:\n        {\n            m_PassStats.bytesMoved -= move.srcAllocation->GetSize();\n            --m_PassStats.allocationsMoved;\n            vector->Free(move.dstTmpAllocation);\n\n            VmaDeviceMemoryBlock* newBlock = move.srcAllocation->GetBlock();\n            bool notPresent = true;\n            for (const FragmentedBlock& block : immovableBlocks)\n            {\n                if (block.block == newBlock)\n                {\n                    notPresent = false;\n                    break;\n                }\n            }\n            if (notPresent)\n                immovableBlocks.push_back({ vectorIndex, newBlock });\n            break;\n        }\n        case VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY:\n        {\n            m_PassStats.bytesMoved -= move.srcAllocation->GetSize();\n            --m_PassStats.allocationsMoved;\n            // Scope for locks, Free have it's own lock\n            {\n                VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n                prevCount = vector->GetBlockCount();\n                freedBlockSize = move.srcAllocation->GetBlock()->m_pMetadata->GetSize();\n            }\n            vector->Free(move.srcAllocation);\n            {\n                VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n                currentCount = vector->GetBlockCount();\n            }\n            freedBlockSize *= prevCount - currentCount;\n\n            VkDeviceSize dstBlockSize;\n            {\n                VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n                dstBlockSize = move.dstTmpAllocation->GetBlock()->m_pMetadata->GetSize();\n            }\n            vector->Free(move.dstTmpAllocation);\n            {\n                VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n                freedBlockSize += dstBlockSize * (currentCount - vector->GetBlockCount());\n                currentCount = vector->GetBlockCount();\n            }\n\n            result = VK_INCOMPLETE;\n            break;\n        }\n        default:\n            VMA_ASSERT(0);\n        }\n\n        if (prevCount > currentCount)\n        {\n            size_t freedBlocks = prevCount - currentCount;\n            m_PassStats.deviceMemoryBlocksFreed += static_cast<uint32_t>(freedBlocks);\n            m_PassStats.bytesFreed += freedBlockSize;\n        }\n\n        switch (m_Algorithm)\n        {\n        case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:\n        {\n            if (m_AlgorithmState != VMA_NULL)\n            {\n                // Avoid unnecessary tries to allocate when new free block is available\n                StateExtensive& state = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[vectorIndex];\n                if (state.firstFreeBlock != SIZE_MAX)\n                {\n                    const size_t diff = prevCount - currentCount;\n                    if (state.firstFreeBlock >= diff)\n                    {\n                        state.firstFreeBlock -= diff;\n                        if (state.firstFreeBlock != 0)\n                            state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty();\n                    }\n                    else\n                        state.firstFreeBlock = 0;\n                }\n            }\n        }\n        }\n    }\n    moveInfo.moveCount = 0;\n    moveInfo.pMoves = VMA_NULL;\n    m_Moves.clear();\n\n    // Update stats\n    m_GlobalStats.allocationsMoved += m_PassStats.allocationsMoved;\n    m_GlobalStats.bytesFreed += m_PassStats.bytesFreed;\n    m_GlobalStats.bytesMoved += m_PassStats.bytesMoved;\n    m_GlobalStats.deviceMemoryBlocksFreed += m_PassStats.deviceMemoryBlocksFreed;\n    m_PassStats = { 0 };\n\n    // Move blocks with immovable allocations according to algorithm\n    if (immovableBlocks.size() > 0)\n    {\n        switch (m_Algorithm)\n        {\n        case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:\n        {\n            if (m_AlgorithmState != VMA_NULL)\n            {\n                bool swapped = false;\n                // Move to the start of free blocks range\n                for (const FragmentedBlock& block : immovableBlocks)\n                {\n                    StateExtensive& state = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[block.data];\n                    if (state.operation != StateExtensive::Operation::Cleanup)\n                    {\n                        VmaBlockVector* vector = m_pBlockVectors[block.data];\n                        VmaMutexLockWrite lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n\n                        for (size_t i = 0, count = vector->GetBlockCount() - m_ImmovableBlockCount; i < count; ++i)\n                        {\n                            if (vector->GetBlock(i) == block.block)\n                            {\n                                VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[vector->GetBlockCount() - ++m_ImmovableBlockCount]);\n                                if (state.firstFreeBlock != SIZE_MAX)\n                                {\n                                    if (i + 1 < state.firstFreeBlock)\n                                    {\n                                        if (state.firstFreeBlock > 1)\n                                            VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[--state.firstFreeBlock]);\n                                        else\n                                            --state.firstFreeBlock;\n                                    }\n                                }\n                                swapped = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n                if (swapped)\n                    result = VK_INCOMPLETE;\n                break;\n            }\n        }\n        default:\n        {\n            // Move to the beginning\n            for (const FragmentedBlock& block : immovableBlocks)\n            {\n                VmaBlockVector* vector = m_pBlockVectors[block.data];\n                VmaMutexLockWrite lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);\n\n                for (size_t i = m_ImmovableBlockCount; i < vector->GetBlockCount(); ++i)\n                {\n                    if (vector->GetBlock(i) == block.block)\n                    {\n                        VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[m_ImmovableBlockCount++]);\n                        break;\n                    }\n                }\n            }\n            break;\n        }\n        }\n    }\n\n    // Bulk-map destination blocks\n    for (const FragmentedBlock& block : mappedBlocks)\n    {\n        VkResult res = block.block->Map(allocator, block.data, VMA_NULL);\n        VMA_ASSERT(res == VK_SUCCESS);\n    }\n    return result;\n}\n\nbool VmaDefragmentationContext_T::ComputeDefragmentation(VmaBlockVector& vector, size_t index)\n{\n    switch (m_Algorithm)\n    {\n    case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT:\n        return ComputeDefragmentation_Fast(vector);\n    default:\n        VMA_ASSERT(0);\n    case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT:\n        return ComputeDefragmentation_Balanced(vector, index, true);\n    case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT:\n        return ComputeDefragmentation_Full(vector);\n    case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:\n        return ComputeDefragmentation_Extensive(vector, index);\n    }\n}\n\nVmaDefragmentationContext_T::MoveAllocationData VmaDefragmentationContext_T::GetMoveData(\n    VmaAllocHandle handle, VmaBlockMetadata* metadata)\n{\n    MoveAllocationData moveData;\n    moveData.move.srcAllocation = (VmaAllocation)metadata->GetAllocationUserData(handle);\n    moveData.size = moveData.move.srcAllocation->GetSize();\n    moveData.alignment = moveData.move.srcAllocation->GetAlignment();\n    moveData.type = moveData.move.srcAllocation->GetSuballocationType();\n    moveData.flags = 0;\n\n    if (moveData.move.srcAllocation->IsPersistentMap())\n        moveData.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;\n    if (moveData.move.srcAllocation->IsMappingAllowed())\n        moveData.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;\n\n    return moveData;\n}\n\nVmaDefragmentationContext_T::CounterStatus VmaDefragmentationContext_T::CheckCounters(VkDeviceSize bytes)\n{\n    // Ignore allocation if will exceed max size for copy\n    if (m_PassStats.bytesMoved + bytes > m_MaxPassBytes)\n    {\n        if (++m_IgnoredAllocs < MAX_ALLOCS_TO_IGNORE)\n            return CounterStatus::Ignore;\n        else\n            return CounterStatus::End;\n    }\n    return CounterStatus::Pass;\n}\n\nbool VmaDefragmentationContext_T::IncrementCounters(VkDeviceSize bytes)\n{\n    m_PassStats.bytesMoved += bytes;\n    // Early return when max found\n    if (++m_PassStats.allocationsMoved >= m_MaxPassAllocations || m_PassStats.bytesMoved >= m_MaxPassBytes)\n    {\n        VMA_ASSERT(m_PassStats.allocationsMoved == m_MaxPassAllocations ||\n            m_PassStats.bytesMoved == m_MaxPassBytes && \"Exceeded maximal pass threshold!\");\n        return true;\n    }\n    return false;\n}\n\nbool VmaDefragmentationContext_T::ReallocWithinBlock(VmaBlockVector& vector, VmaDeviceMemoryBlock* block)\n{\n    VmaBlockMetadata* metadata = block->m_pMetadata;\n\n    for (VmaAllocHandle handle = metadata->GetAllocationListBegin();\n        handle != VK_NULL_HANDLE;\n        handle = metadata->GetNextAllocation(handle))\n    {\n        MoveAllocationData moveData = GetMoveData(handle, metadata);\n        // Ignore newly created allocations by defragmentation algorithm\n        if (moveData.move.srcAllocation->GetUserData() == this)\n            continue;\n        switch (CheckCounters(moveData.move.srcAllocation->GetSize()))\n        {\n        case CounterStatus::Ignore:\n            continue;\n        case CounterStatus::End:\n            return true;\n        default:\n            VMA_ASSERT(0);\n        case CounterStatus::Pass:\n            break;\n        }\n\n        VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();\n        if (offset != 0 && metadata->GetSumFreeSize() >= moveData.size)\n        {\n            VmaAllocationRequest request = {};\n            if (metadata->CreateAllocationRequest(\n                moveData.size,\n                moveData.alignment,\n                false,\n                moveData.type,\n                VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,\n                &request))\n            {\n                if (metadata->GetAllocationOffset(request.allocHandle) < offset)\n                {\n                    if (vector.CommitAllocationRequest(\n                        request,\n                        block,\n                        moveData.alignment,\n                        moveData.flags,\n                        this,\n                        moveData.type,\n                        &moveData.move.dstTmpAllocation) == VK_SUCCESS)\n                    {\n                        m_Moves.push_back(moveData.move);\n                        if (IncrementCounters(moveData.size))\n                            return true;\n                    }\n                }\n            }\n        }\n    }\n    return false;\n}\n\nbool VmaDefragmentationContext_T::AllocInOtherBlock(size_t start, size_t end, MoveAllocationData& data, VmaBlockVector& vector)\n{\n    for (; start < end; ++start)\n    {\n        VmaDeviceMemoryBlock* dstBlock = vector.GetBlock(start);\n        if (dstBlock->m_pMetadata->GetSumFreeSize() >= data.size)\n        {\n            if (vector.AllocateFromBlock(dstBlock,\n                data.size,\n                data.alignment,\n                data.flags,\n                this,\n                data.type,\n                0,\n                &data.move.dstTmpAllocation) == VK_SUCCESS)\n            {\n                m_Moves.push_back(data.move);\n                if (IncrementCounters(data.size))\n                    return true;\n                break;\n            }\n        }\n    }\n    return false;\n}\n\nbool VmaDefragmentationContext_T::ComputeDefragmentation_Fast(VmaBlockVector& vector)\n{\n    // Move only between blocks\n\n    // Go through allocations in last blocks and try to fit them inside first ones\n    for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i)\n    {\n        VmaBlockMetadata* metadata = vector.GetBlock(i)->m_pMetadata;\n\n        for (VmaAllocHandle handle = metadata->GetAllocationListBegin();\n            handle != VK_NULL_HANDLE;\n            handle = metadata->GetNextAllocation(handle))\n        {\n            MoveAllocationData moveData = GetMoveData(handle, metadata);\n            // Ignore newly created allocations by defragmentation algorithm\n            if (moveData.move.srcAllocation->GetUserData() == this)\n                continue;\n            switch (CheckCounters(moveData.move.srcAllocation->GetSize()))\n            {\n            case CounterStatus::Ignore:\n                continue;\n            case CounterStatus::End:\n                return true;\n            default:\n                VMA_ASSERT(0);\n            case CounterStatus::Pass:\n                break;\n            }\n\n            // Check all previous blocks for free space\n            if (AllocInOtherBlock(0, i, moveData, vector))\n                return true;\n        }\n    }\n    return false;\n}\n\nbool VmaDefragmentationContext_T::ComputeDefragmentation_Balanced(VmaBlockVector& vector, size_t index, bool update)\n{\n    // Go over every allocation and try to fit it in previous blocks at lowest offsets,\n    // if not possible: realloc within single block to minimize offset (exclude offset == 0),\n    // but only if there are noticeable gaps between them (some heuristic, ex. average size of allocation in block)\n    VMA_ASSERT(m_AlgorithmState != VMA_NULL);\n\n    StateBalanced& vectorState = reinterpret_cast<StateBalanced*>(m_AlgorithmState)[index];\n    if (update && vectorState.avgAllocSize == UINT64_MAX)\n        UpdateVectorStatistics(vector, vectorState);\n\n    const size_t startMoveCount = m_Moves.size();\n    VkDeviceSize minimalFreeRegion = vectorState.avgFreeSize / 2;\n    for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i)\n    {\n        VmaDeviceMemoryBlock* block = vector.GetBlock(i);\n        VmaBlockMetadata* metadata = block->m_pMetadata;\n        VkDeviceSize prevFreeRegionSize = 0;\n\n        for (VmaAllocHandle handle = metadata->GetAllocationListBegin();\n            handle != VK_NULL_HANDLE;\n            handle = metadata->GetNextAllocation(handle))\n        {\n            MoveAllocationData moveData = GetMoveData(handle, metadata);\n            // Ignore newly created allocations by defragmentation algorithm\n            if (moveData.move.srcAllocation->GetUserData() == this)\n                continue;\n            switch (CheckCounters(moveData.move.srcAllocation->GetSize()))\n            {\n            case CounterStatus::Ignore:\n                continue;\n            case CounterStatus::End:\n                return true;\n            default:\n                VMA_ASSERT(0);\n            case CounterStatus::Pass:\n                break;\n            }\n\n            // Check all previous blocks for free space\n            const size_t prevMoveCount = m_Moves.size();\n            if (AllocInOtherBlock(0, i, moveData, vector))\n                return true;\n\n            VkDeviceSize nextFreeRegionSize = metadata->GetNextFreeRegionSize(handle);\n            // If no room found then realloc within block for lower offset\n            VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();\n            if (prevMoveCount == m_Moves.size() && offset != 0 && metadata->GetSumFreeSize() >= moveData.size)\n            {\n                // Check if realloc will make sense\n                if (prevFreeRegionSize >= minimalFreeRegion ||\n                    nextFreeRegionSize >= minimalFreeRegion ||\n                    moveData.size <= vectorState.avgFreeSize ||\n                    moveData.size <= vectorState.avgAllocSize)\n                {\n                    VmaAllocationRequest request = {};\n                    if (metadata->CreateAllocationRequest(\n                        moveData.size,\n                        moveData.alignment,\n                        false,\n                        moveData.type,\n                        VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,\n                        &request))\n                    {\n                        if (metadata->GetAllocationOffset(request.allocHandle) < offset)\n                        {\n                            if (vector.CommitAllocationRequest(\n                                request,\n                                block,\n                                moveData.alignment,\n                                moveData.flags,\n                                this,\n                                moveData.type,\n                                &moveData.move.dstTmpAllocation) == VK_SUCCESS)\n                            {\n                                m_Moves.push_back(moveData.move);\n                                if (IncrementCounters(moveData.size))\n                                    return true;\n                            }\n                        }\n                    }\n                }\n            }\n            prevFreeRegionSize = nextFreeRegionSize;\n        }\n    }\n\n    // No moves performed, update statistics to current vector state\n    if (startMoveCount == m_Moves.size() && !update)\n    {\n        vectorState.avgAllocSize = UINT64_MAX;\n        return ComputeDefragmentation_Balanced(vector, index, false);\n    }\n    return false;\n}\n\nbool VmaDefragmentationContext_T::ComputeDefragmentation_Full(VmaBlockVector& vector)\n{\n    // Go over every allocation and try to fit it in previous blocks at lowest offsets,\n    // if not possible: realloc within single block to minimize offset (exclude offset == 0)\n\n    for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i)\n    {\n        VmaDeviceMemoryBlock* block = vector.GetBlock(i);\n        VmaBlockMetadata* metadata = block->m_pMetadata;\n\n        for (VmaAllocHandle handle = metadata->GetAllocationListBegin();\n            handle != VK_NULL_HANDLE;\n            handle = metadata->GetNextAllocation(handle))\n        {\n            MoveAllocationData moveData = GetMoveData(handle, metadata);\n            // Ignore newly created allocations by defragmentation algorithm\n            if (moveData.move.srcAllocation->GetUserData() == this)\n                continue;\n            switch (CheckCounters(moveData.move.srcAllocation->GetSize()))\n            {\n            case CounterStatus::Ignore:\n                continue;\n            case CounterStatus::End:\n                return true;\n            default:\n                VMA_ASSERT(0);\n            case CounterStatus::Pass:\n                break;\n            }\n\n            // Check all previous blocks for free space\n            const size_t prevMoveCount = m_Moves.size();\n            if (AllocInOtherBlock(0, i, moveData, vector))\n                return true;\n\n            // If no room found then realloc within block for lower offset\n            VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();\n            if (prevMoveCount == m_Moves.size() && offset != 0 && metadata->GetSumFreeSize() >= moveData.size)\n            {\n                VmaAllocationRequest request = {};\n                if (metadata->CreateAllocationRequest(\n                    moveData.size,\n                    moveData.alignment,\n                    false,\n                    moveData.type,\n                    VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,\n                    &request))\n                {\n                    if (metadata->GetAllocationOffset(request.allocHandle) < offset)\n                    {\n                        if (vector.CommitAllocationRequest(\n                            request,\n                            block,\n                            moveData.alignment,\n                            moveData.flags,\n                            this,\n                            moveData.type,\n                            &moveData.move.dstTmpAllocation) == VK_SUCCESS)\n                        {\n                            m_Moves.push_back(moveData.move);\n                            if (IncrementCounters(moveData.size))\n                                return true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return false;\n}\n\nbool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index)\n{\n    // First free single block, then populate it to the brim, then free another block, and so on\n\n    // Fallback to previous algorithm since without granularity conflicts it can achieve max packing\n    if (vector.m_BufferImageGranularity == 1)\n        return ComputeDefragmentation_Full(vector);\n\n    VMA_ASSERT(m_AlgorithmState != VMA_NULL);\n\n    StateExtensive& vectorState = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[index];\n\n    bool texturePresent = false, bufferPresent = false, otherPresent = false;\n    switch (vectorState.operation)\n    {\n    case StateExtensive::Operation::Done: // Vector defragmented\n        return false;\n    case StateExtensive::Operation::FindFreeBlockBuffer:\n    case StateExtensive::Operation::FindFreeBlockTexture:\n    case StateExtensive::Operation::FindFreeBlockAll:\n    {\n        // No more blocks to free, just perform fast realloc and move to cleanup\n        if (vectorState.firstFreeBlock == 0)\n        {\n            vectorState.operation = StateExtensive::Operation::Cleanup;\n            return ComputeDefragmentation_Fast(vector);\n        }\n\n        // No free blocks, have to clear last one\n        size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1;\n        VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata;\n\n        const size_t prevMoveCount = m_Moves.size();\n        for (VmaAllocHandle handle = freeMetadata->GetAllocationListBegin();\n            handle != VK_NULL_HANDLE;\n            handle = freeMetadata->GetNextAllocation(handle))\n        {\n            MoveAllocationData moveData = GetMoveData(handle, freeMetadata);\n            switch (CheckCounters(moveData.move.srcAllocation->GetSize()))\n            {\n            case CounterStatus::Ignore:\n                continue;\n            case CounterStatus::End:\n                return true;\n            default:\n                VMA_ASSERT(0);\n            case CounterStatus::Pass:\n                break;\n            }\n\n            // Check all previous blocks for free space\n            if (AllocInOtherBlock(0, last, moveData, vector))\n            {\n                // Full clear performed already\n                if (prevMoveCount != m_Moves.size() && freeMetadata->GetNextAllocation(handle) == VK_NULL_HANDLE)\n                    reinterpret_cast<size_t*>(m_AlgorithmState)[index] = last;\n                return true;\n            }\n        }\n\n        if (prevMoveCount == m_Moves.size())\n        {\n            // Cannot perform full clear, have to move data in other blocks around\n            if (last != 0)\n            {\n                for (size_t i = last - 1; i; --i)\n                {\n                    if (ReallocWithinBlock(vector, vector.GetBlock(i)))\n                        return true;\n                }\n            }\n\n            if (prevMoveCount == m_Moves.size())\n            {\n                // No possible reallocs within blocks, try to move them around fast\n                return ComputeDefragmentation_Fast(vector);\n            }\n        }\n        else\n        {\n            switch (vectorState.operation)\n            {\n            case StateExtensive::Operation::FindFreeBlockBuffer:\n                vectorState.operation = StateExtensive::Operation::MoveBuffers;\n                break;\n            default:\n                VMA_ASSERT(0);\n            case StateExtensive::Operation::FindFreeBlockTexture:\n                vectorState.operation = StateExtensive::Operation::MoveTextures;\n                break;\n            case StateExtensive::Operation::FindFreeBlockAll:\n                vectorState.operation = StateExtensive::Operation::MoveAll;\n                break;\n            }\n            vectorState.firstFreeBlock = last;\n            // Nothing done, block found without reallocations, can perform another reallocs in same pass\n            return ComputeDefragmentation_Extensive(vector, index);\n        }\n        break;\n    }\n    case StateExtensive::Operation::MoveTextures:\n    {\n        if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL, vector,\n            vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent))\n        {\n            if (texturePresent)\n            {\n                vectorState.operation = StateExtensive::Operation::FindFreeBlockTexture;\n                return ComputeDefragmentation_Extensive(vector, index);\n            }\n\n            if (!bufferPresent && !otherPresent)\n            {\n                vectorState.operation = StateExtensive::Operation::Cleanup;\n                break;\n            }\n\n            // No more textures to move, check buffers\n            vectorState.operation = StateExtensive::Operation::MoveBuffers;\n            bufferPresent = false;\n            otherPresent = false;\n        }\n        else\n            break;\n    }\n    case StateExtensive::Operation::MoveBuffers:\n    {\n        if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_BUFFER, vector,\n            vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent))\n        {\n            if (bufferPresent)\n            {\n                vectorState.operation = StateExtensive::Operation::FindFreeBlockBuffer;\n                return ComputeDefragmentation_Extensive(vector, index);\n            }\n\n            if (!otherPresent)\n            {\n                vectorState.operation = StateExtensive::Operation::Cleanup;\n                break;\n            }\n\n            // No more buffers to move, check all others\n            vectorState.operation = StateExtensive::Operation::MoveAll;\n            otherPresent = false;\n        }\n        else\n            break;\n    }\n    case StateExtensive::Operation::MoveAll:\n    {\n        if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_FREE, vector,\n            vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent))\n        {\n            if (otherPresent)\n            {\n                vectorState.operation = StateExtensive::Operation::FindFreeBlockBuffer;\n                return ComputeDefragmentation_Extensive(vector, index);\n            }\n            // Everything moved\n            vectorState.operation = StateExtensive::Operation::Cleanup;\n        }\n        break;\n    }\n    case StateExtensive::Operation::Cleanup:\n        // Cleanup is handled below so that other operations may reuse the cleanup code. This case is here to prevent the unhandled enum value warning (C4062).\n        break;\n    }\n\n    if (vectorState.operation == StateExtensive::Operation::Cleanup)\n    {\n        // All other work done, pack data in blocks even tighter if possible\n        const size_t prevMoveCount = m_Moves.size();\n        for (size_t i = 0; i < vector.GetBlockCount(); ++i)\n        {\n            if (ReallocWithinBlock(vector, vector.GetBlock(i)))\n                return true;\n        }\n\n        if (prevMoveCount == m_Moves.size())\n            vectorState.operation = StateExtensive::Operation::Done;\n    }\n    return false;\n}\n\nvoid VmaDefragmentationContext_T::UpdateVectorStatistics(VmaBlockVector& vector, StateBalanced& state)\n{\n    size_t allocCount = 0;\n    size_t freeCount = 0;\n    state.avgFreeSize = 0;\n    state.avgAllocSize = 0;\n\n    for (size_t i = 0; i < vector.GetBlockCount(); ++i)\n    {\n        VmaBlockMetadata* metadata = vector.GetBlock(i)->m_pMetadata;\n\n        allocCount += metadata->GetAllocationCount();\n        freeCount += metadata->GetFreeRegionsCount();\n        state.avgFreeSize += metadata->GetSumFreeSize();\n        state.avgAllocSize += metadata->GetSize();\n    }\n\n    state.avgAllocSize = (state.avgAllocSize - state.avgFreeSize) / allocCount;\n    state.avgFreeSize /= freeCount;\n}\n\nbool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType,\n    VmaBlockVector& vector, size_t firstFreeBlock,\n    bool& texturePresent, bool& bufferPresent, bool& otherPresent)\n{\n    const size_t prevMoveCount = m_Moves.size();\n    for (size_t i = firstFreeBlock ; i;)\n    {\n        VmaDeviceMemoryBlock* block = vector.GetBlock(--i);\n        VmaBlockMetadata* metadata = block->m_pMetadata;\n\n        for (VmaAllocHandle handle = metadata->GetAllocationListBegin();\n            handle != VK_NULL_HANDLE;\n            handle = metadata->GetNextAllocation(handle))\n        {\n            MoveAllocationData moveData = GetMoveData(handle, metadata);\n            // Ignore newly created allocations by defragmentation algorithm\n            if (moveData.move.srcAllocation->GetUserData() == this)\n                continue;\n            switch (CheckCounters(moveData.move.srcAllocation->GetSize()))\n            {\n            case CounterStatus::Ignore:\n                continue;\n            case CounterStatus::End:\n                return true;\n            default:\n                VMA_ASSERT(0);\n            case CounterStatus::Pass:\n                break;\n            }\n\n            // Move only single type of resources at once\n            if (!VmaIsBufferImageGranularityConflict(moveData.type, currentType))\n            {\n                // Try to fit allocation into free blocks\n                if (AllocInOtherBlock(firstFreeBlock, vector.GetBlockCount(), moveData, vector))\n                    return false;\n            }\n\n            if (!VmaIsBufferImageGranularityConflict(moveData.type, VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL))\n                texturePresent = true;\n            else if (!VmaIsBufferImageGranularityConflict(moveData.type, VMA_SUBALLOCATION_TYPE_BUFFER))\n                bufferPresent = true;\n            else\n                otherPresent = true;\n        }\n    }\n    return prevMoveCount == m_Moves.size();\n}\n#endif // _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS\n\n#ifndef _VMA_POOL_T_FUNCTIONS\nVmaPool_T::VmaPool_T(\n    VmaAllocator hAllocator,\n    const VmaPoolCreateInfo& createInfo,\n    VkDeviceSize preferredBlockSize)\n    : m_BlockVector(\n        hAllocator,\n        this, // hParentPool\n        createInfo.memoryTypeIndex,\n        createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,\n        createInfo.minBlockCount,\n        createInfo.maxBlockCount,\n        (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),\n        createInfo.blockSize != 0, // explicitBlockSize\n        createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm\n        createInfo.priority,\n        VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment),\n        createInfo.pMemoryAllocateNext),\n    m_Id(0),\n    m_Name(VMA_NULL) {}\n\nVmaPool_T::~VmaPool_T()\n{\n    VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL);\n}\n\nvoid VmaPool_T::SetName(const char* pName)\n{\n    const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();\n    VmaFreeString(allocs, m_Name);\n\n    if (pName != VMA_NULL)\n    {\n        m_Name = VmaCreateStringCopy(allocs, pName);\n    }\n    else\n    {\n        m_Name = VMA_NULL;\n    }\n}\n#endif // _VMA_POOL_T_FUNCTIONS\n\n#ifndef _VMA_ALLOCATOR_T_FUNCTIONS\nVmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :\n    m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0),\n    m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0),\n    m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0),\n    m_UseKhrBindMemory2((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0),\n    m_UseExtMemoryBudget((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0),\n    m_UseAmdDeviceCoherentMemory((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT) != 0),\n    m_UseKhrBufferDeviceAddress((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT) != 0),\n    m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0),\n    m_hDevice(pCreateInfo->device),\n    m_hInstance(pCreateInfo->instance),\n    m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),\n    m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ?\n        *pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks),\n    m_AllocationObjectAllocator(&m_AllocationCallbacks),\n    m_HeapSizeLimitMask(0),\n    m_DeviceMemoryCount(0),\n    m_PreferredLargeHeapBlockSize(0),\n    m_PhysicalDevice(pCreateInfo->physicalDevice),\n    m_GpuDefragmentationMemoryTypeBits(UINT32_MAX),\n    m_NextPoolId(0),\n    m_GlobalMemoryTypeBits(UINT32_MAX)\n{\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        m_UseKhrDedicatedAllocation = false;\n        m_UseKhrBindMemory2 = false;\n    }\n\n    if(VMA_DEBUG_DETECT_CORRUPTION)\n    {\n        // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it.\n        VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0);\n    }\n\n    VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device && pCreateInfo->instance);\n\n    if(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0))\n    {\n#if !(VMA_DEDICATED_ALLOCATION)\n        if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0)\n        {\n            VMA_ASSERT(0 && \"VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros.\");\n        }\n#endif\n#if !(VMA_BIND_MEMORY2)\n        if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0)\n        {\n            VMA_ASSERT(0 && \"VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros.\");\n        }\n#endif\n    }\n#if !(VMA_MEMORY_BUDGET)\n    if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)\n    {\n        VMA_ASSERT(0 && \"VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros.\");\n    }\n#endif\n#if !(VMA_BUFFER_DEVICE_ADDRESS)\n    if(m_UseKhrBufferDeviceAddress)\n    {\n        VMA_ASSERT(0 && \"VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.\");\n    }\n#endif\n#if VMA_VULKAN_VERSION < 1003000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))\n    {\n        VMA_ASSERT(0 && \"vulkanApiVersion >= VK_API_VERSION_1_3 but required Vulkan version is disabled by preprocessor macros.\");\n    }\n#endif\n#if VMA_VULKAN_VERSION < 1002000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0))\n    {\n        VMA_ASSERT(0 && \"vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros.\");\n    }\n#endif\n#if VMA_VULKAN_VERSION < 1001000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        VMA_ASSERT(0 && \"vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros.\");\n    }\n#endif\n#if !(VMA_MEMORY_PRIORITY)\n    if(m_UseExtMemoryPriority)\n    {\n        VMA_ASSERT(0 && \"VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.\");\n    }\n#endif\n\n    memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));\n    memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));\n    memset(&m_MemProps, 0, sizeof(m_MemProps));\n\n    memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));\n    memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions));\n\n#if VMA_EXTERNAL_MEMORY\n    memset(&m_TypeExternalMemoryHandleTypes, 0, sizeof(m_TypeExternalMemoryHandleTypes));\n#endif // #if VMA_EXTERNAL_MEMORY\n\n    if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL)\n    {\n        m_DeviceMemoryCallbacks.pUserData = pCreateInfo->pDeviceMemoryCallbacks->pUserData;\n        m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate;\n        m_DeviceMemoryCallbacks.pfnFree = pCreateInfo->pDeviceMemoryCallbacks->pfnFree;\n    }\n\n    ImportVulkanFunctions(pCreateInfo->pVulkanFunctions);\n\n    (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);\n    (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);\n\n    VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT));\n    VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));\n    VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity));\n    VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize));\n\n    m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ?\n        pCreateInfo->preferredLargeHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);\n\n    m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits();\n\n#if VMA_EXTERNAL_MEMORY\n    if(pCreateInfo->pTypeExternalMemoryHandleTypes != VMA_NULL)\n    {\n        memcpy(m_TypeExternalMemoryHandleTypes, pCreateInfo->pTypeExternalMemoryHandleTypes,\n            sizeof(VkExternalMemoryHandleTypeFlagsKHR) * GetMemoryTypeCount());\n    }\n#endif // #if VMA_EXTERNAL_MEMORY\n\n    if(pCreateInfo->pHeapSizeLimit != VMA_NULL)\n    {\n        for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)\n        {\n            const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex];\n            if(limit != VK_WHOLE_SIZE)\n            {\n                m_HeapSizeLimitMask |= 1u << heapIndex;\n                if(limit < m_MemProps.memoryHeaps[heapIndex].size)\n                {\n                    m_MemProps.memoryHeaps[heapIndex].size = limit;\n                }\n            }\n        }\n    }\n\n    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n    {\n        // Create only supported types\n        if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)\n        {\n            const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);\n            m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(\n                this,\n                VK_NULL_HANDLE, // hParentPool\n                memTypeIndex,\n                preferredBlockSize,\n                0,\n                SIZE_MAX,\n                GetBufferImageGranularity(),\n                false, // explicitBlockSize\n                0, // algorithm\n                0.5f, // priority (0.5 is the default per Vulkan spec)\n                GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment\n                VMA_NULL); // // pMemoryAllocateNext\n            // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,\n            // becase minBlockCount is 0.\n        }\n    }\n}\n\nVkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo)\n{\n    VkResult res = VK_SUCCESS;\n\n#if VMA_MEMORY_BUDGET\n    if(m_UseExtMemoryBudget)\n    {\n        UpdateVulkanBudget();\n    }\n#endif // #if VMA_MEMORY_BUDGET\n\n    return res;\n}\n\nVmaAllocator_T::~VmaAllocator_T()\n{\n    VMA_ASSERT(m_Pools.IsEmpty());\n\n    for(size_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; )\n    {\n        vma_delete(this, m_pBlockVectors[memTypeIndex]);\n    }\n}\n\nvoid VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions)\n{\n#if VMA_STATIC_VULKAN_FUNCTIONS == 1\n    ImportVulkanFunctions_Static();\n#endif\n\n    if(pVulkanFunctions != VMA_NULL)\n    {\n        ImportVulkanFunctions_Custom(pVulkanFunctions);\n    }\n\n#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1\n    ImportVulkanFunctions_Dynamic();\n#endif\n\n    ValidateVulkanFunctions();\n}\n\n#if VMA_STATIC_VULKAN_FUNCTIONS == 1\n\nvoid VmaAllocator_T::ImportVulkanFunctions_Static()\n{\n    // Vulkan 1.0\n    m_VulkanFunctions.vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr;\n    m_VulkanFunctions.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetDeviceProcAddr;\n    m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties;\n    m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties;\n    m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;\n    m_VulkanFunctions.vkFreeMemory = (PFN_vkFreeMemory)vkFreeMemory;\n    m_VulkanFunctions.vkMapMemory = (PFN_vkMapMemory)vkMapMemory;\n    m_VulkanFunctions.vkUnmapMemory = (PFN_vkUnmapMemory)vkUnmapMemory;\n    m_VulkanFunctions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)vkFlushMappedMemoryRanges;\n    m_VulkanFunctions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)vkInvalidateMappedMemoryRanges;\n    m_VulkanFunctions.vkBindBufferMemory = (PFN_vkBindBufferMemory)vkBindBufferMemory;\n    m_VulkanFunctions.vkBindImageMemory = (PFN_vkBindImageMemory)vkBindImageMemory;\n    m_VulkanFunctions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)vkGetBufferMemoryRequirements;\n    m_VulkanFunctions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)vkGetImageMemoryRequirements;\n    m_VulkanFunctions.vkCreateBuffer = (PFN_vkCreateBuffer)vkCreateBuffer;\n    m_VulkanFunctions.vkDestroyBuffer = (PFN_vkDestroyBuffer)vkDestroyBuffer;\n    m_VulkanFunctions.vkCreateImage = (PFN_vkCreateImage)vkCreateImage;\n    m_VulkanFunctions.vkDestroyImage = (PFN_vkDestroyImage)vkDestroyImage;\n    m_VulkanFunctions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)vkCmdCopyBuffer;\n\n    // Vulkan 1.1\n#if VMA_VULKAN_VERSION >= 1001000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2)vkGetBufferMemoryRequirements2;\n        m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2;\n        m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2;\n        m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2;\n        m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2;\n    }\n#endif\n\n#if VMA_VULKAN_VERSION >= 1003000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))\n    {\n        m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)vkGetDeviceBufferMemoryRequirements;\n        m_VulkanFunctions.vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)vkGetDeviceImageMemoryRequirements;\n    }\n#endif\n}\n\n#endif // VMA_STATIC_VULKAN_FUNCTIONS == 1\n\nvoid VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions)\n{\n    VMA_ASSERT(pVulkanFunctions != VMA_NULL);\n\n#define VMA_COPY_IF_NOT_NULL(funcName) \\\n    if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName;\n\n    VMA_COPY_IF_NOT_NULL(vkGetInstanceProcAddr);\n    VMA_COPY_IF_NOT_NULL(vkGetDeviceProcAddr);\n    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties);\n    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties);\n    VMA_COPY_IF_NOT_NULL(vkAllocateMemory);\n    VMA_COPY_IF_NOT_NULL(vkFreeMemory);\n    VMA_COPY_IF_NOT_NULL(vkMapMemory);\n    VMA_COPY_IF_NOT_NULL(vkUnmapMemory);\n    VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges);\n    VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges);\n    VMA_COPY_IF_NOT_NULL(vkBindBufferMemory);\n    VMA_COPY_IF_NOT_NULL(vkBindImageMemory);\n    VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements);\n    VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements);\n    VMA_COPY_IF_NOT_NULL(vkCreateBuffer);\n    VMA_COPY_IF_NOT_NULL(vkDestroyBuffer);\n    VMA_COPY_IF_NOT_NULL(vkCreateImage);\n    VMA_COPY_IF_NOT_NULL(vkDestroyImage);\n    VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer);\n\n#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR);\n    VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR);\n#endif\n\n#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000\n    VMA_COPY_IF_NOT_NULL(vkBindBufferMemory2KHR);\n    VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR);\n#endif\n\n#if VMA_MEMORY_BUDGET\n    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);\n#endif\n\n#if VMA_VULKAN_VERSION >= 1003000\n    VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements);\n    VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements);\n#endif\n\n#undef VMA_COPY_IF_NOT_NULL\n}\n\n#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1\n\nvoid VmaAllocator_T::ImportVulkanFunctions_Dynamic()\n{\n    VMA_ASSERT(m_VulkanFunctions.vkGetInstanceProcAddr && m_VulkanFunctions.vkGetDeviceProcAddr &&\n        \"To use VMA_DYNAMIC_VULKAN_FUNCTIONS in new versions of VMA you now have to pass \"\n        \"VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VmaAllocatorCreateInfo::pVulkanFunctions. \"\n        \"Other members can be null.\");\n\n#define VMA_FETCH_INSTANCE_FUNC(memberName, functionPointerType, functionNameString) \\\n    if(m_VulkanFunctions.memberName == VMA_NULL) \\\n        m_VulkanFunctions.memberName = \\\n            (functionPointerType)m_VulkanFunctions.vkGetInstanceProcAddr(m_hInstance, functionNameString);\n#define VMA_FETCH_DEVICE_FUNC(memberName, functionPointerType, functionNameString) \\\n    if(m_VulkanFunctions.memberName == VMA_NULL) \\\n        m_VulkanFunctions.memberName = \\\n            (functionPointerType)m_VulkanFunctions.vkGetDeviceProcAddr(m_hDevice, functionNameString);\n\n    VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties, PFN_vkGetPhysicalDeviceProperties, \"vkGetPhysicalDeviceProperties\");\n    VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties, PFN_vkGetPhysicalDeviceMemoryProperties, \"vkGetPhysicalDeviceMemoryProperties\");\n    VMA_FETCH_DEVICE_FUNC(vkAllocateMemory, PFN_vkAllocateMemory, \"vkAllocateMemory\");\n    VMA_FETCH_DEVICE_FUNC(vkFreeMemory, PFN_vkFreeMemory, \"vkFreeMemory\");\n    VMA_FETCH_DEVICE_FUNC(vkMapMemory, PFN_vkMapMemory, \"vkMapMemory\");\n    VMA_FETCH_DEVICE_FUNC(vkUnmapMemory, PFN_vkUnmapMemory, \"vkUnmapMemory\");\n    VMA_FETCH_DEVICE_FUNC(vkFlushMappedMemoryRanges, PFN_vkFlushMappedMemoryRanges, \"vkFlushMappedMemoryRanges\");\n    VMA_FETCH_DEVICE_FUNC(vkInvalidateMappedMemoryRanges, PFN_vkInvalidateMappedMemoryRanges, \"vkInvalidateMappedMemoryRanges\");\n    VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory, PFN_vkBindBufferMemory, \"vkBindBufferMemory\");\n    VMA_FETCH_DEVICE_FUNC(vkBindImageMemory, PFN_vkBindImageMemory, \"vkBindImageMemory\");\n    VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements, PFN_vkGetBufferMemoryRequirements, \"vkGetBufferMemoryRequirements\");\n    VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements, PFN_vkGetImageMemoryRequirements, \"vkGetImageMemoryRequirements\");\n    VMA_FETCH_DEVICE_FUNC(vkCreateBuffer, PFN_vkCreateBuffer, \"vkCreateBuffer\");\n    VMA_FETCH_DEVICE_FUNC(vkDestroyBuffer, PFN_vkDestroyBuffer, \"vkDestroyBuffer\");\n    VMA_FETCH_DEVICE_FUNC(vkCreateImage, PFN_vkCreateImage, \"vkCreateImage\");\n    VMA_FETCH_DEVICE_FUNC(vkDestroyImage, PFN_vkDestroyImage, \"vkDestroyImage\");\n    VMA_FETCH_DEVICE_FUNC(vkCmdCopyBuffer, PFN_vkCmdCopyBuffer, \"vkCmdCopyBuffer\");\n\n#if VMA_VULKAN_VERSION >= 1001000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2, \"vkGetBufferMemoryRequirements2\");\n        VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2, \"vkGetImageMemoryRequirements2\");\n        VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2, \"vkBindBufferMemory2\");\n        VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2, \"vkBindImageMemory2\");\n        VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2, \"vkGetPhysicalDeviceMemoryProperties2\");\n    }\n#endif\n\n#if VMA_DEDICATED_ALLOCATION\n    if(m_UseKhrDedicatedAllocation)\n    {\n        VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2KHR, \"vkGetBufferMemoryRequirements2KHR\");\n        VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2KHR, \"vkGetImageMemoryRequirements2KHR\");\n    }\n#endif\n\n#if VMA_BIND_MEMORY2\n    if(m_UseKhrBindMemory2)\n    {\n        VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2KHR, \"vkBindBufferMemory2KHR\");\n        VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2KHR, \"vkBindImageMemory2KHR\");\n    }\n#endif // #if VMA_BIND_MEMORY2\n\n#if VMA_MEMORY_BUDGET\n    if(m_UseExtMemoryBudget)\n    {\n        VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, \"vkGetPhysicalDeviceMemoryProperties2KHR\");\n    }\n#endif // #if VMA_MEMORY_BUDGET\n\n#if VMA_VULKAN_VERSION >= 1003000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))\n    {\n        VMA_FETCH_DEVICE_FUNC(vkGetDeviceBufferMemoryRequirements, PFN_vkGetDeviceBufferMemoryRequirements, \"vkGetDeviceBufferMemoryRequirements\");\n        VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirements, \"vkGetDeviceImageMemoryRequirements\");\n    }\n#endif\n\n#undef VMA_FETCH_DEVICE_FUNC\n#undef VMA_FETCH_INSTANCE_FUNC\n}\n\n#endif // VMA_DYNAMIC_VULKAN_FUNCTIONS == 1\n\nvoid VmaAllocator_T::ValidateVulkanFunctions()\n{\n    VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkCreateBuffer != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL);\n    VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL);\n\n#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation)\n    {\n        VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL);\n        VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL);\n    }\n#endif\n\n#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2)\n    {\n        VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL);\n        VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL);\n    }\n#endif\n\n#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000\n    if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);\n    }\n#endif\n\n#if VMA_VULKAN_VERSION >= 1003000\n    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))\n    {\n        VMA_ASSERT(m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements != VMA_NULL);\n        VMA_ASSERT(m_VulkanFunctions.vkGetDeviceImageMemoryRequirements != VMA_NULL);\n    }\n#endif\n}\n\nVkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)\n{\n    const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);\n    const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;\n    const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE;\n    return VmaAlignUp(isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize, (VkDeviceSize)32);\n}\n\nVkResult VmaAllocator_T::AllocateMemoryOfType(\n    VmaPool pool,\n    VkDeviceSize size,\n    VkDeviceSize alignment,\n    bool dedicatedPreferred,\n    VkBuffer dedicatedBuffer,\n    VkImage dedicatedImage,\n    VkFlags dedicatedBufferImageUsage,\n    const VmaAllocationCreateInfo& createInfo,\n    uint32_t memTypeIndex,\n    VmaSuballocationType suballocType,\n    VmaDedicatedAllocationList& dedicatedAllocations,\n    VmaBlockVector& blockVector,\n    size_t allocationCount,\n    VmaAllocation* pAllocations)\n{\n    VMA_ASSERT(pAllocations != VMA_NULL);\n    VMA_DEBUG_LOG(\"  AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu\", memTypeIndex, allocationCount, size);\n\n    VmaAllocationCreateInfo finalCreateInfo = createInfo;\n    VkResult res = CalcMemTypeParams(\n        finalCreateInfo,\n        memTypeIndex,\n        size,\n        allocationCount);\n    if(res != VK_SUCCESS)\n        return res;\n\n    if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)\n    {\n        return AllocateDedicatedMemory(\n            pool,\n            size,\n            suballocType,\n            dedicatedAllocations,\n            memTypeIndex,\n            (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,\n            (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,\n            (finalCreateInfo.flags &\n                (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0,\n            (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,\n            finalCreateInfo.pUserData,\n            finalCreateInfo.priority,\n            dedicatedBuffer,\n            dedicatedImage,\n            dedicatedBufferImageUsage,\n            allocationCount,\n            pAllocations,\n            blockVector.GetAllocationNextPtr());\n    }\n    else\n    {\n        const bool canAllocateDedicated =\n            (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&\n            (pool == VK_NULL_HANDLE || !blockVector.HasExplicitBlockSize());\n\n        if(canAllocateDedicated)\n        {\n            // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.\n            if(size > blockVector.GetPreferredBlockSize() / 2)\n            {\n                dedicatedPreferred = true;\n            }\n            // Protection against creating each allocation as dedicated when we reach or exceed heap size/budget,\n            // which can quickly deplete maxMemoryAllocationCount: Don't prefer dedicated allocations when above\n            // 3/4 of the maximum allocation count.\n            if(m_DeviceMemoryCount.load() > m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount * 3 / 4)\n            {\n                dedicatedPreferred = false;\n            }\n\n            if(dedicatedPreferred)\n            {\n                res = AllocateDedicatedMemory(\n                    pool,\n                    size,\n                    suballocType,\n                    dedicatedAllocations,\n                    memTypeIndex,\n                    (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,\n                    (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,\n                    (finalCreateInfo.flags &\n                        (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0,\n                    (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,\n                    finalCreateInfo.pUserData,\n                    finalCreateInfo.priority,\n                    dedicatedBuffer,\n                    dedicatedImage,\n                    dedicatedBufferImageUsage,\n                    allocationCount,\n                    pAllocations,\n                    blockVector.GetAllocationNextPtr());\n                if(res == VK_SUCCESS)\n                {\n                    // Succeeded: AllocateDedicatedMemory function already filled pMemory, nothing more to do here.\n                    VMA_DEBUG_LOG(\"    Allocated as DedicatedMemory\");\n                    return VK_SUCCESS;\n                }\n            }\n        }\n\n        res = blockVector.Allocate(\n            size,\n            alignment,\n            finalCreateInfo,\n            suballocType,\n            allocationCount,\n            pAllocations);\n        if(res == VK_SUCCESS)\n            return VK_SUCCESS;\n\n        // Try dedicated memory.\n        if(canAllocateDedicated && !dedicatedPreferred)\n        {\n            res = AllocateDedicatedMemory(\n                pool,\n                size,\n                suballocType,\n                dedicatedAllocations,\n                memTypeIndex,\n                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,\n                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,\n                (finalCreateInfo.flags &\n                    (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0,\n                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,\n                finalCreateInfo.pUserData,\n                finalCreateInfo.priority,\n                dedicatedBuffer,\n                dedicatedImage,\n                dedicatedBufferImageUsage,\n                allocationCount,\n                pAllocations,\n                blockVector.GetAllocationNextPtr());\n            if(res == VK_SUCCESS)\n            {\n                // Succeeded: AllocateDedicatedMemory function already filled pMemory, nothing more to do here.\n                VMA_DEBUG_LOG(\"    Allocated as DedicatedMemory\");\n                return VK_SUCCESS;\n            }\n        }\n        // Everything failed: Return error code.\n        VMA_DEBUG_LOG(\"    vkAllocateMemory FAILED\");\n        return res;\n    }\n}\n\nVkResult VmaAllocator_T::AllocateDedicatedMemory(\n    VmaPool pool,\n    VkDeviceSize size,\n    VmaSuballocationType suballocType,\n    VmaDedicatedAllocationList& dedicatedAllocations,\n    uint32_t memTypeIndex,\n    bool map,\n    bool isUserDataString,\n    bool isMappingAllowed,\n    bool canAliasMemory,\n    void* pUserData,\n    float priority,\n    VkBuffer dedicatedBuffer,\n    VkImage dedicatedImage,\n    VkFlags dedicatedBufferImageUsage,\n    size_t allocationCount,\n    VmaAllocation* pAllocations,\n    const void* pNextChain)\n{\n    VMA_ASSERT(allocationCount > 0 && pAllocations);\n\n    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };\n    allocInfo.memoryTypeIndex = memTypeIndex;\n    allocInfo.allocationSize = size;\n    allocInfo.pNext = pNextChain;\n\n#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };\n    if(!canAliasMemory)\n    {\n        if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n        {\n            if(dedicatedBuffer != VK_NULL_HANDLE)\n            {\n                VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);\n                dedicatedAllocInfo.buffer = dedicatedBuffer;\n                VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);\n            }\n            else if(dedicatedImage != VK_NULL_HANDLE)\n            {\n                dedicatedAllocInfo.image = dedicatedImage;\n                VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);\n            }\n        }\n    }\n#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n\n#if VMA_BUFFER_DEVICE_ADDRESS\n    VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };\n    if(m_UseKhrBufferDeviceAddress)\n    {\n        bool canContainBufferWithDeviceAddress = true;\n        if(dedicatedBuffer != VK_NULL_HANDLE)\n        {\n            canContainBufferWithDeviceAddress = dedicatedBufferImageUsage == UINT32_MAX || // Usage flags unknown\n                (dedicatedBufferImageUsage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) != 0;\n        }\n        else if(dedicatedImage != VK_NULL_HANDLE)\n        {\n            canContainBufferWithDeviceAddress = false;\n        }\n        if(canContainBufferWithDeviceAddress)\n        {\n            allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;\n            VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo);\n        }\n    }\n#endif // #if VMA_BUFFER_DEVICE_ADDRESS\n\n#if VMA_MEMORY_PRIORITY\n    VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT };\n    if(m_UseExtMemoryPriority)\n    {\n        VMA_ASSERT(priority >= 0.f && priority <= 1.f);\n        priorityInfo.priority = priority;\n        VmaPnextChainPushFront(&allocInfo, &priorityInfo);\n    }\n#endif // #if VMA_MEMORY_PRIORITY\n\n#if VMA_EXTERNAL_MEMORY\n    // Attach VkExportMemoryAllocateInfoKHR if necessary.\n    VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR };\n    exportMemoryAllocInfo.handleTypes = GetExternalMemoryHandleTypeFlags(memTypeIndex);\n    if(exportMemoryAllocInfo.handleTypes != 0)\n    {\n        VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo);\n    }\n#endif // #if VMA_EXTERNAL_MEMORY\n\n    size_t allocIndex;\n    VkResult res = VK_SUCCESS;\n    for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)\n    {\n        res = AllocateDedicatedMemoryPage(\n            pool,\n            size,\n            suballocType,\n            memTypeIndex,\n            allocInfo,\n            map,\n            isUserDataString,\n            isMappingAllowed,\n            pUserData,\n            pAllocations + allocIndex);\n        if(res != VK_SUCCESS)\n        {\n            break;\n        }\n    }\n\n    if(res == VK_SUCCESS)\n    {\n        for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex)\n        {\n            dedicatedAllocations.Register(pAllocations[allocIndex]);\n        }\n        VMA_DEBUG_LOG(\"    Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u\", allocationCount, memTypeIndex);\n    }\n    else\n    {\n        // Free all already created allocations.\n        while(allocIndex--)\n        {\n            VmaAllocation currAlloc = pAllocations[allocIndex];\n            VkDeviceMemory hMemory = currAlloc->GetMemory();\n\n            /*\n            There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory\n            before vkFreeMemory.\n\n            if(currAlloc->GetMappedData() != VMA_NULL)\n            {\n                (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);\n            }\n            */\n\n            FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory);\n            m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc->GetSize());\n            m_AllocationObjectAllocator.Free(currAlloc);\n        }\n\n        memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);\n    }\n\n    return res;\n}\n\nVkResult VmaAllocator_T::AllocateDedicatedMemoryPage(\n    VmaPool pool,\n    VkDeviceSize size,\n    VmaSuballocationType suballocType,\n    uint32_t memTypeIndex,\n    const VkMemoryAllocateInfo& allocInfo,\n    bool map,\n    bool isUserDataString,\n    bool isMappingAllowed,\n    void* pUserData,\n    VmaAllocation* pAllocation)\n{\n    VkDeviceMemory hMemory = VK_NULL_HANDLE;\n    VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory);\n    if(res < 0)\n    {\n        VMA_DEBUG_LOG(\"    vkAllocateMemory FAILED\");\n        return res;\n    }\n\n    void* pMappedData = VMA_NULL;\n    if(map)\n    {\n        res = (*m_VulkanFunctions.vkMapMemory)(\n            m_hDevice,\n            hMemory,\n            0,\n            VK_WHOLE_SIZE,\n            0,\n            &pMappedData);\n        if(res < 0)\n        {\n            VMA_DEBUG_LOG(\"    vkMapMemory FAILED\");\n            FreeVulkanMemory(memTypeIndex, size, hMemory);\n            return res;\n        }\n    }\n\n    *pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);\n    (*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size);\n    if (isUserDataString)\n        (*pAllocation)->SetName(this, (const char*)pUserData);\n    else\n        (*pAllocation)->SetUserData(this, pUserData);\n    m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size);\n    if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)\n    {\n        FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);\n    }\n\n    return VK_SUCCESS;\n}\n\nvoid VmaAllocator_T::GetBufferMemoryRequirements(\n    VkBuffer hBuffer,\n    VkMemoryRequirements& memReq,\n    bool& requiresDedicatedAllocation,\n    bool& prefersDedicatedAllocation) const\n{\n#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };\n        memReqInfo.buffer = hBuffer;\n\n        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };\n\n        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };\n        VmaPnextChainPushFront(&memReq2, &memDedicatedReq);\n\n        (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);\n\n        memReq = memReq2.memoryRequirements;\n        requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);\n        prefersDedicatedAllocation  = (memDedicatedReq.prefersDedicatedAllocation  != VK_FALSE);\n    }\n    else\n#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    {\n        (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq);\n        requiresDedicatedAllocation = false;\n        prefersDedicatedAllocation  = false;\n    }\n}\n\nvoid VmaAllocator_T::GetImageMemoryRequirements(\n    VkImage hImage,\n    VkMemoryRequirements& memReq,\n    bool& requiresDedicatedAllocation,\n    bool& prefersDedicatedAllocation) const\n{\n#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))\n    {\n        VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };\n        memReqInfo.image = hImage;\n\n        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };\n\n        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };\n        VmaPnextChainPushFront(&memReq2, &memDedicatedReq);\n\n        (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);\n\n        memReq = memReq2.memoryRequirements;\n        requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);\n        prefersDedicatedAllocation  = (memDedicatedReq.prefersDedicatedAllocation  != VK_FALSE);\n    }\n    else\n#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000\n    {\n        (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq);\n        requiresDedicatedAllocation = false;\n        prefersDedicatedAllocation  = false;\n    }\n}\n\nVkResult VmaAllocator_T::FindMemoryTypeIndex(\n    uint32_t memoryTypeBits,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    VkFlags bufImgUsage,\n    uint32_t* pMemoryTypeIndex) const\n{\n    memoryTypeBits &= GetGlobalMemoryTypeBits();\n\n    if(pAllocationCreateInfo->memoryTypeBits != 0)\n    {\n        memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits;\n    }\n\n    VkMemoryPropertyFlags requiredFlags = 0, preferredFlags = 0, notPreferredFlags = 0;\n    if(!FindMemoryPreferences(\n        IsIntegratedGpu(),\n        *pAllocationCreateInfo,\n        bufImgUsage,\n        requiredFlags, preferredFlags, notPreferredFlags))\n    {\n        return VK_ERROR_FEATURE_NOT_PRESENT;\n    }\n\n    *pMemoryTypeIndex = UINT32_MAX;\n    uint32_t minCost = UINT32_MAX;\n    for(uint32_t memTypeIndex = 0, memTypeBit = 1;\n        memTypeIndex < GetMemoryTypeCount();\n        ++memTypeIndex, memTypeBit <<= 1)\n    {\n        // This memory type is acceptable according to memoryTypeBits bitmask.\n        if((memTypeBit & memoryTypeBits) != 0)\n        {\n            const VkMemoryPropertyFlags currFlags =\n                m_MemProps.memoryTypes[memTypeIndex].propertyFlags;\n            // This memory type contains requiredFlags.\n            if((requiredFlags & ~currFlags) == 0)\n            {\n                // Calculate cost as number of bits from preferredFlags not present in this memory type.\n                uint32_t currCost = VMA_COUNT_BITS_SET(preferredFlags & ~currFlags) +\n                    VMA_COUNT_BITS_SET(currFlags & notPreferredFlags);\n                // Remember memory type with lowest cost.\n                if(currCost < minCost)\n                {\n                    *pMemoryTypeIndex = memTypeIndex;\n                    if(currCost == 0)\n                    {\n                        return VK_SUCCESS;\n                    }\n                    minCost = currCost;\n                }\n            }\n        }\n    }\n    return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;\n}\n\nVkResult VmaAllocator_T::CalcMemTypeParams(\n    VmaAllocationCreateInfo& inoutCreateInfo,\n    uint32_t memTypeIndex,\n    VkDeviceSize size,\n    size_t allocationCount)\n{\n    // If memory type is not HOST_VISIBLE, disable MAPPED.\n    if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&\n        (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)\n    {\n        inoutCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;\n    }\n\n    if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&\n        (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0)\n    {\n        const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);\n        VmaBudget heapBudget = {};\n        GetHeapBudgets(&heapBudget, heapIndex, 1);\n        if(heapBudget.usage + size * allocationCount > heapBudget.budget)\n        {\n            return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n        }\n    }\n    return VK_SUCCESS;\n}\n\nVkResult VmaAllocator_T::CalcAllocationParams(\n    VmaAllocationCreateInfo& inoutCreateInfo,\n    bool dedicatedRequired,\n    bool dedicatedPreferred)\n{\n    VMA_ASSERT((inoutCreateInfo.flags &\n        (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) !=\n        (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) &&\n        \"Specifying both flags VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT and VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT is incorrect.\");\n    VMA_ASSERT((((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) == 0 ||\n        (inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0)) &&\n        \"Specifying VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT requires also VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.\");\n    if(inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST)\n    {\n        if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0)\n        {\n            VMA_ASSERT((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0 &&\n                \"When using VMA_ALLOCATION_CREATE_MAPPED_BIT and usage = VMA_MEMORY_USAGE_AUTO*, you must also specify VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.\");\n        }\n    }\n\n    // If memory is lazily allocated, it should be always dedicated.\n    if(dedicatedRequired ||\n        inoutCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED)\n    {\n        inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;\n    }\n\n    if(inoutCreateInfo.pool != VK_NULL_HANDLE)\n    {\n        if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() &&\n            (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)\n        {\n            VMA_ASSERT(0 && \"Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations.\");\n            return VK_ERROR_FEATURE_NOT_PRESENT;\n        }\n        inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority();\n    }\n\n    if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&\n        (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)\n    {\n        VMA_ASSERT(0 && \"Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.\");\n        return VK_ERROR_FEATURE_NOT_PRESENT;\n    }\n\n    if(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY &&\n        (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)\n    {\n        inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;\n    }\n\n    // Non-auto USAGE values imply HOST_ACCESS flags.\n    // And so does VMA_MEMORY_USAGE_UNKNOWN because it is used with custom pools.\n    // Which specific flag is used doesn't matter. They change things only when used with VMA_MEMORY_USAGE_AUTO*.\n    // Otherwise they just protect from assert on mapping.\n    if(inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO &&\n        inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE &&\n        inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_HOST)\n    {\n        if((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) == 0)\n        {\n            inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;\n        }\n    }\n\n    return VK_SUCCESS;\n}\n\nVkResult VmaAllocator_T::AllocateMemory(\n    const VkMemoryRequirements& vkMemReq,\n    bool requiresDedicatedAllocation,\n    bool prefersDedicatedAllocation,\n    VkBuffer dedicatedBuffer,\n    VkImage dedicatedImage,\n    VkFlags dedicatedBufferImageUsage,\n    const VmaAllocationCreateInfo& createInfo,\n    VmaSuballocationType suballocType,\n    size_t allocationCount,\n    VmaAllocation* pAllocations)\n{\n    memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);\n\n    VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));\n\n    if(vkMemReq.size == 0)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n\n    VmaAllocationCreateInfo createInfoFinal = createInfo;\n    VkResult res = CalcAllocationParams(createInfoFinal, requiresDedicatedAllocation, prefersDedicatedAllocation);\n    if(res != VK_SUCCESS)\n        return res;\n\n    if(createInfoFinal.pool != VK_NULL_HANDLE)\n    {\n        VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector;\n        return AllocateMemoryOfType(\n            createInfoFinal.pool,\n            vkMemReq.size,\n            vkMemReq.alignment,\n            prefersDedicatedAllocation,\n            dedicatedBuffer,\n            dedicatedImage,\n            dedicatedBufferImageUsage,\n            createInfoFinal,\n            blockVector.GetMemoryTypeIndex(),\n            suballocType,\n            createInfoFinal.pool->m_DedicatedAllocations,\n            blockVector,\n            allocationCount,\n            pAllocations);\n    }\n    else\n    {\n        // Bit mask of memory Vulkan types acceptable for this allocation.\n        uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;\n        uint32_t memTypeIndex = UINT32_MAX;\n        res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex);\n        // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.\n        if(res != VK_SUCCESS)\n            return res;\n        do\n        {\n            VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex];\n            VMA_ASSERT(blockVector && \"Trying to use unsupported memory type!\");\n            res = AllocateMemoryOfType(\n                VK_NULL_HANDLE,\n                vkMemReq.size,\n                vkMemReq.alignment,\n                requiresDedicatedAllocation || prefersDedicatedAllocation,\n                dedicatedBuffer,\n                dedicatedImage,\n                dedicatedBufferImageUsage,\n                createInfoFinal,\n                memTypeIndex,\n                suballocType,\n                m_DedicatedAllocations[memTypeIndex],\n                *blockVector,\n                allocationCount,\n                pAllocations);\n            // Allocation succeeded\n            if(res == VK_SUCCESS)\n                return VK_SUCCESS;\n\n            // Remove old memTypeIndex from list of possibilities.\n            memoryTypeBits &= ~(1u << memTypeIndex);\n            // Find alternative memTypeIndex.\n            res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex);\n        } while(res == VK_SUCCESS);\n\n        // No other matching memory type index could be found.\n        // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.\n        return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n    }\n}\n\nvoid VmaAllocator_T::FreeMemory(\n    size_t allocationCount,\n    const VmaAllocation* pAllocations)\n{\n    VMA_ASSERT(pAllocations);\n\n    for(size_t allocIndex = allocationCount; allocIndex--; )\n    {\n        VmaAllocation allocation = pAllocations[allocIndex];\n\n        if(allocation != VK_NULL_HANDLE)\n        {\n            if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)\n            {\n                FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);\n            }\n\n            allocation->FreeName(this);\n\n            switch(allocation->GetType())\n            {\n            case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:\n                {\n                    VmaBlockVector* pBlockVector = VMA_NULL;\n                    VmaPool hPool = allocation->GetParentPool();\n                    if(hPool != VK_NULL_HANDLE)\n                    {\n                        pBlockVector = &hPool->m_BlockVector;\n                    }\n                    else\n                    {\n                        const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();\n                        pBlockVector = m_pBlockVectors[memTypeIndex];\n                        VMA_ASSERT(pBlockVector && \"Trying to free memory of unsupported type!\");\n                    }\n                    pBlockVector->Free(allocation);\n                }\n                break;\n            case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:\n                FreeDedicatedMemory(allocation);\n                break;\n            default:\n                VMA_ASSERT(0);\n            }\n        }\n    }\n}\n\nvoid VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats)\n{\n    // Initialize.\n    VmaClearDetailedStatistics(pStats->total);\n    for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)\n        VmaClearDetailedStatistics(pStats->memoryType[i]);\n    for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)\n        VmaClearDetailedStatistics(pStats->memoryHeap[i]);\n\n    // Process default pools.\n    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n    {\n        VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];\n        if (pBlockVector != VMA_NULL)\n            pBlockVector->AddDetailedStatistics(pStats->memoryType[memTypeIndex]);\n    }\n\n    // Process custom pools.\n    {\n        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);\n        for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))\n        {\n            VmaBlockVector& blockVector = pool->m_BlockVector;\n            const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex();\n            blockVector.AddDetailedStatistics(pStats->memoryType[memTypeIndex]);\n            pool->m_DedicatedAllocations.AddDetailedStatistics(pStats->memoryType[memTypeIndex]);\n        }\n    }\n\n    // Process dedicated allocations.\n    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n    {\n        m_DedicatedAllocations[memTypeIndex].AddDetailedStatistics(pStats->memoryType[memTypeIndex]);\n    }\n\n    // Sum from memory types to memory heaps.\n    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n    {\n        const uint32_t memHeapIndex = m_MemProps.memoryTypes[memTypeIndex].heapIndex;\n        VmaAddDetailedStatistics(pStats->memoryHeap[memHeapIndex], pStats->memoryType[memTypeIndex]);\n    }\n\n    // Sum from memory heaps to total.\n    for(uint32_t memHeapIndex = 0; memHeapIndex < GetMemoryHeapCount(); ++memHeapIndex)\n        VmaAddDetailedStatistics(pStats->total, pStats->memoryHeap[memHeapIndex]);\n\n    VMA_ASSERT(pStats->total.statistics.allocationCount == 0 ||\n        pStats->total.allocationSizeMax >= pStats->total.allocationSizeMin);\n    VMA_ASSERT(pStats->total.unusedRangeCount == 0 ||\n        pStats->total.unusedRangeSizeMax >= pStats->total.unusedRangeSizeMin);\n}\n\nvoid VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount)\n{\n#if VMA_MEMORY_BUDGET\n    if(m_UseExtMemoryBudget)\n    {\n        if(m_Budget.m_OperationsSinceBudgetFetch < 30)\n        {\n            VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex);\n            for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets)\n            {\n                const uint32_t heapIndex = firstHeap + i;\n\n                outBudgets->statistics.blockCount = m_Budget.m_BlockCount[heapIndex];\n                outBudgets->statistics.allocationCount = m_Budget.m_AllocationCount[heapIndex];\n                outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex];\n                outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex];\n\n                if(m_Budget.m_VulkanUsage[heapIndex] + outBudgets->statistics.blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex])\n                {\n                    outBudgets->usage = m_Budget.m_VulkanUsage[heapIndex] +\n                        outBudgets->statistics.blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];\n                }\n                else\n                {\n                    outBudgets->usage = 0;\n                }\n\n                // Have to take MIN with heap size because explicit HeapSizeLimit is included in it.\n                outBudgets->budget = VMA_MIN(\n                    m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size);\n            }\n        }\n        else\n        {\n            UpdateVulkanBudget(); // Outside of mutex lock\n            GetHeapBudgets(outBudgets, firstHeap, heapCount); // Recursion\n        }\n    }\n    else\n#endif\n    {\n        for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets)\n        {\n            const uint32_t heapIndex = firstHeap + i;\n\n            outBudgets->statistics.blockCount = m_Budget.m_BlockCount[heapIndex];\n            outBudgets->statistics.allocationCount = m_Budget.m_AllocationCount[heapIndex];\n            outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex];\n            outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex];\n\n            outBudgets->usage = outBudgets->statistics.blockBytes;\n            outBudgets->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.\n        }\n    }\n}\n\nvoid VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo)\n{\n    pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();\n    pAllocationInfo->deviceMemory = hAllocation->GetMemory();\n    pAllocationInfo->offset = hAllocation->GetOffset();\n    pAllocationInfo->size = hAllocation->GetSize();\n    pAllocationInfo->pMappedData = hAllocation->GetMappedData();\n    pAllocationInfo->pUserData = hAllocation->GetUserData();\n    pAllocationInfo->pName = hAllocation->GetName();\n}\n\nVkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool)\n{\n    VMA_DEBUG_LOG(\"  CreatePool: MemoryTypeIndex=%u, flags=%u\", pCreateInfo->memoryTypeIndex, pCreateInfo->flags);\n\n    VmaPoolCreateInfo newCreateInfo = *pCreateInfo;\n\n    // Protection against uninitialized new structure member. If garbage data are left there, this pointer dereference would crash.\n    if(pCreateInfo->pMemoryAllocateNext)\n    {\n        VMA_ASSERT(((const VkBaseInStructure*)pCreateInfo->pMemoryAllocateNext)->sType != 0);\n    }\n\n    if(newCreateInfo.maxBlockCount == 0)\n    {\n        newCreateInfo.maxBlockCount = SIZE_MAX;\n    }\n    if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n    // Memory type index out of range or forbidden.\n    if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() ||\n        ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0)\n    {\n        return VK_ERROR_FEATURE_NOT_PRESENT;\n    }\n    if(newCreateInfo.minAllocationAlignment > 0)\n    {\n        VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment));\n    }\n\n    const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex);\n\n    *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize);\n\n    VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks();\n    if(res != VK_SUCCESS)\n    {\n        vma_delete(this, *pPool);\n        *pPool = VMA_NULL;\n        return res;\n    }\n\n    // Add to m_Pools.\n    {\n        VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);\n        (*pPool)->SetId(m_NextPoolId++);\n        m_Pools.PushBack(*pPool);\n    }\n\n    return VK_SUCCESS;\n}\n\nvoid VmaAllocator_T::DestroyPool(VmaPool pool)\n{\n    // Remove from m_Pools.\n    {\n        VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);\n        m_Pools.Remove(pool);\n    }\n\n    vma_delete(this, pool);\n}\n\nvoid VmaAllocator_T::GetPoolStatistics(VmaPool pool, VmaStatistics* pPoolStats)\n{\n    VmaClearStatistics(*pPoolStats);\n    pool->m_BlockVector.AddStatistics(*pPoolStats);\n    pool->m_DedicatedAllocations.AddStatistics(*pPoolStats);\n}\n\nvoid VmaAllocator_T::CalculatePoolStatistics(VmaPool pool, VmaDetailedStatistics* pPoolStats)\n{\n    VmaClearDetailedStatistics(*pPoolStats);\n    pool->m_BlockVector.AddDetailedStatistics(*pPoolStats);\n    pool->m_DedicatedAllocations.AddDetailedStatistics(*pPoolStats);\n}\n\nvoid VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)\n{\n    m_CurrentFrameIndex.store(frameIndex);\n\n#if VMA_MEMORY_BUDGET\n    if(m_UseExtMemoryBudget)\n    {\n        UpdateVulkanBudget();\n    }\n#endif // #if VMA_MEMORY_BUDGET\n}\n\nVkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)\n{\n    return hPool->m_BlockVector.CheckCorruption();\n}\n\nVkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)\n{\n    VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT;\n\n    // Process default pools.\n    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n    {\n        VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];\n        if(pBlockVector != VMA_NULL)\n        {\n            VkResult localRes = pBlockVector->CheckCorruption();\n            switch(localRes)\n            {\n            case VK_ERROR_FEATURE_NOT_PRESENT:\n                break;\n            case VK_SUCCESS:\n                finalRes = VK_SUCCESS;\n                break;\n            default:\n                return localRes;\n            }\n        }\n    }\n\n    // Process custom pools.\n    {\n        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);\n        for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))\n        {\n            if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0)\n            {\n                VkResult localRes = pool->m_BlockVector.CheckCorruption();\n                switch(localRes)\n                {\n                case VK_ERROR_FEATURE_NOT_PRESENT:\n                    break;\n                case VK_SUCCESS:\n                    finalRes = VK_SUCCESS;\n                    break;\n                default:\n                    return localRes;\n                }\n            }\n        }\n    }\n\n    return finalRes;\n}\n\nVkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)\n{\n    AtomicTransactionalIncrement<uint32_t> deviceMemoryCountIncrement;\n    const uint64_t prevDeviceMemoryCount = deviceMemoryCountIncrement.Increment(&m_DeviceMemoryCount);\n#if VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT\n    if(prevDeviceMemoryCount >= m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount)\n    {\n        return VK_ERROR_TOO_MANY_OBJECTS;\n    }\n#endif\n\n    const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex);\n\n    // HeapSizeLimit is in effect for this heap.\n    if((m_HeapSizeLimitMask & (1u << heapIndex)) != 0)\n    {\n        const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;\n        VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex];\n        for(;;)\n        {\n            const VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo->allocationSize;\n            if(blockBytesAfterAllocation > heapSize)\n            {\n                return VK_ERROR_OUT_OF_DEVICE_MEMORY;\n            }\n            if(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation))\n            {\n                break;\n            }\n        }\n    }\n    else\n    {\n        m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo->allocationSize;\n    }\n    ++m_Budget.m_BlockCount[heapIndex];\n\n    // VULKAN CALL vkAllocateMemory.\n    VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);\n\n    if(res == VK_SUCCESS)\n    {\n#if VMA_MEMORY_BUDGET\n        ++m_Budget.m_OperationsSinceBudgetFetch;\n#endif\n\n        // Informative callback.\n        if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)\n        {\n            (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize, m_DeviceMemoryCallbacks.pUserData);\n        }\n\n        deviceMemoryCountIncrement.Commit();\n    }\n    else\n    {\n        --m_Budget.m_BlockCount[heapIndex];\n        m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo->allocationSize;\n    }\n\n    return res;\n}\n\nvoid VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory)\n{\n    // Informative callback.\n    if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)\n    {\n        (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size, m_DeviceMemoryCallbacks.pUserData);\n    }\n\n    // VULKAN CALL vkFreeMemory.\n    (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks());\n\n    const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memoryType);\n    --m_Budget.m_BlockCount[heapIndex];\n    m_Budget.m_BlockBytes[heapIndex] -= size;\n\n    --m_DeviceMemoryCount;\n}\n\nVkResult VmaAllocator_T::BindVulkanBuffer(\n    VkDeviceMemory memory,\n    VkDeviceSize memoryOffset,\n    VkBuffer buffer,\n    const void* pNext)\n{\n    if(pNext != VMA_NULL)\n    {\n#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2\n        if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) &&\n            m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL)\n        {\n            VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR };\n            bindBufferMemoryInfo.pNext = pNext;\n            bindBufferMemoryInfo.buffer = buffer;\n            bindBufferMemoryInfo.memory = memory;\n            bindBufferMemoryInfo.memoryOffset = memoryOffset;\n            return (*m_VulkanFunctions.vkBindBufferMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo);\n        }\n        else\n#endif // #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2\n        {\n            return VK_ERROR_EXTENSION_NOT_PRESENT;\n        }\n    }\n    else\n    {\n        return (*m_VulkanFunctions.vkBindBufferMemory)(m_hDevice, buffer, memory, memoryOffset);\n    }\n}\n\nVkResult VmaAllocator_T::BindVulkanImage(\n    VkDeviceMemory memory,\n    VkDeviceSize memoryOffset,\n    VkImage image,\n    const void* pNext)\n{\n    if(pNext != VMA_NULL)\n    {\n#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2\n        if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) &&\n            m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL)\n        {\n            VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR };\n            bindBufferMemoryInfo.pNext = pNext;\n            bindBufferMemoryInfo.image = image;\n            bindBufferMemoryInfo.memory = memory;\n            bindBufferMemoryInfo.memoryOffset = memoryOffset;\n            return (*m_VulkanFunctions.vkBindImageMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo);\n        }\n        else\n#endif // #if VMA_BIND_MEMORY2\n        {\n            return VK_ERROR_EXTENSION_NOT_PRESENT;\n        }\n    }\n    else\n    {\n        return (*m_VulkanFunctions.vkBindImageMemory)(m_hDevice, image, memory, memoryOffset);\n    }\n}\n\nVkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)\n{\n    switch(hAllocation->GetType())\n    {\n    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:\n        {\n            VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();\n            char *pBytes = VMA_NULL;\n            VkResult res = pBlock->Map(this, 1, (void**)&pBytes);\n            if(res == VK_SUCCESS)\n            {\n                *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset();\n                hAllocation->BlockAllocMap();\n            }\n            return res;\n        }\n    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:\n        return hAllocation->DedicatedAllocMap(this, ppData);\n    default:\n        VMA_ASSERT(0);\n        return VK_ERROR_MEMORY_MAP_FAILED;\n    }\n}\n\nvoid VmaAllocator_T::Unmap(VmaAllocation hAllocation)\n{\n    switch(hAllocation->GetType())\n    {\n    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:\n        {\n            VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();\n            hAllocation->BlockAllocUnmap();\n            pBlock->Unmap(this, 1);\n        }\n        break;\n    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:\n        hAllocation->DedicatedAllocUnmap(this);\n        break;\n    default:\n        VMA_ASSERT(0);\n    }\n}\n\nVkResult VmaAllocator_T::BindBufferMemory(\n    VmaAllocation hAllocation,\n    VkDeviceSize allocationLocalOffset,\n    VkBuffer hBuffer,\n    const void* pNext)\n{\n    VkResult res = VK_ERROR_UNKNOWN;\n    switch(hAllocation->GetType())\n    {\n    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:\n        res = BindVulkanBuffer(hAllocation->GetMemory(), allocationLocalOffset, hBuffer, pNext);\n        break;\n    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:\n    {\n        VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();\n        VMA_ASSERT(pBlock && \"Binding buffer to allocation that doesn't belong to any block.\");\n        res = pBlock->BindBufferMemory(this, hAllocation, allocationLocalOffset, hBuffer, pNext);\n        break;\n    }\n    default:\n        VMA_ASSERT(0);\n    }\n    return res;\n}\n\nVkResult VmaAllocator_T::BindImageMemory(\n    VmaAllocation hAllocation,\n    VkDeviceSize allocationLocalOffset,\n    VkImage hImage,\n    const void* pNext)\n{\n    VkResult res = VK_ERROR_UNKNOWN;\n    switch(hAllocation->GetType())\n    {\n    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:\n        res = BindVulkanImage(hAllocation->GetMemory(), allocationLocalOffset, hImage, pNext);\n        break;\n    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:\n    {\n        VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();\n        VMA_ASSERT(pBlock && \"Binding image to allocation that doesn't belong to any block.\");\n        res = pBlock->BindImageMemory(this, hAllocation, allocationLocalOffset, hImage, pNext);\n        break;\n    }\n    default:\n        VMA_ASSERT(0);\n    }\n    return res;\n}\n\nVkResult VmaAllocator_T::FlushOrInvalidateAllocation(\n    VmaAllocation hAllocation,\n    VkDeviceSize offset, VkDeviceSize size,\n    VMA_CACHE_OPERATION op)\n{\n    VkResult res = VK_SUCCESS;\n\n    VkMappedMemoryRange memRange = {};\n    if(GetFlushOrInvalidateRange(hAllocation, offset, size, memRange))\n    {\n        switch(op)\n        {\n        case VMA_CACHE_FLUSH:\n            res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange);\n            break;\n        case VMA_CACHE_INVALIDATE:\n            res = (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange);\n            break;\n        default:\n            VMA_ASSERT(0);\n        }\n    }\n    // else: Just ignore this call.\n    return res;\n}\n\nVkResult VmaAllocator_T::FlushOrInvalidateAllocations(\n    uint32_t allocationCount,\n    const VmaAllocation* allocations,\n    const VkDeviceSize* offsets, const VkDeviceSize* sizes,\n    VMA_CACHE_OPERATION op)\n{\n    typedef VmaStlAllocator<VkMappedMemoryRange> RangeAllocator;\n    typedef VmaSmallVector<VkMappedMemoryRange, RangeAllocator, 16> RangeVector;\n    RangeVector ranges = RangeVector(RangeAllocator(GetAllocationCallbacks()));\n\n    for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex)\n    {\n        const VmaAllocation alloc = allocations[allocIndex];\n        const VkDeviceSize offset = offsets != VMA_NULL ? offsets[allocIndex] : 0;\n        const VkDeviceSize size = sizes != VMA_NULL ? sizes[allocIndex] : VK_WHOLE_SIZE;\n        VkMappedMemoryRange newRange;\n        if(GetFlushOrInvalidateRange(alloc, offset, size, newRange))\n        {\n            ranges.push_back(newRange);\n        }\n    }\n\n    VkResult res = VK_SUCCESS;\n    if(!ranges.empty())\n    {\n        switch(op)\n        {\n        case VMA_CACHE_FLUSH:\n            res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data());\n            break;\n        case VMA_CACHE_INVALIDATE:\n            res = (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data());\n            break;\n        default:\n            VMA_ASSERT(0);\n        }\n    }\n    // else: Just ignore this call.\n    return res;\n}\n\nvoid VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)\n{\n    VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);\n\n    const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();\n    VmaPool parentPool = allocation->GetParentPool();\n    if(parentPool == VK_NULL_HANDLE)\n    {\n        // Default pool\n        m_DedicatedAllocations[memTypeIndex].Unregister(allocation);\n    }\n    else\n    {\n        // Custom pool\n        parentPool->m_DedicatedAllocations.Unregister(allocation);\n    }\n\n    VkDeviceMemory hMemory = allocation->GetMemory();\n\n    /*\n    There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory\n    before vkFreeMemory.\n\n    if(allocation->GetMappedData() != VMA_NULL)\n    {\n        (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);\n    }\n    */\n\n    FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);\n\n    m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());\n    m_AllocationObjectAllocator.Free(allocation);\n\n    VMA_DEBUG_LOG(\"    Freed DedicatedMemory MemoryTypeIndex=%u\", memTypeIndex);\n}\n\nuint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const\n{\n    VkBufferCreateInfo dummyBufCreateInfo;\n    VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo);\n\n    uint32_t memoryTypeBits = 0;\n\n    // Create buffer.\n    VkBuffer buf = VK_NULL_HANDLE;\n    VkResult res = (*GetVulkanFunctions().vkCreateBuffer)(\n        m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf);\n    if(res == VK_SUCCESS)\n    {\n        // Query for supported memory types.\n        VkMemoryRequirements memReq;\n        (*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &memReq);\n        memoryTypeBits = memReq.memoryTypeBits;\n\n        // Destroy buffer.\n        (*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks());\n    }\n\n    return memoryTypeBits;\n}\n\nuint32_t VmaAllocator_T::CalculateGlobalMemoryTypeBits() const\n{\n    // Make sure memory information is already fetched.\n    VMA_ASSERT(GetMemoryTypeCount() > 0);\n\n    uint32_t memoryTypeBits = UINT32_MAX;\n\n    if(!m_UseAmdDeviceCoherentMemory)\n    {\n        // Exclude memory types that have VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD.\n        for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n        {\n            if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0)\n            {\n                memoryTypeBits &= ~(1u << memTypeIndex);\n            }\n        }\n    }\n\n    return memoryTypeBits;\n}\n\nbool VmaAllocator_T::GetFlushOrInvalidateRange(\n    VmaAllocation allocation,\n    VkDeviceSize offset, VkDeviceSize size,\n    VkMappedMemoryRange& outRange) const\n{\n    const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();\n    if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex))\n    {\n        const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;\n        const VkDeviceSize allocationSize = allocation->GetSize();\n        VMA_ASSERT(offset <= allocationSize);\n\n        outRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;\n        outRange.pNext = VMA_NULL;\n        outRange.memory = allocation->GetMemory();\n\n        switch(allocation->GetType())\n        {\n        case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:\n            outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);\n            if(size == VK_WHOLE_SIZE)\n            {\n                outRange.size = allocationSize - outRange.offset;\n            }\n            else\n            {\n                VMA_ASSERT(offset + size <= allocationSize);\n                outRange.size = VMA_MIN(\n                    VmaAlignUp(size + (offset - outRange.offset), nonCoherentAtomSize),\n                    allocationSize - outRange.offset);\n            }\n            break;\n        case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:\n        {\n            // 1. Still within this allocation.\n            outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);\n            if(size == VK_WHOLE_SIZE)\n            {\n                size = allocationSize - offset;\n            }\n            else\n            {\n                VMA_ASSERT(offset + size <= allocationSize);\n            }\n            outRange.size = VmaAlignUp(size + (offset - outRange.offset), nonCoherentAtomSize);\n\n            // 2. Adjust to whole block.\n            const VkDeviceSize allocationOffset = allocation->GetOffset();\n            VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);\n            const VkDeviceSize blockSize = allocation->GetBlock()->m_pMetadata->GetSize();\n            outRange.offset += allocationOffset;\n            outRange.size = VMA_MIN(outRange.size, blockSize - outRange.offset);\n\n            break;\n        }\n        default:\n            VMA_ASSERT(0);\n        }\n        return true;\n    }\n    return false;\n}\n\n#if VMA_MEMORY_BUDGET\nvoid VmaAllocator_T::UpdateVulkanBudget()\n{\n    VMA_ASSERT(m_UseExtMemoryBudget);\n\n    VkPhysicalDeviceMemoryProperties2KHR memProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR };\n\n    VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT };\n    VmaPnextChainPushFront(&memProps, &budgetProps);\n\n    GetVulkanFunctions().vkGetPhysicalDeviceMemoryProperties2KHR(m_PhysicalDevice, &memProps);\n\n    {\n        VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex);\n\n        for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)\n        {\n            m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex];\n            m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex];\n            m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load();\n\n            // Some bugged drivers return the budget incorrectly, e.g. 0 or much bigger than heap size.\n            if(m_Budget.m_VulkanBudget[heapIndex] == 0)\n            {\n                m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.\n            }\n            else if(m_Budget.m_VulkanBudget[heapIndex] > m_MemProps.memoryHeaps[heapIndex].size)\n            {\n                m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size;\n            }\n            if(m_Budget.m_VulkanUsage[heapIndex] == 0 && m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] > 0)\n            {\n                m_Budget.m_VulkanUsage[heapIndex] = m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];\n            }\n        }\n        m_Budget.m_OperationsSinceBudgetFetch = 0;\n    }\n}\n#endif // VMA_MEMORY_BUDGET\n\nvoid VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)\n{\n    if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&\n        hAllocation->IsMappingAllowed() &&\n        (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)\n    {\n        void* pData = VMA_NULL;\n        VkResult res = Map(hAllocation, &pData);\n        if(res == VK_SUCCESS)\n        {\n            memset(pData, (int)pattern, (size_t)hAllocation->GetSize());\n            FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH);\n            Unmap(hAllocation);\n        }\n        else\n        {\n            VMA_ASSERT(0 && \"VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn't map memory to fill allocation.\");\n        }\n    }\n}\n\nuint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits()\n{\n    uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load();\n    if(memoryTypeBits == UINT32_MAX)\n    {\n        memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits();\n        m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits);\n    }\n    return memoryTypeBits;\n}\n\n#if VMA_STATS_STRING_ENABLED\nvoid VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)\n{\n    json.WriteString(\"DefaultPools\");\n    json.BeginObject();\n    {\n        for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n        {\n            VmaBlockVector* pBlockVector = m_pBlockVectors[memTypeIndex];\n            VmaDedicatedAllocationList& dedicatedAllocList = m_DedicatedAllocations[memTypeIndex];\n            if (pBlockVector != VMA_NULL)\n            {\n                json.BeginString(\"Type \");\n                json.ContinueString(memTypeIndex);\n                json.EndString();\n                json.BeginObject();\n                {\n                    json.WriteString(\"PreferredBlockSize\");\n                    json.WriteNumber(pBlockVector->GetPreferredBlockSize());\n\n                    json.WriteString(\"Blocks\");\n                    pBlockVector->PrintDetailedMap(json);\n\n                    json.WriteString(\"DedicatedAllocations\");\n                    dedicatedAllocList.BuildStatsString(json);\n                }\n                json.EndObject();\n            }\n        }\n    }\n    json.EndObject();\n\n    json.WriteString(\"CustomPools\");\n    json.BeginObject();\n    {\n        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);\n        if (!m_Pools.IsEmpty())\n        {\n            for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)\n            {\n                bool displayType = true;\n                size_t index = 0;\n                for (VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))\n                {\n                    VmaBlockVector& blockVector = pool->m_BlockVector;\n                    if (blockVector.GetMemoryTypeIndex() == memTypeIndex)\n                    {\n                        if (displayType)\n                        {\n                            json.BeginString(\"Type \");\n                            json.ContinueString(memTypeIndex);\n                            json.EndString();\n                            json.BeginArray();\n                            displayType = false;\n                        }\n\n                        json.BeginObject();\n                        {\n                            json.WriteString(\"Name\");\n                            json.BeginString();\n                            json.ContinueString((uint64_t)index++);\n                            if (pool->GetName())\n                            {\n                                json.ContinueString(\" - \");\n                                json.ContinueString(pool->GetName());\n                            }\n                            json.EndString();\n\n                            json.WriteString(\"PreferredBlockSize\");\n                            json.WriteNumber(blockVector.GetPreferredBlockSize());\n\n                            json.WriteString(\"Blocks\");\n                            blockVector.PrintDetailedMap(json);\n\n                            json.WriteString(\"DedicatedAllocations\");\n                            pool->m_DedicatedAllocations.BuildStatsString(json);\n                        }\n                        json.EndObject();\n                    }\n                }\n\n                if (!displayType)\n                    json.EndArray();\n            }\n        }\n    }\n    json.EndObject();\n}\n#endif // VMA_STATS_STRING_ENABLED\n#endif // _VMA_ALLOCATOR_T_FUNCTIONS\n\n\n#ifndef _VMA_PUBLIC_INTERFACE\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(\n    const VmaAllocatorCreateInfo* pCreateInfo,\n    VmaAllocator* pAllocator)\n{\n    VMA_ASSERT(pCreateInfo && pAllocator);\n    VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 ||\n        (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 3));\n    VMA_DEBUG_LOG(\"vmaCreateAllocator\");\n    *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);\n    VkResult result = (*pAllocator)->Init(pCreateInfo);\n    if(result < 0)\n    {\n        vma_delete(pCreateInfo->pAllocationCallbacks, *pAllocator);\n        *pAllocator = VK_NULL_HANDLE;\n    }\n    return result;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(\n    VmaAllocator allocator)\n{\n    if(allocator != VK_NULL_HANDLE)\n    {\n        VMA_DEBUG_LOG(\"vmaDestroyAllocator\");\n        VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks; // Have to copy the callbacks when destroying.\n        vma_delete(&allocationCallbacks, allocator);\n    }\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator allocator, VmaAllocatorInfo* pAllocatorInfo)\n{\n    VMA_ASSERT(allocator && pAllocatorInfo);\n    pAllocatorInfo->instance = allocator->m_hInstance;\n    pAllocatorInfo->physicalDevice = allocator->GetPhysicalDevice();\n    pAllocatorInfo->device = allocator->m_hDevice;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(\n    VmaAllocator allocator,\n    const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)\n{\n    VMA_ASSERT(allocator && ppPhysicalDeviceProperties);\n    *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(\n    VmaAllocator allocator,\n    const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties)\n{\n    VMA_ASSERT(allocator && ppPhysicalDeviceMemoryProperties);\n    *ppPhysicalDeviceMemoryProperties = &allocator->m_MemProps;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(\n    VmaAllocator allocator,\n    uint32_t memoryTypeIndex,\n    VkMemoryPropertyFlags* pFlags)\n{\n    VMA_ASSERT(allocator && pFlags);\n    VMA_ASSERT(memoryTypeIndex < allocator->GetMemoryTypeCount());\n    *pFlags = allocator->m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(\n    VmaAllocator allocator,\n    uint32_t frameIndex)\n{\n    VMA_ASSERT(allocator);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->SetCurrentFrameIndex(frameIndex);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics(\n    VmaAllocator allocator,\n    VmaTotalStatistics* pStats)\n{\n    VMA_ASSERT(allocator && pStats);\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n    allocator->CalculateStatistics(pStats);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets(\n    VmaAllocator allocator,\n    VmaBudget* pBudgets)\n{\n    VMA_ASSERT(allocator && pBudgets);\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n    allocator->GetHeapBudgets(pBudgets, 0, allocator->GetMemoryHeapCount());\n}\n\n#if VMA_STATS_STRING_ENABLED\n\nVMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(\n    VmaAllocator allocator,\n    char** ppStatsString,\n    VkBool32 detailedMap)\n{\n    VMA_ASSERT(allocator && ppStatsString);\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    VmaStringBuilder sb(allocator->GetAllocationCallbacks());\n    {\n        VmaBudget budgets[VK_MAX_MEMORY_HEAPS];\n        allocator->GetHeapBudgets(budgets, 0, allocator->GetMemoryHeapCount());\n\n        VmaTotalStatistics stats;\n        allocator->CalculateStatistics(&stats);\n\n        VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb);\n        json.BeginObject();\n        {\n            json.WriteString(\"General\");\n            json.BeginObject();\n            {\n                const VkPhysicalDeviceProperties& deviceProperties = allocator->m_PhysicalDeviceProperties;\n                const VkPhysicalDeviceMemoryProperties& memoryProperties = allocator->m_MemProps;\n\n                json.WriteString(\"API\");\n                json.WriteString(\"Vulkan\");\n\n                json.WriteString(\"apiVersion\");\n                json.BeginString();\n                json.ContinueString(VK_VERSION_MAJOR(deviceProperties.apiVersion));\n                json.ContinueString(\".\");\n                json.ContinueString(VK_VERSION_MINOR(deviceProperties.apiVersion));\n                json.ContinueString(\".\");\n                json.ContinueString(VK_VERSION_PATCH(deviceProperties.apiVersion));\n                json.EndString();\n\n                json.WriteString(\"GPU\");\n                json.WriteString(deviceProperties.deviceName);\n                json.WriteString(\"deviceType\");\n                json.WriteNumber(static_cast<uint32_t>(deviceProperties.deviceType));\n\n                json.WriteString(\"maxMemoryAllocationCount\");\n                json.WriteNumber(deviceProperties.limits.maxMemoryAllocationCount);\n                json.WriteString(\"bufferImageGranularity\");\n                json.WriteNumber(deviceProperties.limits.bufferImageGranularity);\n                json.WriteString(\"nonCoherentAtomSize\");\n                json.WriteNumber(deviceProperties.limits.nonCoherentAtomSize);\n\n                json.WriteString(\"memoryHeapCount\");\n                json.WriteNumber(memoryProperties.memoryHeapCount);\n                json.WriteString(\"memoryTypeCount\");\n                json.WriteNumber(memoryProperties.memoryTypeCount);\n            }\n            json.EndObject();\n        }\n        {\n            json.WriteString(\"Total\");\n            VmaPrintDetailedStatistics(json, stats.total);\n        }\n        {\n            json.WriteString(\"MemoryInfo\");\n            json.BeginObject();\n            {\n                for (uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex)\n                {\n                    json.BeginString(\"Heap \");\n                    json.ContinueString(heapIndex);\n                    json.EndString();\n                    json.BeginObject();\n                    {\n                        const VkMemoryHeap& heapInfo = allocator->m_MemProps.memoryHeaps[heapIndex];\n                        json.WriteString(\"Flags\");\n                        json.BeginArray(true);\n                        {\n                            if (heapInfo.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)\n                                json.WriteString(\"DEVICE_LOCAL\");\n                        #if VMA_VULKAN_VERSION >= 1001000\n                            if (heapInfo.flags & VK_MEMORY_HEAP_MULTI_INSTANCE_BIT)\n                                json.WriteString(\"MULTI_INSTANCE\");\n                        #endif\n\n                            VkMemoryHeapFlags flags = heapInfo.flags &\n                                ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT\n                        #if VMA_VULKAN_VERSION >= 1001000\n                                    | VK_MEMORY_HEAP_MULTI_INSTANCE_BIT\n                        #endif\n                                    );\n                            if (flags != 0)\n                                json.WriteNumber(flags);\n                        }\n                        json.EndArray();\n\n                        json.WriteString(\"Size\");\n                        json.WriteNumber(heapInfo.size);\n\n                        json.WriteString(\"Budget\");\n                        json.BeginObject();\n                        {\n                            json.WriteString(\"BudgetBytes\");\n                            json.WriteNumber(budgets[heapIndex].budget);\n                            json.WriteString(\"UsageBytes\");\n                            json.WriteNumber(budgets[heapIndex].usage);\n                        }\n                        json.EndObject();\n\n                        json.WriteString(\"Stats\");\n                        VmaPrintDetailedStatistics(json, stats.memoryHeap[heapIndex]);\n\n                        json.WriteString(\"MemoryPools\");\n                        json.BeginObject();\n                        {\n                            for (uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex)\n                            {\n                                if (allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)\n                                {\n                                    json.BeginString(\"Type \");\n                                    json.ContinueString(typeIndex);\n                                    json.EndString();\n                                    json.BeginObject();\n                                    {\n                                        json.WriteString(\"Flags\");\n                                        json.BeginArray(true);\n                                        {\n                                            VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags;\n                                            if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)\n                                                json.WriteString(\"DEVICE_LOCAL\");\n                                            if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)\n                                                json.WriteString(\"HOST_VISIBLE\");\n                                            if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)\n                                                json.WriteString(\"HOST_COHERENT\");\n                                            if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)\n                                                json.WriteString(\"HOST_CACHED\");\n                                            if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)\n                                                json.WriteString(\"LAZILY_ALLOCATED\");\n                                        #if VMA_VULKAN_VERSION >= 1001000\n                                            if (flags & VK_MEMORY_PROPERTY_PROTECTED_BIT)\n                                                json.WriteString(\"PROTECTED\");\n                                        #endif\n                                        #if VK_AMD_device_coherent_memory\n                                            if (flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY)\n                                                json.WriteString(\"DEVICE_COHERENT_AMD\");\n                                            if (flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)\n                                                json.WriteString(\"DEVICE_UNCACHED_AMD\");\n                                        #endif\n\n                                            flags &= ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT\n                                        #if VMA_VULKAN_VERSION >= 1001000\n                                                | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT\n                                        #endif\n                                        #if VK_AMD_device_coherent_memory\n                                                | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY\n                                                | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY\n                                        #endif\n                                                | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT\n                                                | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT\n                                                | VK_MEMORY_PROPERTY_HOST_CACHED_BIT);\n                                            if (flags != 0)\n                                                json.WriteNumber(flags);\n                                        }\n                                        json.EndArray();\n\n                                        json.WriteString(\"Stats\");\n                                        VmaPrintDetailedStatistics(json, stats.memoryType[typeIndex]);\n                                    }\n                                    json.EndObject();\n                                }\n                            }\n\n                        }\n                        json.EndObject();\n                    }\n                    json.EndObject();\n                }\n            }\n            json.EndObject();\n        }\n\n        if (detailedMap == VK_TRUE)\n            allocator->PrintDetailedMap(json);\n\n        json.EndObject();\n    }\n\n    *ppStatsString = VmaCreateStringCopy(allocator->GetAllocationCallbacks(), sb.GetData(), sb.GetLength());\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(\n    VmaAllocator allocator,\n    char* pStatsString)\n{\n    if(pStatsString != VMA_NULL)\n    {\n        VMA_ASSERT(allocator);\n        VmaFreeString(allocator->GetAllocationCallbacks(), pStatsString);\n    }\n}\n\n#endif // VMA_STATS_STRING_ENABLED\n\n/*\nThis function is not protected by any mutex because it just reads immutable data.\n*/\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(\n    VmaAllocator allocator,\n    uint32_t memoryTypeBits,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    uint32_t* pMemoryTypeIndex)\n{\n    VMA_ASSERT(allocator != VK_NULL_HANDLE);\n    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);\n    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);\n\n    return allocator->FindMemoryTypeIndex(memoryTypeBits, pAllocationCreateInfo, UINT32_MAX, pMemoryTypeIndex);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(\n    VmaAllocator allocator,\n    const VkBufferCreateInfo* pBufferCreateInfo,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    uint32_t* pMemoryTypeIndex)\n{\n    VMA_ASSERT(allocator != VK_NULL_HANDLE);\n    VMA_ASSERT(pBufferCreateInfo != VMA_NULL);\n    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);\n    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);\n\n    const VkDevice hDev = allocator->m_hDevice;\n    const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions();\n    VkResult res;\n\n#if VMA_VULKAN_VERSION >= 1003000\n    if(funcs->vkGetDeviceBufferMemoryRequirements)\n    {\n        // Can query straight from VkBufferCreateInfo :)\n        VkDeviceBufferMemoryRequirements devBufMemReq = {VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS};\n        devBufMemReq.pCreateInfo = pBufferCreateInfo;\n\n        VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};\n        (*funcs->vkGetDeviceBufferMemoryRequirements)(hDev, &devBufMemReq, &memReq);\n\n        res = allocator->FindMemoryTypeIndex(\n            memReq.memoryRequirements.memoryTypeBits, pAllocationCreateInfo, pBufferCreateInfo->usage, pMemoryTypeIndex);\n    }\n    else\n#endif // #if VMA_VULKAN_VERSION >= 1003000\n    {\n        // Must create a dummy buffer to query :(\n        VkBuffer hBuffer = VK_NULL_HANDLE;\n        res = funcs->vkCreateBuffer(\n            hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer);\n        if(res == VK_SUCCESS)\n        {\n            VkMemoryRequirements memReq = {};\n            funcs->vkGetBufferMemoryRequirements(hDev, hBuffer, &memReq);\n\n            res = allocator->FindMemoryTypeIndex(\n                memReq.memoryTypeBits, pAllocationCreateInfo, pBufferCreateInfo->usage, pMemoryTypeIndex);\n\n            funcs->vkDestroyBuffer(\n                hDev, hBuffer, allocator->GetAllocationCallbacks());\n        }\n    }\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(\n    VmaAllocator allocator,\n    const VkImageCreateInfo* pImageCreateInfo,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    uint32_t* pMemoryTypeIndex)\n{\n    VMA_ASSERT(allocator != VK_NULL_HANDLE);\n    VMA_ASSERT(pImageCreateInfo != VMA_NULL);\n    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);\n    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);\n\n    const VkDevice hDev = allocator->m_hDevice;\n    const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions();\n    VkResult res;\n\n#if VMA_VULKAN_VERSION >= 1003000\n    if(funcs->vkGetDeviceImageMemoryRequirements)\n    {\n        // Can query straight from VkImageCreateInfo :)\n        VkDeviceImageMemoryRequirements devImgMemReq = {VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS};\n        devImgMemReq.pCreateInfo = pImageCreateInfo;\n        VMA_ASSERT(pImageCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY && (pImageCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_COPY) == 0 &&\n            \"Cannot use this VkImageCreateInfo with vmaFindMemoryTypeIndexForImageInfo as I don't know what to pass as VkDeviceImageMemoryRequirements::planeAspect.\");\n\n        VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};\n        (*funcs->vkGetDeviceImageMemoryRequirements)(hDev, &devImgMemReq, &memReq);\n\n        res = allocator->FindMemoryTypeIndex(\n            memReq.memoryRequirements.memoryTypeBits, pAllocationCreateInfo, pImageCreateInfo->usage, pMemoryTypeIndex);\n    }\n    else\n#endif // #if VMA_VULKAN_VERSION >= 1003000\n    {\n        // Must create a dummy image to query :(\n        VkImage hImage = VK_NULL_HANDLE;\n        res = funcs->vkCreateImage(\n            hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage);\n        if(res == VK_SUCCESS)\n        {\n            VkMemoryRequirements memReq = {};\n            funcs->vkGetImageMemoryRequirements(hDev, hImage, &memReq);\n\n            res = allocator->FindMemoryTypeIndex(\n                memReq.memoryTypeBits, pAllocationCreateInfo, pImageCreateInfo->usage, pMemoryTypeIndex);\n\n            funcs->vkDestroyImage(\n                hDev, hImage, allocator->GetAllocationCallbacks());\n        }\n    }\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(\n    VmaAllocator allocator,\n    const VmaPoolCreateInfo* pCreateInfo,\n    VmaPool* pPool)\n{\n    VMA_ASSERT(allocator && pCreateInfo && pPool);\n\n    VMA_DEBUG_LOG(\"vmaCreatePool\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return allocator->CreatePool(pCreateInfo, pPool);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(\n    VmaAllocator allocator,\n    VmaPool pool)\n{\n    VMA_ASSERT(allocator);\n\n    if(pool == VK_NULL_HANDLE)\n    {\n        return;\n    }\n\n    VMA_DEBUG_LOG(\"vmaDestroyPool\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->DestroyPool(pool);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(\n    VmaAllocator allocator,\n    VmaPool pool,\n    VmaStatistics* pPoolStats)\n{\n    VMA_ASSERT(allocator && pool && pPoolStats);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->GetPoolStatistics(pool, pPoolStats);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics(\n    VmaAllocator allocator,\n    VmaPool pool,\n    VmaDetailedStatistics* pPoolStats)\n{\n    VMA_ASSERT(allocator && pool && pPoolStats);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->CalculatePoolStatistics(pool, pPoolStats);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool)\n{\n    VMA_ASSERT(allocator && pool);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    VMA_DEBUG_LOG(\"vmaCheckPoolCorruption\");\n\n    return allocator->CheckPoolCorruption(pool);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(\n    VmaAllocator allocator,\n    VmaPool pool,\n    const char** ppName)\n{\n    VMA_ASSERT(allocator && pool && ppName);\n\n    VMA_DEBUG_LOG(\"vmaGetPoolName\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    *ppName = pool->GetName();\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(\n    VmaAllocator allocator,\n    VmaPool pool,\n    const char* pName)\n{\n    VMA_ASSERT(allocator && pool);\n\n    VMA_DEBUG_LOG(\"vmaSetPoolName\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    pool->SetName(pName);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(\n    VmaAllocator allocator,\n    const VkMemoryRequirements* pVkMemoryRequirements,\n    const VmaAllocationCreateInfo* pCreateInfo,\n    VmaAllocation* pAllocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocation);\n\n    VMA_DEBUG_LOG(\"vmaAllocateMemory\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    VkResult result = allocator->AllocateMemory(\n        *pVkMemoryRequirements,\n        false, // requiresDedicatedAllocation\n        false, // prefersDedicatedAllocation\n        VK_NULL_HANDLE, // dedicatedBuffer\n        VK_NULL_HANDLE, // dedicatedImage\n        UINT32_MAX, // dedicatedBufferImageUsage\n        *pCreateInfo,\n        VMA_SUBALLOCATION_TYPE_UNKNOWN,\n        1, // allocationCount\n        pAllocation);\n\n    if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)\n    {\n        allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);\n    }\n\n    return result;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(\n    VmaAllocator allocator,\n    const VkMemoryRequirements* pVkMemoryRequirements,\n    const VmaAllocationCreateInfo* pCreateInfo,\n    size_t allocationCount,\n    VmaAllocation* pAllocations,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    if(allocationCount == 0)\n    {\n        return VK_SUCCESS;\n    }\n\n    VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocations);\n\n    VMA_DEBUG_LOG(\"vmaAllocateMemoryPages\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    VkResult result = allocator->AllocateMemory(\n        *pVkMemoryRequirements,\n        false, // requiresDedicatedAllocation\n        false, // prefersDedicatedAllocation\n        VK_NULL_HANDLE, // dedicatedBuffer\n        VK_NULL_HANDLE, // dedicatedImage\n        UINT32_MAX, // dedicatedBufferImageUsage\n        *pCreateInfo,\n        VMA_SUBALLOCATION_TYPE_UNKNOWN,\n        allocationCount,\n        pAllocations);\n\n    if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)\n    {\n        for(size_t i = 0; i < allocationCount; ++i)\n        {\n            allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i);\n        }\n    }\n\n    return result;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(\n    VmaAllocator allocator,\n    VkBuffer buffer,\n    const VmaAllocationCreateInfo* pCreateInfo,\n    VmaAllocation* pAllocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && buffer != VK_NULL_HANDLE && pCreateInfo && pAllocation);\n\n    VMA_DEBUG_LOG(\"vmaAllocateMemoryForBuffer\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    VkMemoryRequirements vkMemReq = {};\n    bool requiresDedicatedAllocation = false;\n    bool prefersDedicatedAllocation = false;\n    allocator->GetBufferMemoryRequirements(buffer, vkMemReq,\n        requiresDedicatedAllocation,\n        prefersDedicatedAllocation);\n\n    VkResult result = allocator->AllocateMemory(\n        vkMemReq,\n        requiresDedicatedAllocation,\n        prefersDedicatedAllocation,\n        buffer, // dedicatedBuffer\n        VK_NULL_HANDLE, // dedicatedImage\n        UINT32_MAX, // dedicatedBufferImageUsage\n        *pCreateInfo,\n        VMA_SUBALLOCATION_TYPE_BUFFER,\n        1, // allocationCount\n        pAllocation);\n\n    if(pAllocationInfo && result == VK_SUCCESS)\n    {\n        allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);\n    }\n\n    return result;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(\n    VmaAllocator allocator,\n    VkImage image,\n    const VmaAllocationCreateInfo* pCreateInfo,\n    VmaAllocation* pAllocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && image != VK_NULL_HANDLE && pCreateInfo && pAllocation);\n\n    VMA_DEBUG_LOG(\"vmaAllocateMemoryForImage\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    VkMemoryRequirements vkMemReq = {};\n    bool requiresDedicatedAllocation = false;\n    bool prefersDedicatedAllocation  = false;\n    allocator->GetImageMemoryRequirements(image, vkMemReq,\n        requiresDedicatedAllocation, prefersDedicatedAllocation);\n\n    VkResult result = allocator->AllocateMemory(\n        vkMemReq,\n        requiresDedicatedAllocation,\n        prefersDedicatedAllocation,\n        VK_NULL_HANDLE, // dedicatedBuffer\n        image, // dedicatedImage\n        UINT32_MAX, // dedicatedBufferImageUsage\n        *pCreateInfo,\n        VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN,\n        1, // allocationCount\n        pAllocation);\n\n    if(pAllocationInfo && result == VK_SUCCESS)\n    {\n        allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);\n    }\n\n    return result;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(\n    VmaAllocator allocator,\n    VmaAllocation allocation)\n{\n    VMA_ASSERT(allocator);\n\n    if(allocation == VK_NULL_HANDLE)\n    {\n        return;\n    }\n\n    VMA_DEBUG_LOG(\"vmaFreeMemory\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->FreeMemory(\n        1, // allocationCount\n        &allocation);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(\n    VmaAllocator allocator,\n    size_t allocationCount,\n    const VmaAllocation* pAllocations)\n{\n    if(allocationCount == 0)\n    {\n        return;\n    }\n\n    VMA_ASSERT(allocator);\n\n    VMA_DEBUG_LOG(\"vmaFreeMemoryPages\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->FreeMemory(allocationCount, pAllocations);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && allocation && pAllocationInfo);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->GetAllocationInfo(allocation, pAllocationInfo);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    void* pUserData)\n{\n    VMA_ASSERT(allocator && allocation);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocation->SetUserData(allocator, pUserData);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    const char* VMA_NULLABLE pName)\n{\n    allocation->SetName(allocator, pName);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkMemoryPropertyFlags* VMA_NOT_NULL pFlags)\n{\n    VMA_ASSERT(allocator && allocation && pFlags);\n    const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();\n    *pFlags = allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    void** ppData)\n{\n    VMA_ASSERT(allocator && allocation && ppData);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return allocator->Map(allocation, ppData);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(\n    VmaAllocator allocator,\n    VmaAllocation allocation)\n{\n    VMA_ASSERT(allocator && allocation);\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    allocator->Unmap(allocation);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VkDeviceSize offset,\n    VkDeviceSize size)\n{\n    VMA_ASSERT(allocator && allocation);\n\n    VMA_DEBUG_LOG(\"vmaFlushAllocation\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    const VkResult res = allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);\n\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VkDeviceSize offset,\n    VkDeviceSize size)\n{\n    VMA_ASSERT(allocator && allocation);\n\n    VMA_DEBUG_LOG(\"vmaInvalidateAllocation\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    const VkResult res = allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);\n\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations(\n    VmaAllocator allocator,\n    uint32_t allocationCount,\n    const VmaAllocation* allocations,\n    const VkDeviceSize* offsets,\n    const VkDeviceSize* sizes)\n{\n    VMA_ASSERT(allocator);\n\n    if(allocationCount == 0)\n    {\n        return VK_SUCCESS;\n    }\n\n    VMA_ASSERT(allocations);\n\n    VMA_DEBUG_LOG(\"vmaFlushAllocations\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    const VkResult res = allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_FLUSH);\n\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations(\n    VmaAllocator allocator,\n    uint32_t allocationCount,\n    const VmaAllocation* allocations,\n    const VkDeviceSize* offsets,\n    const VkDeviceSize* sizes)\n{\n    VMA_ASSERT(allocator);\n\n    if(allocationCount == 0)\n    {\n        return VK_SUCCESS;\n    }\n\n    VMA_ASSERT(allocations);\n\n    VMA_DEBUG_LOG(\"vmaInvalidateAllocations\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    const VkResult res = allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_INVALIDATE);\n\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(\n    VmaAllocator allocator,\n    uint32_t memoryTypeBits)\n{\n    VMA_ASSERT(allocator);\n\n    VMA_DEBUG_LOG(\"vmaCheckCorruption\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return allocator->CheckCorruption(memoryTypeBits);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation(\n    VmaAllocator allocator,\n    const VmaDefragmentationInfo* pInfo,\n    VmaDefragmentationContext* pContext)\n{\n    VMA_ASSERT(allocator && pInfo && pContext);\n\n    VMA_DEBUG_LOG(\"vmaBeginDefragmentation\");\n\n    if (pInfo->pool != VMA_NULL)\n    {\n        // Check if run on supported algorithms\n        if (pInfo->pool->m_BlockVector.GetAlgorithm() & VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)\n            return VK_ERROR_FEATURE_NOT_PRESENT;\n    }\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    *pContext = vma_new(allocator, VmaDefragmentationContext_T)(allocator, *pInfo);\n    return VK_SUCCESS;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation(\n    VmaAllocator allocator,\n    VmaDefragmentationContext context,\n    VmaDefragmentationStats* pStats)\n{\n    VMA_ASSERT(allocator && context);\n\n    VMA_DEBUG_LOG(\"vmaEndDefragmentation\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    if (pStats)\n        context->GetStats(*pStats);\n    vma_delete(allocator, context);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaDefragmentationContext VMA_NOT_NULL context,\n    VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo)\n{\n    VMA_ASSERT(context && pPassInfo);\n\n    VMA_DEBUG_LOG(\"vmaBeginDefragmentationPass\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return context->DefragmentPassBegin(*pPassInfo);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaDefragmentationContext VMA_NOT_NULL context,\n    VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo)\n{\n    VMA_ASSERT(context && pPassInfo);\n\n    VMA_DEBUG_LOG(\"vmaEndDefragmentationPass\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return context->DefragmentPassEnd(*pPassInfo);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VkBuffer buffer)\n{\n    VMA_ASSERT(allocator && allocation && buffer);\n\n    VMA_DEBUG_LOG(\"vmaBindBufferMemory\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VkDeviceSize allocationLocalOffset,\n    VkBuffer buffer,\n    const void* pNext)\n{\n    VMA_ASSERT(allocator && allocation && buffer);\n\n    VMA_DEBUG_LOG(\"vmaBindBufferMemory2\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VkImage image)\n{\n    VMA_ASSERT(allocator && allocation && image);\n\n    VMA_DEBUG_LOG(\"vmaBindImageMemory\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    return allocator->BindImageMemory(allocation, 0, image, VMA_NULL);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(\n    VmaAllocator allocator,\n    VmaAllocation allocation,\n    VkDeviceSize allocationLocalOffset,\n    VkImage image,\n    const void* pNext)\n{\n    VMA_ASSERT(allocator && allocation && image);\n\n    VMA_DEBUG_LOG(\"vmaBindImageMemory2\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n        return allocator->BindImageMemory(allocation, allocationLocalOffset, image, pNext);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(\n    VmaAllocator allocator,\n    const VkBufferCreateInfo* pBufferCreateInfo,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    VkBuffer* pBuffer,\n    VmaAllocation* pAllocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation);\n\n    if(pBufferCreateInfo->size == 0)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n    if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&\n        !allocator->m_UseKhrBufferDeviceAddress)\n    {\n        VMA_ASSERT(0 && \"Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.\");\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n\n    VMA_DEBUG_LOG(\"vmaCreateBuffer\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    *pBuffer = VK_NULL_HANDLE;\n    *pAllocation = VK_NULL_HANDLE;\n\n    // 1. Create VkBuffer.\n    VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(\n        allocator->m_hDevice,\n        pBufferCreateInfo,\n        allocator->GetAllocationCallbacks(),\n        pBuffer);\n    if(res >= 0)\n    {\n        // 2. vkGetBufferMemoryRequirements.\n        VkMemoryRequirements vkMemReq = {};\n        bool requiresDedicatedAllocation = false;\n        bool prefersDedicatedAllocation  = false;\n        allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq,\n            requiresDedicatedAllocation, prefersDedicatedAllocation);\n\n        // 3. Allocate memory using allocator.\n        res = allocator->AllocateMemory(\n            vkMemReq,\n            requiresDedicatedAllocation,\n            prefersDedicatedAllocation,\n            *pBuffer, // dedicatedBuffer\n            VK_NULL_HANDLE, // dedicatedImage\n            pBufferCreateInfo->usage, // dedicatedBufferImageUsage\n            *pAllocationCreateInfo,\n            VMA_SUBALLOCATION_TYPE_BUFFER,\n            1, // allocationCount\n            pAllocation);\n\n        if(res >= 0)\n        {\n            // 3. Bind buffer with memory.\n            if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)\n            {\n                res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL);\n            }\n            if(res >= 0)\n            {\n                // All steps succeeded.\n                #if VMA_STATS_STRING_ENABLED\n                    (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage);\n                #endif\n                if(pAllocationInfo != VMA_NULL)\n                {\n                    allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);\n                }\n\n                return VK_SUCCESS;\n            }\n            allocator->FreeMemory(\n                1, // allocationCount\n                pAllocation);\n            *pAllocation = VK_NULL_HANDLE;\n            (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());\n            *pBuffer = VK_NULL_HANDLE;\n            return res;\n        }\n        (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());\n        *pBuffer = VK_NULL_HANDLE;\n        return res;\n    }\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment(\n    VmaAllocator allocator,\n    const VkBufferCreateInfo* pBufferCreateInfo,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    VkDeviceSize minAlignment,\n    VkBuffer* pBuffer,\n    VmaAllocation* pAllocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && VmaIsPow2(minAlignment) && pBuffer && pAllocation);\n\n    if(pBufferCreateInfo->size == 0)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n    if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&\n        !allocator->m_UseKhrBufferDeviceAddress)\n    {\n        VMA_ASSERT(0 && \"Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.\");\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n\n    VMA_DEBUG_LOG(\"vmaCreateBufferWithAlignment\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    *pBuffer = VK_NULL_HANDLE;\n    *pAllocation = VK_NULL_HANDLE;\n\n    // 1. Create VkBuffer.\n    VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(\n        allocator->m_hDevice,\n        pBufferCreateInfo,\n        allocator->GetAllocationCallbacks(),\n        pBuffer);\n    if(res >= 0)\n    {\n        // 2. vkGetBufferMemoryRequirements.\n        VkMemoryRequirements vkMemReq = {};\n        bool requiresDedicatedAllocation = false;\n        bool prefersDedicatedAllocation  = false;\n        allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq,\n            requiresDedicatedAllocation, prefersDedicatedAllocation);\n\n        // 2a. Include minAlignment\n        vkMemReq.alignment = VMA_MAX(vkMemReq.alignment, minAlignment);\n\n        // 3. Allocate memory using allocator.\n        res = allocator->AllocateMemory(\n            vkMemReq,\n            requiresDedicatedAllocation,\n            prefersDedicatedAllocation,\n            *pBuffer, // dedicatedBuffer\n            VK_NULL_HANDLE, // dedicatedImage\n            pBufferCreateInfo->usage, // dedicatedBufferImageUsage\n            *pAllocationCreateInfo,\n            VMA_SUBALLOCATION_TYPE_BUFFER,\n            1, // allocationCount\n            pAllocation);\n\n        if(res >= 0)\n        {\n            // 3. Bind buffer with memory.\n            if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)\n            {\n                res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL);\n            }\n            if(res >= 0)\n            {\n                // All steps succeeded.\n                #if VMA_STATS_STRING_ENABLED\n                    (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage);\n                #endif\n                if(pAllocationInfo != VMA_NULL)\n                {\n                    allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);\n                }\n\n                return VK_SUCCESS;\n            }\n            allocator->FreeMemory(\n                1, // allocationCount\n                pAllocation);\n            *pAllocation = VK_NULL_HANDLE;\n            (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());\n            *pBuffer = VK_NULL_HANDLE;\n            return res;\n        }\n        (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());\n        *pBuffer = VK_NULL_HANDLE;\n        return res;\n    }\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer)\n{\n    return vmaCreateAliasingBuffer2(allocator, allocation, 0, pBufferCreateInfo, pBuffer);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize allocationLocalOffset,\n    const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,\n    VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer)\n{\n    VMA_ASSERT(allocator && pBufferCreateInfo && pBuffer && allocation);\n    VMA_ASSERT(allocationLocalOffset + pBufferCreateInfo->size <= allocation->GetSize());\n\n    VMA_DEBUG_LOG(\"vmaCreateAliasingBuffer2\");\n\n    *pBuffer = VK_NULL_HANDLE;\n\n    if (pBufferCreateInfo->size == 0)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n    if ((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&\n        !allocator->m_UseKhrBufferDeviceAddress)\n    {\n        VMA_ASSERT(0 && \"Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.\");\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    // 1. Create VkBuffer.\n    VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(\n        allocator->m_hDevice,\n        pBufferCreateInfo,\n        allocator->GetAllocationCallbacks(),\n        pBuffer);\n    if (res >= 0)\n    {\n        // 2. Bind buffer with memory.\n        res = allocator->BindBufferMemory(allocation, allocationLocalOffset, *pBuffer, VMA_NULL);\n        if (res >= 0)\n        {\n            return VK_SUCCESS;\n        }\n        (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());\n    }\n    return res;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(\n    VmaAllocator allocator,\n    VkBuffer buffer,\n    VmaAllocation allocation)\n{\n    VMA_ASSERT(allocator);\n\n    if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)\n    {\n        return;\n    }\n\n    VMA_DEBUG_LOG(\"vmaDestroyBuffer\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    if(buffer != VK_NULL_HANDLE)\n    {\n        (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks());\n    }\n\n    if(allocation != VK_NULL_HANDLE)\n    {\n        allocator->FreeMemory(\n            1, // allocationCount\n            &allocation);\n    }\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(\n    VmaAllocator allocator,\n    const VkImageCreateInfo* pImageCreateInfo,\n    const VmaAllocationCreateInfo* pAllocationCreateInfo,\n    VkImage* pImage,\n    VmaAllocation* pAllocation,\n    VmaAllocationInfo* pAllocationInfo)\n{\n    VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation);\n\n    if(pImageCreateInfo->extent.width == 0 ||\n        pImageCreateInfo->extent.height == 0 ||\n        pImageCreateInfo->extent.depth == 0 ||\n        pImageCreateInfo->mipLevels == 0 ||\n        pImageCreateInfo->arrayLayers == 0)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n\n    VMA_DEBUG_LOG(\"vmaCreateImage\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    *pImage = VK_NULL_HANDLE;\n    *pAllocation = VK_NULL_HANDLE;\n\n    // 1. Create VkImage.\n    VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)(\n        allocator->m_hDevice,\n        pImageCreateInfo,\n        allocator->GetAllocationCallbacks(),\n        pImage);\n    if(res >= 0)\n    {\n        VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?\n            VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :\n            VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR;\n\n        // 2. Allocate memory using allocator.\n        VkMemoryRequirements vkMemReq = {};\n        bool requiresDedicatedAllocation = false;\n        bool prefersDedicatedAllocation  = false;\n        allocator->GetImageMemoryRequirements(*pImage, vkMemReq,\n            requiresDedicatedAllocation, prefersDedicatedAllocation);\n\n        res = allocator->AllocateMemory(\n            vkMemReq,\n            requiresDedicatedAllocation,\n            prefersDedicatedAllocation,\n            VK_NULL_HANDLE, // dedicatedBuffer\n            *pImage, // dedicatedImage\n            pImageCreateInfo->usage, // dedicatedBufferImageUsage\n            *pAllocationCreateInfo,\n            suballocType,\n            1, // allocationCount\n            pAllocation);\n\n        if(res >= 0)\n        {\n            // 3. Bind image with memory.\n            if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)\n            {\n                res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);\n            }\n            if(res >= 0)\n            {\n                // All steps succeeded.\n                #if VMA_STATS_STRING_ENABLED\n                    (*pAllocation)->InitBufferImageUsage(pImageCreateInfo->usage);\n                #endif\n                if(pAllocationInfo != VMA_NULL)\n                {\n                    allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);\n                }\n\n                return VK_SUCCESS;\n            }\n            allocator->FreeMemory(\n                1, // allocationCount\n                pAllocation);\n            *pAllocation = VK_NULL_HANDLE;\n            (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());\n            *pImage = VK_NULL_HANDLE;\n            return res;\n        }\n        (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());\n        *pImage = VK_NULL_HANDLE;\n        return res;\n    }\n    return res;\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage)\n{\n    return vmaCreateAliasingImage2(allocator, allocation, 0, pImageCreateInfo, pImage);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VmaAllocation VMA_NOT_NULL allocation,\n    VkDeviceSize allocationLocalOffset,\n    const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage)\n{\n    VMA_ASSERT(allocator && pImageCreateInfo && pImage && allocation);\n\n    *pImage = VK_NULL_HANDLE;\n\n    VMA_DEBUG_LOG(\"vmaCreateImage2\");\n\n    if (pImageCreateInfo->extent.width == 0 ||\n        pImageCreateInfo->extent.height == 0 ||\n        pImageCreateInfo->extent.depth == 0 ||\n        pImageCreateInfo->mipLevels == 0 ||\n        pImageCreateInfo->arrayLayers == 0)\n    {\n        return VK_ERROR_INITIALIZATION_FAILED;\n    }\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    // 1. Create VkImage.\n    VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)(\n        allocator->m_hDevice,\n        pImageCreateInfo,\n        allocator->GetAllocationCallbacks(),\n        pImage);\n    if (res >= 0)\n    {\n        // 2. Bind image with memory.\n        res = allocator->BindImageMemory(allocation, allocationLocalOffset, *pImage, VMA_NULL);\n        if (res >= 0)\n        {\n            return VK_SUCCESS;\n        }\n        (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());\n    }\n    return res;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(\n    VmaAllocator VMA_NOT_NULL allocator,\n    VkImage VMA_NULLABLE_NON_DISPATCHABLE image,\n    VmaAllocation VMA_NULLABLE allocation)\n{\n    VMA_ASSERT(allocator);\n\n    if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)\n    {\n        return;\n    }\n\n    VMA_DEBUG_LOG(\"vmaDestroyImage\");\n\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK\n\n    if(image != VK_NULL_HANDLE)\n    {\n        (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks());\n    }\n    if(allocation != VK_NULL_HANDLE)\n    {\n        allocator->FreeMemory(\n            1, // allocationCount\n            &allocation);\n    }\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock(\n    const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo,\n    VmaVirtualBlock VMA_NULLABLE * VMA_NOT_NULL pVirtualBlock)\n{\n    VMA_ASSERT(pCreateInfo && pVirtualBlock);\n    VMA_ASSERT(pCreateInfo->size > 0);\n    VMA_DEBUG_LOG(\"vmaCreateVirtualBlock\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    *pVirtualBlock = vma_new(pCreateInfo->pAllocationCallbacks, VmaVirtualBlock_T)(*pCreateInfo);\n    VkResult res = (*pVirtualBlock)->Init();\n    if(res < 0)\n    {\n        vma_delete(pCreateInfo->pAllocationCallbacks, *pVirtualBlock);\n        *pVirtualBlock = VK_NULL_HANDLE;\n    }\n    return res;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(VmaVirtualBlock VMA_NULLABLE virtualBlock)\n{\n    if(virtualBlock != VK_NULL_HANDLE)\n    {\n        VMA_DEBUG_LOG(\"vmaDestroyVirtualBlock\");\n        VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n        VkAllocationCallbacks allocationCallbacks = virtualBlock->m_AllocationCallbacks; // Have to copy the callbacks when destroying.\n        vma_delete(&allocationCallbacks, virtualBlock);\n    }\n}\n\nVMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty(VmaVirtualBlock VMA_NOT_NULL virtualBlock)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);\n    VMA_DEBUG_LOG(\"vmaIsVirtualBlockEmpty\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    return virtualBlock->IsEmpty() ? VK_TRUE : VK_FALSE;\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pVirtualAllocInfo != VMA_NULL);\n    VMA_DEBUG_LOG(\"vmaGetVirtualAllocationInfo\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    virtualBlock->GetAllocationInfo(allocation, *pVirtualAllocInfo);\n}\n\nVMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation,\n    VkDeviceSize* VMA_NULLABLE pOffset)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pCreateInfo != VMA_NULL && pAllocation != VMA_NULL);\n    VMA_DEBUG_LOG(\"vmaVirtualAllocate\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    return virtualBlock->Allocate(*pCreateInfo, *pAllocation, pOffset);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(VmaVirtualBlock VMA_NOT_NULL virtualBlock, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation)\n{\n    if(allocation != VK_NULL_HANDLE)\n    {\n        VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);\n        VMA_DEBUG_LOG(\"vmaVirtualFree\");\n        VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n        virtualBlock->Free(allocation);\n    }\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock(VmaVirtualBlock VMA_NOT_NULL virtualBlock)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);\n    VMA_DEBUG_LOG(\"vmaClearVirtualBlock\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    virtualBlock->Clear();\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, void* VMA_NULLABLE pUserData)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);\n    VMA_DEBUG_LOG(\"vmaSetVirtualAllocationUserData\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    virtualBlock->SetAllocationUserData(allocation, pUserData);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaStatistics* VMA_NOT_NULL pStats)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStats != VMA_NULL);\n    VMA_DEBUG_LOG(\"vmaGetVirtualBlockStatistics\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    virtualBlock->GetStatistics(*pStats);\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    VmaDetailedStatistics* VMA_NOT_NULL pStats)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStats != VMA_NULL);\n    VMA_DEBUG_LOG(\"vmaCalculateVirtualBlockStatistics\");\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    virtualBlock->CalculateDetailedStatistics(*pStats);\n}\n\n#if VMA_STATS_STRING_ENABLED\n\nVMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString, VkBool32 detailedMap)\n{\n    VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && ppStatsString != VMA_NULL);\n    VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n    const VkAllocationCallbacks* allocationCallbacks = virtualBlock->GetAllocationCallbacks();\n    VmaStringBuilder sb(allocationCallbacks);\n    virtualBlock->BuildStatsString(detailedMap != VK_FALSE, sb);\n    *ppStatsString = VmaCreateStringCopy(allocationCallbacks, sb.GetData(), sb.GetLength());\n}\n\nVMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock,\n    char* VMA_NULLABLE pStatsString)\n{\n    if(pStatsString != VMA_NULL)\n    {\n        VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);\n        VMA_DEBUG_GLOBAL_MUTEX_LOCK;\n        VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString);\n    }\n}\n#endif // VMA_STATS_STRING_ENABLED\n#endif // _VMA_PUBLIC_INTERFACE\n#endif // VMA_IMPLEMENTATION\n\n/**\n\\page quick_start Quick start\n\n\\section quick_start_project_setup Project setup\n\nVulkan Memory Allocator comes in form of a \"stb-style\" single header file.\nYou don't need to build it as a separate library project.\nYou can add this file directly to your project and submit it to code repository next to your other source files.\n\n\"Single header\" doesn't mean that everything is contained in C/C++ declarations,\nlike it tends to be in case of inline functions or C++ templates.\nIt means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro.\nIf you don't do it properly, you will get linker errors.\n\nTo do it properly:\n\n-# Include \"vk_mem_alloc.h\" file in each CPP file where you want to use the library.\n   This includes declarations of all members of the library.\n-# In exactly one CPP file define following macro before this include.\n   It enables also internal definitions.\n\n\\code\n#define VMA_IMPLEMENTATION\n#include \"vk_mem_alloc.h\"\n\\endcode\n\nIt may be a good idea to create dedicated CPP file just for this purpose.\n\nThis library includes header `<vulkan/vulkan.h>`, which in turn\nincludes `<windows.h>` on Windows. If you need some specific macros defined\nbefore including these headers (like `WIN32_LEAN_AND_MEAN` or\n`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define\nthem before every `#include` of this library.\n\nThis library is written in C++, but has C-compatible interface.\nThus you can include and use vk_mem_alloc.h in C or C++ code, but full\nimplementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C.\nSome features of C++14 are used. STL containers, RTTI, or C++ exceptions are not used.\n\n\n\\section quick_start_initialization Initialization\n\nAt program startup:\n\n-# Initialize Vulkan to have `VkPhysicalDevice`, `VkDevice` and `VkInstance` object.\n-# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by\n   calling vmaCreateAllocator().\n\nOnly members `physicalDevice`, `device`, `instance` are required.\nHowever, you should inform the library which Vulkan version do you use by setting\nVmaAllocatorCreateInfo::vulkanApiVersion and which extensions did you enable\nby setting VmaAllocatorCreateInfo::flags (like #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT for VK_KHR_buffer_device_address).\nOtherwise, VMA would use only features of Vulkan 1.0 core with no extensions.\n\n\\subsection quick_start_initialization_selecting_vulkan_version Selecting Vulkan version\n\nVMA supports Vulkan version down to 1.0, for backward compatibility.\nIf you want to use higher version, you need to inform the library about it.\nThis is a two-step process.\n\n<b>Step 1: Compile time.</b> By default, VMA compiles with code supporting the highest\nVulkan version found in the included `<vulkan/vulkan.h>` that is also supported by the library.\nIf this is OK, you don't need to do anything.\nHowever, if you want to compile VMA as if only some lower Vulkan version was available,\ndefine macro `VMA_VULKAN_VERSION` before every `#include \"vk_mem_alloc.h\"`.\nIt should have decimal numeric value in form of ABBBCCC, where A = major, BBB = minor, CCC = patch Vulkan version.\nFor example, to compile against Vulkan 1.2:\n\n\\code\n#define VMA_VULKAN_VERSION 1002000 // Vulkan 1.2\n#include \"vk_mem_alloc.h\"\n\\endcode\n\n<b>Step 2: Runtime.</b> Even when compiled with higher Vulkan version available,\nVMA can use only features of a lower version, which is configurable during creation of the #VmaAllocator object.\nBy default, only Vulkan 1.0 is used.\nTo initialize the allocator with support for higher Vulkan version, you need to set member\nVmaAllocatorCreateInfo::vulkanApiVersion to an appropriate value, e.g. using constants like `VK_API_VERSION_1_2`.\nSee code sample below.\n\n\\subsection quick_start_initialization_importing_vulkan_functions Importing Vulkan functions\n\nYou may need to configure importing Vulkan functions. There are 3 ways to do this:\n\n-# **If you link with Vulkan static library** (e.g. \"vulkan-1.lib\" on Windows):\n   - You don't need to do anything.\n   - VMA will use these, as macro `VMA_STATIC_VULKAN_FUNCTIONS` is defined to 1 by default.\n-# **If you want VMA to fetch pointers to Vulkan functions dynamically** using `vkGetInstanceProcAddr`,\n   `vkGetDeviceProcAddr` (this is the option presented in the example below):\n   - Define `VMA_STATIC_VULKAN_FUNCTIONS` to 0, `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 1.\n   - Provide pointers to these two functions via VmaVulkanFunctions::vkGetInstanceProcAddr,\n     VmaVulkanFunctions::vkGetDeviceProcAddr.\n   - The library will fetch pointers to all other functions it needs internally.\n-# **If you fetch pointers to all Vulkan functions in a custom way**, e.g. using some loader like\n   [Volk](https://github.com/zeux/volk):\n   - Define `VMA_STATIC_VULKAN_FUNCTIONS` and `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 0.\n   - Pass these pointers via structure #VmaVulkanFunctions.\n\nExample for case 2:\n\n\\code\n#define VMA_STATIC_VULKAN_FUNCTIONS 0\n#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1\n#include \"vk_mem_alloc.h\"\n\n...\n\nVmaVulkanFunctions vulkanFunctions = {};\nvulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;\nvulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;\n\nVmaAllocatorCreateInfo allocatorCreateInfo = {};\nallocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;\nallocatorCreateInfo.physicalDevice = physicalDevice;\nallocatorCreateInfo.device = device;\nallocatorCreateInfo.instance = instance;\nallocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;\n\nVmaAllocator allocator;\nvmaCreateAllocator(&allocatorCreateInfo, &allocator);\n\\endcode\n\n\n\\section quick_start_resource_allocation Resource allocation\n\nWhen you want to create a buffer or image:\n\n-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure.\n-# Fill VmaAllocationCreateInfo structure.\n-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory\n   already allocated and bound to it, plus #VmaAllocation objects that represents its underlying memory.\n\n\\code\nVkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufferInfo.size = 65536;\nbufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo allocInfo = {};\nallocInfo.usage = VMA_MEMORY_USAGE_AUTO;\n\nVkBuffer buffer;\nVmaAllocation allocation;\nvmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);\n\\endcode\n\nDon't forget to destroy your objects when no longer needed:\n\n\\code\nvmaDestroyBuffer(allocator, buffer, allocation);\nvmaDestroyAllocator(allocator);\n\\endcode\n\n\n\\page choosing_memory_type Choosing memory type\n\nPhysical devices in Vulkan support various combinations of memory heaps and\ntypes. Help with choosing correct and optimal memory type for your specific\nresource is one of the key features of this library. You can use it by filling\nappropriate members of VmaAllocationCreateInfo structure, as described below.\nYou can also combine multiple methods.\n\n-# If you just want to find memory type index that meets your requirements, you\n   can use function: vmaFindMemoryTypeIndexForBufferInfo(),\n   vmaFindMemoryTypeIndexForImageInfo(), vmaFindMemoryTypeIndex().\n-# If you want to allocate a region of device memory without association with any\n   specific image or buffer, you can use function vmaAllocateMemory(). Usage of\n   this function is not recommended and usually not needed.\n   vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once,\n   which may be useful for sparse binding.\n-# If you already have a buffer or an image created, you want to allocate memory\n   for it and then you will bind it yourself, you can use function\n   vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage().\n   For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory()\n   or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2().\n-# **This is the easiest and recommended way to use this library:**\n   If you want to create a buffer or an image, allocate memory for it and bind\n   them together, all in one call, you can use function vmaCreateBuffer(),\n   vmaCreateImage().\n\nWhen using 3. or 4., the library internally queries Vulkan for memory types\nsupported for that buffer or image (function `vkGetBufferMemoryRequirements()`)\nand uses only one of these types.\n\nIf no memory type can be found that meets all the requirements, these functions\nreturn `VK_ERROR_FEATURE_NOT_PRESENT`.\n\nYou can leave VmaAllocationCreateInfo structure completely filled with zeros.\nIt means no requirements are specified for memory type.\nIt is valid, although not very useful.\n\n\\section choosing_memory_type_usage Usage\n\nThe easiest way to specify memory requirements is to fill member\nVmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage.\nIt defines high level, common usage types.\nSince version 3 of the library, it is recommended to use #VMA_MEMORY_USAGE_AUTO to let it select best memory type for your resource automatically.\n\nFor example, if you want to create a uniform buffer that will be filled using\ntransfer only once or infrequently and then used for rendering every frame as a uniform buffer, you can\ndo it using following code. The buffer will most likely end up in a memory type with\n`VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT` to be fast to access by the GPU device.\n\n\\code\nVkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufferInfo.size = 65536;\nbufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo allocInfo = {};\nallocInfo.usage = VMA_MEMORY_USAGE_AUTO;\n\nVkBuffer buffer;\nVmaAllocation allocation;\nvmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);\n\\endcode\n\nIf you have a preference for putting the resource in GPU (device) memory or CPU (host) memory\non systems with discrete graphics card that have the memories separate, you can use\n#VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or #VMA_MEMORY_USAGE_AUTO_PREFER_HOST.\n\nWhen using `VMA_MEMORY_USAGE_AUTO*` while you want to map the allocated memory,\nyou also need to specify one of the host access flags:\n#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.\nThis will help the library decide about preferred memory type to ensure it has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`\nso you can map it.\n\nFor example, a staging buffer that will be filled via mapped pointer and then\nused as a source of transfer to the buffer described previously can be created like this.\nIt will likely end up in a memory type that is `HOST_VISIBLE` and `HOST_COHERENT`\nbut not `HOST_CACHED` (meaning uncached, write-combined) and not `DEVICE_LOCAL` (meaning system RAM).\n\n\\code\nVkBufferCreateInfo stagingBufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nstagingBufferInfo.size = 65536;\nstagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;\n\nVmaAllocationCreateInfo stagingAllocInfo = {};\nstagingAllocInfo.usage = VMA_MEMORY_USAGE_AUTO;\nstagingAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;\n\nVkBuffer stagingBuffer;\nVmaAllocation stagingAllocation;\nvmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo, &stagingBuffer, &stagingAllocation, nullptr);\n\\endcode\n\nFor more examples of creating different kinds of resources, see chapter \\ref usage_patterns.\n\nUsage values `VMA_MEMORY_USAGE_AUTO*` are legal to use only when the library knows\nabout the resource being created by having `VkBufferCreateInfo` / `VkImageCreateInfo` passed,\nso they work with functions like: vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo() etc.\nIf you allocate raw memory using function vmaAllocateMemory(), you have to use other means of selecting\nmemory type, as described below.\n\n\\note\nOld usage values (`VMA_MEMORY_USAGE_GPU_ONLY`, `VMA_MEMORY_USAGE_CPU_ONLY`,\n`VMA_MEMORY_USAGE_CPU_TO_GPU`, `VMA_MEMORY_USAGE_GPU_TO_CPU`, `VMA_MEMORY_USAGE_CPU_COPY`)\nare still available and work same way as in previous versions of the library\nfor backward compatibility, but they are not recommended.\n\n\\section choosing_memory_type_required_preferred_flags Required and preferred flags\n\nYou can specify more detailed requirements by filling members\nVmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags\nwith a combination of bits from enum `VkMemoryPropertyFlags`. For example,\nif you want to create a buffer that will be persistently mapped on host (so it\nmust be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`,\nuse following code:\n\n\\code\nVmaAllocationCreateInfo allocInfo = {};\nallocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;\nallocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;\nallocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\nVkBuffer buffer;\nVmaAllocation allocation;\nvmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);\n\\endcode\n\nA memory type is chosen that has all the required flags and as many preferred\nflags set as possible.\n\nValue passed in VmaAllocationCreateInfo::usage is internally converted to a set of required and preferred flags,\nplus some extra \"magic\" (heuristics).\n\n\\section choosing_memory_type_explicit_memory_types Explicit memory types\n\nIf you inspected memory types available on the physical device and you have\na preference for memory types that you want to use, you can fill member\nVmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set\nmeans that a memory type with that index is allowed to be used for the\nallocation. Special value 0, just like `UINT32_MAX`, means there are no\nrestrictions to memory type index.\n\nPlease note that this member is NOT just a memory type index.\nStill you can use it to choose just one, specific memory type.\nFor example, if you already determined that your buffer should be created in\nmemory type 2, use following code:\n\n\\code\nuint32_t memoryTypeIndex = 2;\n\nVmaAllocationCreateInfo allocInfo = {};\nallocInfo.memoryTypeBits = 1u << memoryTypeIndex;\n\nVkBuffer buffer;\nVmaAllocation allocation;\nvmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);\n\\endcode\n\n\n\\section choosing_memory_type_custom_memory_pools Custom memory pools\n\nIf you allocate from custom memory pool, all the ways of specifying memory\nrequirements described above are not applicable and the aforementioned members\nof VmaAllocationCreateInfo structure are ignored. Memory type is selected\nexplicitly when creating the pool and then used to make all the allocations from\nthat pool. For further details, see \\ref custom_memory_pools.\n\n\\section choosing_memory_type_dedicated_allocations Dedicated allocations\n\nMemory for allocations is reserved out of larger block of `VkDeviceMemory`\nallocated from Vulkan internally. That is the main feature of this whole library.\nYou can still request a separate memory block to be created for an allocation,\njust like you would do in a trivial solution without using any allocator.\nIn that case, a buffer or image is always bound to that memory at offset 0.\nThis is called a \"dedicated allocation\".\nYou can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\nThe library can also internally decide to use dedicated allocation in some cases, e.g.:\n\n- When the size of the allocation is large.\n- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled\n  and it reports that dedicated allocation is required or recommended for the resource.\n- When allocation of next big memory block fails due to not enough device memory,\n  but allocation with the exact requested size succeeds.\n\n\n\\page memory_mapping Memory mapping\n\nTo \"map memory\" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`,\nto be able to read from it or write to it in CPU code.\nMapping is possible only of memory allocated from a memory type that has\n`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag.\nFunctions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose.\nYou can use them directly with memory allocated by this library,\nbut it is not recommended because of following issue:\nMapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed.\nThis includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan.\nBecause of this, Vulkan Memory Allocator provides following facilities:\n\n\\note If you want to be able to map an allocation, you need to specify one of the flags\n#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT\nin VmaAllocationCreateInfo::flags. These flags are required for an allocation to be mappable\nwhen using #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` enum values.\nFor other usage values they are ignored and every such allocation made in `HOST_VISIBLE` memory type is mappable,\nbut they can still be used for consistency.\n\n\\section memory_mapping_mapping_functions Mapping functions\n\nThe library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory().\nThey are safer and more convenient to use than standard Vulkan functions.\nYou can map an allocation multiple times simultaneously - mapping is reference-counted internally.\nYou can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block.\nThe way it is implemented is that the library always maps entire memory block, not just region of the allocation.\nFor further details, see description of vmaMapMemory() function.\nExample:\n\n\\code\n// Having these objects initialized:\nstruct ConstantBuffer\n{\n    ...\n};\nConstantBuffer constantBufferData = ...\n\nVmaAllocator allocator = ...\nVkBuffer constantBuffer = ...\nVmaAllocation constantBufferAllocation = ...\n\n// You can map and fill your buffer using following code:\n\nvoid* mappedData;\nvmaMapMemory(allocator, constantBufferAllocation, &mappedData);\nmemcpy(mappedData, &constantBufferData, sizeof(constantBufferData));\nvmaUnmapMemory(allocator, constantBufferAllocation);\n\\endcode\n\nWhen mapping, you may see a warning from Vulkan validation layer similar to this one:\n\n<i>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</i>\n\nIt happens because the library maps entire `VkDeviceMemory` block, where different\ntypes of images and buffers may end up together, especially on GPUs with unified memory like Intel.\nYou can safely ignore it if you are sure you access only memory of the intended\nobject that you wanted to map.\n\n\n\\section memory_mapping_persistently_mapped_memory Persistently mapped memory\n\nKeeping your memory persistently mapped is generally OK in Vulkan.\nYou don't need to unmap it before using its data on the GPU.\nThe library provides a special feature designed for that:\nAllocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in\nVmaAllocationCreateInfo::flags stay mapped all the time,\nso you can just access CPU pointer to it any time\nwithout a need to call any \"map\" or \"unmap\" function.\nExample:\n\n\\code\nVkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufCreateInfo.size = sizeof(ConstantBuffer);\nbufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |\n    VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\nVkBuffer buf;\nVmaAllocation alloc;\nVmaAllocationInfo allocInfo;\nvmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);\n\n// Buffer is already mapped. You can access its memory.\nmemcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));\n\\endcode\n\n\\note #VMA_ALLOCATION_CREATE_MAPPED_BIT by itself doesn't guarantee that the allocation will end up\nin a mappable memory type.\nFor this, you need to also specify #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or\n#VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.\n#VMA_ALLOCATION_CREATE_MAPPED_BIT only guarantees that if the memory is `HOST_VISIBLE`, the allocation will be mapped on creation.\nFor an example of how to make use of this fact, see section \\ref usage_patterns_advanced_data_uploading.\n\n\\section memory_mapping_cache_control Cache flush and invalidate\n\nMemory in Vulkan doesn't need to be unmapped before using it on GPU,\nbut unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,\nyou need to manually **invalidate** cache before reading of mapped pointer\nand **flush** cache after writing to mapped pointer.\nMap/unmap operations don't do that automatically.\nVulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,\n`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient\nfunctions that refer to given allocation object: vmaFlushAllocation(),\nvmaInvalidateAllocation(),\nor multiple objects at once: vmaFlushAllocations(), vmaInvalidateAllocations().\n\nRegions of memory specified for flush/invalidate must be aligned to\n`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.\nIn any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations\nwithin blocks are aligned to this value, so their offsets are always multiply of\n`nonCoherentAtomSize` and two different allocations never share same \"line\" of this size.\n\nAlso, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA)\ncurrently provide `HOST_COHERENT` flag on all memory types that are\n`HOST_VISIBLE`, so on PC you may not need to bother.\n\n\n\\page staying_within_budget Staying within budget\n\nWhen developing a graphics-intensive game or program, it is important to avoid allocating\nmore GPU memory than it is physically available. When the memory is over-committed,\nvarious bad things can happen, depending on the specific GPU, graphics driver, and\noperating system:\n\n- It may just work without any problems.\n- The application may slow down because some memory blocks are moved to system RAM\n  and the GPU has to access them through PCI Express bus.\n- A new allocation may take very long time to complete, even few seconds, and possibly\n  freeze entire system.\n- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.\n- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST`\n  returned somewhere later.\n\n\\section staying_within_budget_querying_for_budget Querying for budget\n\nTo query for current memory usage and available budget, use function vmaGetHeapBudgets().\nReturned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap.\n\nPlease note that this function returns different information and works faster than\nvmaCalculateStatistics(). vmaGetHeapBudgets() can be called every frame or even before every\nallocation, while vmaCalculateStatistics() is intended to be used rarely,\nonly to obtain statistical information, e.g. for debugging purposes.\n\nIt is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information\nabout the budget from Vulkan device. VMA is able to use this extension automatically.\nWhen not enabled, the allocator behaves same way, but then it estimates current usage\nand available budget based on its internal information and Vulkan memory heap sizes,\nwhich may be less precise. In order to use this extension:\n\n1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2\n   required by it are available and enable them. Please note that the first is a device\n   extension and the second is instance extension!\n2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object.\n3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from\n   Vulkan inside of it to avoid overhead of querying it with every allocation.\n\n\\section staying_within_budget_controlling_memory_usage Controlling memory usage\n\nThere are many ways in which you can try to stay within the budget.\n\nFirst, when making new allocation requires allocating a new memory block, the library\ntries not to exceed the budget automatically. If a block with default recommended size\n(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even\ndedicated memory for just this resource.\n\nIf the size of the requested resource plus current memory usage is more than the\nbudget, by default the library still tries to create it, leaving it to the Vulkan\nimplementation whether the allocation succeeds or fails. You can change this behavior\nby using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is\nnot made if it would exceed the budget or if the budget is already exceeded.\nVMA then tries to make the allocation from the next eligible Vulkan memory type.\nThe all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.\nExample usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag\nwhen creating resources that are not essential for the application (e.g. the texture\nof a specific object) and not to pass it when creating critically important resources\n(e.g. render targets).\n\nOn AMD graphics cards there is a custom vendor extension available: <b>VK_AMD_memory_overallocation_behavior</b>\nthat allows to control the behavior of the Vulkan implementation in out-of-memory cases -\nwhether it should fail with an error code or still allow the allocation.\nUsage of this extension involves only passing extra structure on Vulkan device creation,\nso it is out of scope of this library.\n\nFinally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure\na new allocation is created only when it fits inside one of the existing memory blocks.\nIf it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.\nThis also ensures that the function call is very fast because it never goes to Vulkan\nto obtain a new block.\n\n\\note Creating \\ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount\nset to more than 0 will currently try to allocate memory blocks without checking whether they\nfit within budget.\n\n\n\\page resource_aliasing Resource aliasing (overlap)\n\nNew explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory\nmanagement, give an opportunity to alias (overlap) multiple resources in the\nsame region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL).\nIt can be useful to save video memory, but it must be used with caution.\n\nFor example, if you know the flow of your whole render frame in advance, you\nare going to use some intermediate textures or buffers only during a small range of render passes,\nand you know these ranges don't overlap in time, you can bind these resources to\nthe same place in memory, even if they have completely different parameters (width, height, format etc.).\n\n![Resource aliasing (overlap)](../gfx/Aliasing.png)\n\nSuch scenario is possible using VMA, but you need to create your images manually.\nThen you need to calculate parameters of an allocation to be made using formula:\n\n- allocation size = max(size of each image)\n- allocation alignment = max(alignment of each image)\n- allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image)\n\nFollowing example shows two different images bound to the same place in memory,\nallocated to fit largest of them.\n\n\\code\n// A 512x512 texture to be sampled.\nVkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };\nimg1CreateInfo.imageType = VK_IMAGE_TYPE_2D;\nimg1CreateInfo.extent.width = 512;\nimg1CreateInfo.extent.height = 512;\nimg1CreateInfo.extent.depth = 1;\nimg1CreateInfo.mipLevels = 10;\nimg1CreateInfo.arrayLayers = 1;\nimg1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;\nimg1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;\nimg1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;\nimg1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;\nimg1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;\n\n// A full screen texture to be used as color attachment.\nVkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };\nimg2CreateInfo.imageType = VK_IMAGE_TYPE_2D;\nimg2CreateInfo.extent.width = 1920;\nimg2CreateInfo.extent.height = 1080;\nimg2CreateInfo.extent.depth = 1;\nimg2CreateInfo.mipLevels = 1;\nimg2CreateInfo.arrayLayers = 1;\nimg2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;\nimg2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;\nimg2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;\nimg2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;\nimg2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;\n\nVkImage img1;\nres = vkCreateImage(device, &img1CreateInfo, nullptr, &img1);\nVkImage img2;\nres = vkCreateImage(device, &img2CreateInfo, nullptr, &img2);\n\nVkMemoryRequirements img1MemReq;\nvkGetImageMemoryRequirements(device, img1, &img1MemReq);\nVkMemoryRequirements img2MemReq;\nvkGetImageMemoryRequirements(device, img2, &img2MemReq);\n\nVkMemoryRequirements finalMemReq = {};\nfinalMemReq.size = std::max(img1MemReq.size, img2MemReq.size);\nfinalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment);\nfinalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits & img2MemReq.memoryTypeBits;\n// Validate if(finalMemReq.memoryTypeBits != 0)\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;\n\nVmaAllocation alloc;\nres = vmaAllocateMemory(allocator, &finalMemReq, &allocCreateInfo, &alloc, nullptr);\n\nres = vmaBindImageMemory(allocator, alloc, img1);\nres = vmaBindImageMemory(allocator, alloc, img2);\n\n// You can use img1, img2 here, but not at the same time!\n\nvmaFreeMemory(allocator, alloc);\nvkDestroyImage(allocator, img2, nullptr);\nvkDestroyImage(allocator, img1, nullptr);\n\\endcode\n\nRemember that using resources that alias in memory requires proper synchronization.\nYou need to issue a memory barrier to make sure commands that use `img1` and `img2`\ndon't overlap on GPU timeline.\nYou also need to treat a resource after aliasing as uninitialized - containing garbage data.\nFor example, if you use `img1` and then want to use `img2`, you need to issue\nan image memory barrier for `img2` with `oldLayout` = `VK_IMAGE_LAYOUT_UNDEFINED`.\n\nAdditional considerations:\n\n- Vulkan also allows to interpret contents of memory between aliasing resources consistently in some cases.\nSee chapter 11.8. \"Memory Aliasing\" of Vulkan specification or `VK_IMAGE_CREATE_ALIAS_BIT` flag.\n- You can create more complex layout where different images and buffers are bound\nat different offsets inside one large allocation. For example, one can imagine\na big texture used in some render passes, aliasing with a set of many small buffers\nused between in some further passes. To bind a resource at non-zero offset in an allocation,\nuse vmaBindBufferMemory2() / vmaBindImageMemory2().\n- Before allocating memory for the resources you want to alias, check `memoryTypeBits`\nreturned in memory requirements of each resource to make sure the bits overlap.\nSome GPUs may expose multiple memory types suitable e.g. only for buffers or\nimages with `COLOR_ATTACHMENT` usage, so the sets of memory types supported by your\nresources may be disjoint. Aliasing them is not possible in that case.\n\n\n\\page custom_memory_pools Custom memory pools\n\nA memory pool contains a number of `VkDeviceMemory` blocks.\nThe library automatically creates and manages default pool for each memory type available on the device.\nDefault memory pool automatically grows in size.\nSize of allocated blocks is also variable and managed automatically.\n\nYou can create custom pool and allocate memory out of it.\nIt can be useful if you want to:\n\n- Keep certain kind of allocations separate from others.\n- Enforce particular, fixed size of Vulkan memory blocks.\n- Limit maximum amount of Vulkan memory allocated for that pool.\n- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.\n- Use extra parameters for a set of your allocations that are available in #VmaPoolCreateInfo but not in\n  #VmaAllocationCreateInfo - e.g., custom minimum alignment, custom `pNext` chain.\n- Perform defragmentation on a specific subset of your allocations.\n\nTo use custom memory pools:\n\n-# Fill VmaPoolCreateInfo structure.\n-# Call vmaCreatePool() to obtain #VmaPool handle.\n-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.\n   You don't need to specify any other parameters of this structure, like `usage`.\n\nExample:\n\n\\code\n// Find memoryTypeIndex for the pool.\nVkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nsampleBufCreateInfo.size = 0x10000; // Doesn't matter.\nsampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo sampleAllocCreateInfo = {};\nsampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\n\nuint32_t memTypeIndex;\nVkResult res = vmaFindMemoryTypeIndexForBufferInfo(allocator,\n    &sampleBufCreateInfo, &sampleAllocCreateInfo, &memTypeIndex);\n// Check res...\n\n// Create a pool that can have at most 2 blocks, 128 MiB each.\nVmaPoolCreateInfo poolCreateInfo = {};\npoolCreateInfo.memoryTypeIndex = memTypeIndex;\npoolCreateInfo.blockSize = 128ull * 1024 * 1024;\npoolCreateInfo.maxBlockCount = 2;\n\nVmaPool pool;\nres = vmaCreatePool(allocator, &poolCreateInfo, &pool);\n// Check res...\n\n// Allocate a buffer out of it.\nVkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufCreateInfo.size = 1024;\nbufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.pool = pool;\n\nVkBuffer buf;\nVmaAllocation alloc;\nres = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr);\n// Check res...\n\\endcode\n\nYou have to free all allocations made from this pool before destroying it.\n\n\\code\nvmaDestroyBuffer(allocator, buf, alloc);\nvmaDestroyPool(allocator, pool);\n\\endcode\n\nNew versions of this library support creating dedicated allocations in custom pools.\nIt is supported only when VmaPoolCreateInfo::blockSize = 0.\nTo use this feature, set VmaAllocationCreateInfo::pool to the pointer to your custom pool and\nVmaAllocationCreateInfo::flags to #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\n\n\\note Excessive use of custom pools is a common mistake when using this library.\nCustom pools may be useful for special purposes - when you want to\nkeep certain type of resources separate e.g. to reserve minimum amount of memory\nfor them or limit maximum amount of memory they can occupy. For most\nresources this is not needed and so it is not recommended to create #VmaPool\nobjects and allocations out of them. Allocating from the default pool is sufficient.\n\n\n\\section custom_memory_pools_MemTypeIndex Choosing memory type index\n\nWhen creating a pool, you must explicitly specify memory type index.\nTo find the one suitable for your buffers or images, you can use helper functions\nvmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo().\nYou need to provide structures with example parameters of buffers or images\nthat you are going to create in that pool.\n\n\\code\nVkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nexampleBufCreateInfo.size = 1024; // Doesn't matter\nexampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\n\nuint32_t memTypeIndex;\nvmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex);\n\nVmaPoolCreateInfo poolCreateInfo = {};\npoolCreateInfo.memoryTypeIndex = memTypeIndex;\n// ...\n\\endcode\n\nWhen creating buffers/images allocated in that pool, provide following parameters:\n\n- `VkBufferCreateInfo`: Prefer to pass same parameters as above.\n  Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior.\n  Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers\n  or the other way around.\n- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member.\n  Other members are ignored anyway.\n\n\\section linear_algorithm Linear allocation algorithm\n\nEach Vulkan memory block managed by this library has accompanying metadata that\nkeeps track of used and unused regions. By default, the metadata structure and\nalgorithm tries to find best place for new allocations among free regions to\noptimize memory usage. This way you can allocate and free objects in any order.\n\n![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)\n\nSometimes there is a need to use simpler, linear allocation algorithm. You can\ncreate custom pool that uses such algorithm by adding flag\n#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating\n#VmaPool object. Then an alternative metadata management is used. It always\ncreates new allocations after last one and doesn't reuse free regions after\nallocations freed in the middle. It results in better allocation performance and\nless memory consumed by metadata.\n\n![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)\n\nWith this one flag, you can create a custom pool that can be used in many ways:\nfree-at-once, stack, double stack, and ring buffer. See below for details.\nYou don't need to specify explicitly which of these options you are going to use - it is detected automatically.\n\n\\subsection linear_algorithm_free_at_once Free-at-once\n\nIn a pool that uses linear algorithm, you still need to free all the allocations\nindividually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free\nthem in any order. New allocations are always made after last one - free space\nin the middle is not reused. However, when you release all the allocation and\nthe pool becomes empty, allocation starts from the beginning again. This way you\ncan use linear algorithm to speed up creation of allocations that you are going\nto release all at once.\n\n![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)\n\nThis mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount\nvalue that allows multiple memory blocks.\n\n\\subsection linear_algorithm_stack Stack\n\nWhen you free an allocation that was created last, its space can be reused.\nThanks to this, if you always release allocations in the order opposite to their\ncreation (LIFO - Last In First Out), you can achieve behavior of a stack.\n\n![Stack](../gfx/Linear_allocator_4_stack.png)\n\nThis mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount\nvalue that allows multiple memory blocks.\n\n\\subsection linear_algorithm_double_stack Double stack\n\nThe space reserved by a custom pool with linear algorithm may be used by two\nstacks:\n\n- First, default one, growing up from offset 0.\n- Second, \"upper\" one, growing down from the end towards lower offsets.\n\nTo make allocation from the upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT\nto VmaAllocationCreateInfo::flags.\n\n![Double stack](../gfx/Linear_allocator_7_double_stack.png)\n\nDouble stack is available only in pools with one memory block -\nVmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.\n\nWhen the two stacks' ends meet so there is not enough space between them for a\nnew allocation, such allocation fails with usual\n`VK_ERROR_OUT_OF_DEVICE_MEMORY` error.\n\n\\subsection linear_algorithm_ring_buffer Ring buffer\n\nWhen you free some allocations from the beginning and there is not enough free space\nfor a new one at the end of a pool, allocator's \"cursor\" wraps around to the\nbeginning and starts allocation there. Thanks to this, if you always release\nallocations in the same order as you created them (FIFO - First In First Out),\nyou can achieve behavior of a ring buffer / queue.\n\n![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)\n\nRing buffer is available only in pools with one memory block -\nVmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.\n\n\\note \\ref defragmentation is not supported in custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT.\n\n\n\\page defragmentation Defragmentation\n\nInterleaved allocations and deallocations of many objects of varying size can\ncause fragmentation over time, which can lead to a situation where the library is unable\nto find a continuous range of free memory for a new allocation despite there is\nenough free space, just scattered across many small free ranges between existing\nallocations.\n\nTo mitigate this problem, you can use defragmentation feature.\nIt doesn't happen automatically though and needs your cooperation,\nbecause VMA is a low level library that only allocates memory.\nIt cannot recreate buffers and images in a new place as it doesn't remember the contents of `VkBufferCreateInfo` / `VkImageCreateInfo` structures.\nIt cannot copy their contents as it doesn't record any commands to a command buffer.\n\nExample:\n\n\\code\nVmaDefragmentationInfo defragInfo = {};\ndefragInfo.pool = myPool;\ndefragInfo.flags = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT;\n\nVmaDefragmentationContext defragCtx;\nVkResult res = vmaBeginDefragmentation(allocator, &defragInfo, &defragCtx);\n// Check res...\n\nfor(;;)\n{\n    VmaDefragmentationPassMoveInfo pass;\n    res = vmaBeginDefragmentationPass(allocator, defragCtx, &pass);\n    if(res == VK_SUCCESS)\n        break;\n    else if(res != VK_INCOMPLETE)\n        // Handle error...\n\n    for(uint32_t i = 0; i < pass.moveCount; ++i)\n    {\n        // Inspect pass.pMoves[i].srcAllocation, identify what buffer/image it represents.\n        VmaAllocationInfo allocInfo;\n        vmaGetAllocationInfo(allocator, pass.pMoves[i].srcAllocation, &allocInfo);\n        MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData;\n\n        // Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.\n        VkImageCreateInfo imgCreateInfo = ...\n        VkImage newImg;\n        res = vkCreateImage(device, &imgCreateInfo, nullptr, &newImg);\n        // Check res...\n        res = vmaBindImageMemory(allocator, pass.pMoves[i].dstTmpAllocation, newImg);\n        // Check res...\n\n        // Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.\n        vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...);\n    }\n\n    // Make sure the copy commands finished executing.\n    vkWaitForFences(...);\n\n    // Destroy old buffers/images bound with pass.pMoves[i].srcAllocation.\n    for(uint32_t i = 0; i < pass.moveCount; ++i)\n    {\n        // ...\n        vkDestroyImage(device, resData->img, nullptr);\n    }\n\n    // Update appropriate descriptors to point to the new places...\n\n    res = vmaEndDefragmentationPass(allocator, defragCtx, &pass);\n    if(res == VK_SUCCESS)\n        break;\n    else if(res != VK_INCOMPLETE)\n        // Handle error...\n}\n\nvmaEndDefragmentation(allocator, defragCtx, nullptr);\n\\endcode\n\nAlthough functions like vmaCreateBuffer(), vmaCreateImage(), vmaDestroyBuffer(), vmaDestroyImage()\ncreate/destroy an allocation and a buffer/image at once, these are just a shortcut for\ncreating the resource, allocating memory, and binding them together.\nDefragmentation works on memory allocations only. You must handle the rest manually.\nDefragmentation is an iterative process that should repreat \"passes\" as long as related functions\nreturn `VK_INCOMPLETE` not `VK_SUCCESS`.\nIn each pass:\n\n1. vmaBeginDefragmentationPass() function call:\n   - Calculates and returns the list of allocations to be moved in this pass.\n     Note this can be a time-consuming process.\n   - Reserves destination memory for them by creating temporary destination allocations\n     that you can query for their `VkDeviceMemory` + offset using vmaGetAllocationInfo().\n2. Inside the pass, **you should**:\n   - Inspect the returned list of allocations to be moved.\n   - Create new buffers/images and bind them at the returned destination temporary allocations.\n   - Copy data from source to destination resources if necessary.\n   - Destroy the source buffers/images, but NOT their allocations.\n3. vmaEndDefragmentationPass() function call:\n   - Frees the source memory reserved for the allocations that are moved.\n   - Modifies source #VmaAllocation objects that are moved to point to the destination reserved memory.\n   - Frees `VkDeviceMemory` blocks that became empty.\n\nUnlike in previous iterations of the defragmentation API, there is no list of \"movable\" allocations passed as a parameter.\nDefragmentation algorithm tries to move all suitable allocations.\nYou can, however, refuse to move some of them inside a defragmentation pass, by setting\n`pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE.\nThis is not recommended and may result in suboptimal packing of the allocations after defragmentation.\nIf you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.\n\nInside a pass, for each allocation that should be moved:\n\n- You should copy its data from the source to the destination place by calling e.g. `vkCmdCopyBuffer()`, `vkCmdCopyImage()`.\n  - You need to make sure these commands finished executing before destroying the source buffers/images and before calling vmaEndDefragmentationPass().\n- If a resource doesn't contain any meaningful data, e.g. it is a transient color attachment image to be cleared,\n  filled, and used temporarily in each rendering frame, you can just recreate this image\n  without copying its data.\n- If the resource is in `HOST_VISIBLE` and `HOST_CACHED` memory, you can copy its data on the CPU\n  using `memcpy()`.\n- If you cannot move the allocation, you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE.\n  This will cancel the move.\n  - vmaEndDefragmentationPass() will then free the destination memory\n    not the source memory of the allocation, leaving it unchanged.\n- If you decide the allocation is unimportant and can be destroyed instead of moved (e.g. it wasn't used for long time),\n  you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY.\n  - vmaEndDefragmentationPass() will then free both source and destination memory, and will destroy the source #VmaAllocation object.\n\nYou can defragment a specific custom pool by setting VmaDefragmentationInfo::pool\n(like in the example above) or all the default pools by setting this member to null.\n\nDefragmentation is always performed in each pool separately.\nAllocations are never moved between different Vulkan memory types.\nThe size of the destination memory reserved for a moved allocation is the same as the original one.\nAlignment of an allocation as it was determined using `vkGetBufferMemoryRequirements()` etc. is also respected after defragmentation.\nBuffers/images should be recreated with the same `VkBufferCreateInfo` / `VkImageCreateInfo` parameters as the original ones.\n\nYou can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved\nin each pass, e.g. to call it in sync with render frames and not to experience too big hitches.\nSee members: VmaDefragmentationInfo::maxBytesPerPass, VmaDefragmentationInfo::maxAllocationsPerPass.\n\nIt is also safe to perform the defragmentation asynchronously to render frames and other Vulkan and VMA\nusage, possibly from multiple threads, with the exception that allocations\nreturned in VmaDefragmentationPassMoveInfo::pMoves shouldn't be destroyed until the defragmentation pass is ended.\n\n<b>Mapping</b> is preserved on allocations that are moved during defragmentation.\nWhether through #VMA_ALLOCATION_CREATE_MAPPED_BIT or vmaMapMemory(), the allocations\nare mapped at their new place. Of course, pointer to the mapped data changes, so it needs to be queried\nusing VmaAllocationInfo::pMappedData.\n\n\\note Defragmentation is not supported in custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT.\n\n\n\\page statistics Statistics\n\nThis library contains several functions that return information about its internal state,\nespecially the amount of memory allocated from Vulkan.\n\n\\section statistics_numeric_statistics Numeric statistics\n\nIf you need to obtain basic statistics about memory usage per heap, together with current budget,\nyou can call function vmaGetHeapBudgets() and inspect structure #VmaBudget.\nThis is useful to keep track of memory usage and stay within budget\n(see also \\ref staying_within_budget).\nExample:\n\n\\code\nuint32_t heapIndex = ...\n\nVmaBudget budgets[VK_MAX_MEMORY_HEAPS];\nvmaGetHeapBudgets(allocator, budgets);\n\nprintf(\"My heap currently has %u allocations taking %llu B,\\n\",\n    budgets[heapIndex].statistics.allocationCount,\n    budgets[heapIndex].statistics.allocationBytes);\nprintf(\"allocated out of %u Vulkan device memory blocks taking %llu B,\\n\",\n    budgets[heapIndex].statistics.blockCount,\n    budgets[heapIndex].statistics.blockBytes);\nprintf(\"Vulkan reports total usage %llu B with budget %llu B.\\n\",\n    budgets[heapIndex].usage,\n    budgets[heapIndex].budget);\n\\endcode\n\nYou can query for more detailed statistics per memory heap, type, and totals,\nincluding minimum and maximum allocation size and unused range size,\nby calling function vmaCalculateStatistics() and inspecting structure #VmaTotalStatistics.\nThis function is slower though, as it has to traverse all the internal data structures,\nso it should be used only for debugging purposes.\n\nYou can query for statistics of a custom pool using function vmaGetPoolStatistics()\nor vmaCalculatePoolStatistics().\n\nYou can query for information about a specific allocation using function vmaGetAllocationInfo().\nIt fill structure #VmaAllocationInfo.\n\n\\section statistics_json_dump JSON dump\n\nYou can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString().\nThe result is guaranteed to be correct JSON.\nIt uses ANSI encoding.\nAny strings provided by user (see [Allocation names](@ref allocation_names))\nare copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding,\nthis JSON string can be treated as using this encoding.\nIt must be freed using function vmaFreeStatsString().\n\nThe format of this JSON string is not part of official documentation of the library,\nbut it will not change in backward-incompatible way without increasing library major version number\nand appropriate mention in changelog.\n\nThe JSON string contains all the data that can be obtained using vmaCalculateStatistics().\nIt can also contain detailed map of allocated memory blocks and their regions -\nfree and occupied by allocations.\nThis allows e.g. to visualize the memory or assess fragmentation.\n\n\n\\page allocation_annotation Allocation names and user data\n\n\\section allocation_user_data Allocation user data\n\nYou can annotate allocations with your own information, e.g. for debugging purposes.\nTo do that, fill VmaAllocationCreateInfo::pUserData field when creating\nan allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer,\nsome handle, index, key, ordinal number or any other value that would associate\nthe allocation with your custom metadata.\nIt is useful to identify appropriate data structures in your engine given #VmaAllocation,\ne.g. when doing \\ref defragmentation.\n\n\\code\nVkBufferCreateInfo bufCreateInfo = ...\n\nMyBufferMetadata* pMetadata = CreateBufferMetadata();\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.pUserData = pMetadata;\n\nVkBuffer buffer;\nVmaAllocation allocation;\nvmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buffer, &allocation, nullptr);\n\\endcode\n\nThe pointer may be later retrieved as VmaAllocationInfo::pUserData:\n\n\\code\nVmaAllocationInfo allocInfo;\nvmaGetAllocationInfo(allocator, allocation, &allocInfo);\nMyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData;\n\\endcode\n\nIt can also be changed using function vmaSetAllocationUserData().\n\nValues of (non-zero) allocations' `pUserData` are printed in JSON report created by\nvmaBuildStatsString() in hexadecimal form.\n\n\\section allocation_names Allocation names\n\nAn allocation can also carry a null-terminated string, giving a name to the allocation.\nTo set it, call vmaSetAllocationName().\nThe library creates internal copy of the string, so the pointer you pass doesn't need\nto be valid for whole lifetime of the allocation. You can free it after the call.\n\n\\code\nstd::string imageName = \"Texture: \";\nimageName += fileName;\nvmaSetAllocationName(allocator, allocation, imageName.c_str());\n\\endcode\n\nThe string can be later retrieved by inspecting VmaAllocationInfo::pName.\nIt is also printed in JSON report created by vmaBuildStatsString().\n\n\\note Setting string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it.\nYou must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.\n\n\n\\page virtual_allocator Virtual allocator\n\nAs an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of \"virtual allocator\".\nIt doesn't allocate any real GPU memory. It just keeps track of used and free regions of a \"virtual block\".\nYou can use it to allocate your own memory or other objects, even completely unrelated to Vulkan.\nA common use case is sub-allocation of pieces of one large GPU buffer.\n\n\\section virtual_allocator_creating_virtual_block Creating virtual block\n\nTo use this functionality, there is no main \"allocator\" object.\nYou don't need to have #VmaAllocator object created.\nAll you need to do is to create a separate #VmaVirtualBlock object for each block of memory you want to be managed by the allocator:\n\n-# Fill in #VmaVirtualBlockCreateInfo structure.\n-# Call vmaCreateVirtualBlock(). Get new #VmaVirtualBlock object.\n\nExample:\n\n\\code\nVmaVirtualBlockCreateInfo blockCreateInfo = {};\nblockCreateInfo.size = 1048576; // 1 MB\n\nVmaVirtualBlock block;\nVkResult res = vmaCreateVirtualBlock(&blockCreateInfo, &block);\n\\endcode\n\n\\section virtual_allocator_making_virtual_allocations Making virtual allocations\n\n#VmaVirtualBlock object contains internal data structure that keeps track of free and occupied regions\nusing the same code as the main Vulkan memory allocator.\nSimilarly to #VmaAllocation for standard GPU allocations, there is #VmaVirtualAllocation type\nthat represents an opaque handle to an allocation within the virtual block.\n\nIn order to make such allocation:\n\n-# Fill in #VmaVirtualAllocationCreateInfo structure.\n-# Call vmaVirtualAllocate(). Get new #VmaVirtualAllocation object that represents the allocation.\n   You can also receive `VkDeviceSize offset` that was assigned to the allocation.\n\nExample:\n\n\\code\nVmaVirtualAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.size = 4096; // 4 KB\n\nVmaVirtualAllocation alloc;\nVkDeviceSize offset;\nres = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, &offset);\nif(res == VK_SUCCESS)\n{\n    // Use the 4 KB of your memory starting at offset.\n}\nelse\n{\n    // Allocation failed - no space for it could be found. Handle this error!\n}\n\\endcode\n\n\\section virtual_allocator_deallocation Deallocation\n\nWhen no longer needed, an allocation can be freed by calling vmaVirtualFree().\nYou can only pass to this function an allocation that was previously returned by vmaVirtualAllocate()\ncalled for the same #VmaVirtualBlock.\n\nWhen whole block is no longer needed, the block object can be released by calling vmaDestroyVirtualBlock().\nAll allocations must be freed before the block is destroyed, which is checked internally by an assert.\nHowever, if you don't want to call vmaVirtualFree() for each allocation, you can use vmaClearVirtualBlock() to free them all at once -\na feature not available in normal Vulkan memory allocator. Example:\n\n\\code\nvmaVirtualFree(block, alloc);\nvmaDestroyVirtualBlock(block);\n\\endcode\n\n\\section virtual_allocator_allocation_parameters Allocation parameters\n\nYou can attach a custom pointer to each allocation by using vmaSetVirtualAllocationUserData().\nIts default value is null.\nIt can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some\nlarger data structure containing more information. Example:\n\n\\code\nstruct CustomAllocData\n{\n    std::string m_AllocName;\n};\nCustomAllocData* allocData = new CustomAllocData();\nallocData->m_AllocName = \"My allocation 1\";\nvmaSetVirtualAllocationUserData(block, alloc, allocData);\n\\endcode\n\nThe pointer can later be fetched, along with allocation offset and size, by passing the allocation handle to function\nvmaGetVirtualAllocationInfo() and inspecting returned structure #VmaVirtualAllocationInfo.\nIf you allocated a new object to be used as the custom pointer, don't forget to delete that object before freeing the allocation!\nExample:\n\n\\code\nVmaVirtualAllocationInfo allocInfo;\nvmaGetVirtualAllocationInfo(block, alloc, &allocInfo);\ndelete (CustomAllocData*)allocInfo.pUserData;\n\nvmaVirtualFree(block, alloc);\n\\endcode\n\n\\section virtual_allocator_alignment_and_units Alignment and units\n\nIt feels natural to express sizes and offsets in bytes.\nIf an offset of an allocation needs to be aligned to a multiply of some number (e.g. 4 bytes), you can fill optional member\nVmaVirtualAllocationCreateInfo::alignment to request it. Example:\n\n\\code\nVmaVirtualAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.size = 4096; // 4 KB\nallocCreateInfo.alignment = 4; // Returned offset must be a multiply of 4 B\n\nVmaVirtualAllocation alloc;\nres = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, nullptr);\n\\endcode\n\nAlignments of different allocations made from one block may vary.\nHowever, if all alignments and sizes are always multiply of some size e.g. 4 B or `sizeof(MyDataStruct)`,\nyou can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes.\nIt might be more convenient, but you need to make sure to use this new unit consistently in all the places:\n\n- VmaVirtualBlockCreateInfo::size\n- VmaVirtualAllocationCreateInfo::size and VmaVirtualAllocationCreateInfo::alignment\n- Using offset returned by vmaVirtualAllocate() or in VmaVirtualAllocationInfo::offset\n\n\\section virtual_allocator_statistics Statistics\n\nYou can obtain statistics of a virtual block using vmaGetVirtualBlockStatistics()\n(to get brief statistics that are fast to calculate)\nor vmaCalculateVirtualBlockStatistics() (to get more detailed statistics, slower to calculate).\nThe functions fill structures #VmaStatistics, #VmaDetailedStatistics respectively - same as used by the normal Vulkan memory allocator.\nExample:\n\n\\code\nVmaStatistics stats;\nvmaGetVirtualBlockStatistics(block, &stats);\nprintf(\"My virtual block has %llu bytes used by %u virtual allocations\\n\",\n    stats.allocationBytes, stats.allocationCount);\n\\endcode\n\nYou can also request a full list of allocations and free regions as a string in JSON format by calling\nvmaBuildVirtualBlockStatsString().\nReturned string must be later freed using vmaFreeVirtualBlockStatsString().\nThe format of this string differs from the one returned by the main Vulkan allocator, but it is similar.\n\n\\section virtual_allocator_additional_considerations Additional considerations\n\nThe \"virtual allocator\" functionality is implemented on a level of individual memory blocks.\nKeeping track of a whole collection of blocks, allocating new ones when out of free space,\ndeleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user.\n\nAlternative allocation algorithms are supported, just like in custom pools of the real GPU memory.\nSee enum #VmaVirtualBlockCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT).\nYou can find their description in chapter \\ref custom_memory_pools.\nAllocation strategies are also supported.\nSee enum #VmaVirtualAllocationCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT).\n\nFollowing features are supported only by the allocator of the real GPU memory and not by virtual allocations:\nbuffer-image granularity, `VMA_DEBUG_MARGIN`, `VMA_MIN_ALIGNMENT`.\n\n\n\\page debugging_memory_usage Debugging incorrect memory usage\n\nIf you suspect a bug with memory usage, like usage of uninitialized memory or\nmemory being overwritten out of bounds of an allocation,\nyou can use debug features of this library to verify this.\n\n\\section debugging_memory_usage_initialization Memory initialization\n\nIf you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,\nyou can enable automatic memory initialization to verify this.\nTo do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.\n\n\\code\n#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1\n#include \"vk_mem_alloc.h\"\n\\endcode\n\nIt makes memory of new allocations initialized to bit pattern `0xDCDCDCDC`.\nBefore an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.\nMemory is automatically mapped and unmapped if necessary.\n\nIf you find these values while debugging your program, good chances are that you incorrectly\nread Vulkan memory that is allocated but not initialized, or already freed, respectively.\n\nMemory initialization works only with memory types that are `HOST_VISIBLE` and with allocations that can be mapped.\nIt works also with dedicated allocations.\n\n\\section debugging_memory_usage_margins Margins\n\nBy default, allocations are laid out in memory blocks next to each other if possible\n(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`).\n\n![Allocations without margin](../gfx/Margins_1.png)\n\nDefine macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified\nnumber of bytes as a margin after every allocation.\n\n\\code\n#define VMA_DEBUG_MARGIN 16\n#include \"vk_mem_alloc.h\"\n\\endcode\n\n![Allocations with margin](../gfx/Margins_2.png)\n\nIf your bug goes away after enabling margins, it means it may be caused by memory\nbeing overwritten outside of allocation boundaries. It is not 100% certain though.\nChange in application behavior may also be caused by different order and distribution\nof allocations across memory blocks after margins are applied.\n\nMargins work with all types of memory.\n\nMargin is applied only to allocations made out of memory blocks and not to dedicated\nallocations, which have their own memory block of specific size.\nIt is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag\nor those automatically decided to put into dedicated allocations, e.g. due to its\nlarge size or recommended by VK_KHR_dedicated_allocation extension.\n\nMargins appear in [JSON dump](@ref statistics_json_dump) as part of free space.\n\nNote that enabling margins increases memory usage and fragmentation.\n\nMargins do not apply to \\ref virtual_allocator.\n\n\\section debugging_memory_usage_corruption_detection Corruption detection\n\nYou can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation\nof contents of the margins.\n\n\\code\n#define VMA_DEBUG_MARGIN 16\n#define VMA_DEBUG_DETECT_CORRUPTION 1\n#include \"vk_mem_alloc.h\"\n\\endcode\n\nWhen this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN`\n(it must be multiply of 4) after every allocation is filled with a magic number.\nThis idea is also know as \"canary\".\nMemory is automatically mapped and unmapped if necessary.\n\nThis number is validated automatically when the allocation is destroyed.\nIf it is not equal to the expected value, `VMA_ASSERT()` is executed.\nIt clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation,\nwhich indicates a serious bug.\n\nYou can also explicitly request checking margins of all allocations in all memory blocks\nthat belong to specified memory types by using function vmaCheckCorruption(),\nor in memory blocks that belong to specified custom pool, by using function\nvmaCheckPoolCorruption().\n\nMargin validation (corruption detection) works only for memory types that are\n`HOST_VISIBLE` and `HOST_COHERENT`.\n\n\n\\page opengl_interop OpenGL Interop\n\nVMA provides some features that help with interoperability with OpenGL.\n\n\\section opengl_interop_exporting_memory Exporting memory\n\nIf you want to attach `VkExportMemoryAllocateInfoKHR` structure to `pNext` chain of memory allocations made by the library:\n\nIt is recommended to create \\ref custom_memory_pools for such allocations.\nDefine and fill in your `VkExportMemoryAllocateInfoKHR` structure and attach it to VmaPoolCreateInfo::pMemoryAllocateNext\nwhile creating the custom pool.\nPlease note that the structure must remain alive and unchanged for the whole lifetime of the #VmaPool,\nnot only while creating it, as no copy of the structure is made,\nbut its original pointer is used for each allocation instead.\n\nIf you want to export all memory allocated by the library from certain memory types,\nalso dedicated allocations or other allocations made from default pools,\nan alternative solution is to fill in VmaAllocatorCreateInfo::pTypeExternalMemoryHandleTypes.\nIt should point to an array with `VkExternalMemoryHandleTypeFlagsKHR` to be automatically passed by the library\nthrough `VkExportMemoryAllocateInfoKHR` on each allocation made from a specific memory type.\nPlease note that new versions of the library also support dedicated allocations created in custom pools.\n\nYou should not mix these two methods in a way that allows to apply both to the same memory type.\nOtherwise, `VkExportMemoryAllocateInfoKHR` structure would be attached twice to the `pNext` chain of `VkMemoryAllocateInfo`.\n\n\n\\section opengl_interop_custom_alignment Custom alignment\n\nBuffers or images exported to a different API like OpenGL may require a different alignment,\nhigher than the one used by the library automatically, queried from functions like `vkGetBufferMemoryRequirements`.\nTo impose such alignment:\n\nIt is recommended to create \\ref custom_memory_pools for such allocations.\nSet VmaPoolCreateInfo::minAllocationAlignment member to the minimum alignment required for each allocation\nto be made out of this pool.\nThe alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image\nfrom a function like `vkGetBufferMemoryRequirements`, which is called by VMA automatically.\n\nIf you want to create a buffer with a specific minimum alignment out of default pools,\nuse special function vmaCreateBufferWithAlignment(), which takes additional parameter `minAlignment`.\n\nNote the problem of alignment affects only resources placed inside bigger `VkDeviceMemory` blocks and not dedicated\nallocations, as these, by definition, always have alignment = 0 because the resource is bound to the beginning of its dedicated block.\nContrary to Direct3D 12, Vulkan doesn't have a concept of alignment of the entire memory block passed on its allocation.\n\n\n\\page usage_patterns Recommended usage patterns\n\nVulkan gives great flexibility in memory allocation.\nThis chapter shows the most common patterns.\n\nSee also slides from talk:\n[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New)\n\n\n\\section usage_patterns_gpu_only GPU-only resource\n\n<b>When:</b>\nAny resources that you frequently write and read on GPU,\ne.g. images used as color attachments (aka \"render targets\"), depth-stencil attachments,\nimages/buffers used as storage image/buffer (aka \"Unordered Access View (UAV)\").\n\n<b>What to do:</b>\nLet the library select the optimal memory type, which will likely have `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.\n\n\\code\nVkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };\nimgCreateInfo.imageType = VK_IMAGE_TYPE_2D;\nimgCreateInfo.extent.width = 3840;\nimgCreateInfo.extent.height = 2160;\nimgCreateInfo.extent.depth = 1;\nimgCreateInfo.mipLevels = 1;\nimgCreateInfo.arrayLayers = 1;\nimgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;\nimgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;\nimgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;\nimgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;\nimgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;\nallocCreateInfo.priority = 1.0f;\n\nVkImage img;\nVmaAllocation alloc;\nvmaCreateImage(allocator, &imgCreateInfo, &allocCreateInfo, &img, &alloc, nullptr);\n\\endcode\n\n<b>Also consider:</b>\nConsider creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,\nespecially if they are large or if you plan to destroy and recreate them with different sizes\ne.g. when display resolution changes.\nPrefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.\nWhen VK_EXT_memory_priority extension is enabled, it is also worth setting high priority to such allocation\nto decrease chances to be evicted to system memory by the operating system.\n\n\\section usage_patterns_staging_copy_upload Staging copy for upload\n\n<b>When:</b>\nA \"staging\" buffer than you want to map and fill from CPU code, then use as a source of transfer\nto some GPU resource.\n\n<b>What to do:</b>\nUse flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT.\nLet the library select the optimal memory type, which will always have `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`.\n\n\\code\nVkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufCreateInfo.size = 65536;\nbufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |\n    VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\nVkBuffer buf;\nVmaAllocation alloc;\nVmaAllocationInfo allocInfo;\nvmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);\n\n...\n\nmemcpy(allocInfo.pMappedData, myData, myDataSize);\n\\endcode\n\n<b>Also consider:</b>\nYou can map the allocation using vmaMapMemory() or you can create it as persistenly mapped\nusing #VMA_ALLOCATION_CREATE_MAPPED_BIT, as in the example above.\n\n\n\\section usage_patterns_readback Readback\n\n<b>When:</b>\nBuffers for data written by or transferred from the GPU that you want to read back on the CPU,\ne.g. results of some computations.\n\n<b>What to do:</b>\nUse flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.\nLet the library select the optimal memory type, which will always have `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`\nand `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`.\n\n\\code\nVkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufCreateInfo.size = 65536;\nbufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT |\n    VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\nVkBuffer buf;\nVmaAllocation alloc;\nVmaAllocationInfo allocInfo;\nvmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);\n\n...\n\nconst float* downloadedData = (const float*)allocInfo.pMappedData;\n\\endcode\n\n\n\\section usage_patterns_advanced_data_uploading Advanced data uploading\n\nFor resources that you frequently write on CPU via mapped pointer and\nfrequently read on GPU e.g. as a uniform buffer (also called \"dynamic\"), multiple options are possible:\n\n-# Easiest solution is to have one copy of the resource in `HOST_VISIBLE` memory,\n   even if it means system RAM (not `DEVICE_LOCAL`) on systems with a discrete graphics card,\n   and make the device reach out to that resource directly.\n   - Reads performed by the device will then go through PCI Express bus.\n     The performance of this access may be limited, but it may be fine depending on the size\n     of this resource (whether it is small enough to quickly end up in GPU cache) and the sparsity\n     of access.\n-# On systems with unified memory (e.g. AMD APU or Intel integrated graphics, mobile chips),\n   a memory type may be available that is both `HOST_VISIBLE` (available for mapping) and `DEVICE_LOCAL`\n   (fast to access from the GPU). Then, it is likely the best choice for such type of resource.\n-# Systems with a discrete graphics card and separate video memory may or may not expose\n   a memory type that is both `HOST_VISIBLE` and `DEVICE_LOCAL`, also known as Base Address Register (BAR).\n   If they do, it represents a piece of VRAM (or entire VRAM, if ReBAR is enabled in the motherboard BIOS)\n   that is available to CPU for mapping.\n   - Writes performed by the host to that memory go through PCI Express bus.\n     The performance of these writes may be limited, but it may be fine, especially on PCIe 4.0,\n     as long as rules of using uncached and write-combined memory are followed - only sequential writes and no reads.\n-# Finally, you may need or prefer to create a separate copy of the resource in `DEVICE_LOCAL` memory,\n   a separate \"staging\" copy in `HOST_VISIBLE` memory and perform an explicit transfer command between them.\n\nThankfully, VMA offers an aid to create and use such resources in the the way optimal\nfor the current Vulkan device. To help the library make the best choice,\nuse flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT together with\n#VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT.\nIt will then prefer a memory type that is both `DEVICE_LOCAL` and `HOST_VISIBLE` (integrated memory or BAR),\nbut if no such memory type is available or allocation from it fails\n(PC graphics cards have only 256 MB of BAR by default, unless ReBAR is supported and enabled in BIOS),\nit will fall back to `DEVICE_LOCAL` memory for fast GPU access.\nIt is then up to you to detect that the allocation ended up in a memory type that is not `HOST_VISIBLE`,\nso you need to create another \"staging\" allocation and perform explicit transfers.\n\n\\code\nVkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\nbufCreateInfo.size = 65536;\nbufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |\n    VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |\n    VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\nVkBuffer buf;\nVmaAllocation alloc;\nVmaAllocationInfo allocInfo;\nvmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);\n\nVkMemoryPropertyFlags memPropFlags;\nvmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags);\n\nif(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)\n{\n    // Allocation ended up in a mappable memory and is already mapped - write to it directly.\n\n    // [Executed in runtime]:\n    memcpy(allocInfo.pMappedData, myData, myDataSize);\n}\nelse\n{\n    // Allocation ended up in a non-mappable memory - need to transfer.\n    VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };\n    stagingBufCreateInfo.size = 65536;\n    stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;\n\n    VmaAllocationCreateInfo stagingAllocCreateInfo = {};\n    stagingAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\n    stagingAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |\n        VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\n    VkBuffer stagingBuf;\n    VmaAllocation stagingAlloc;\n    VmaAllocationInfo stagingAllocInfo;\n    vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,\n        &stagingBuf, &stagingAlloc, stagingAllocInfo);\n\n    // [Executed in runtime]:\n    memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);\n    //vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT\n    VkBufferCopy bufCopy = {\n        0, // srcOffset\n        0, // dstOffset,\n        myDataSize); // size\n    vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy);\n}\n\\endcode\n\n\\section usage_patterns_other_use_cases Other use cases\n\nHere are some other, less obvious use cases and their recommended settings:\n\n- An image that is used only as transfer source and destination, but it should stay on the device,\n  as it is used to temporarily store a copy of some texture, e.g. from the current to the next frame,\n  for temporal antialiasing or other temporal effects.\n  - Use `VkImageCreateInfo::usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT`\n  - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO\n- An image that is used only as transfer source and destination, but it should be placed\n  in the system RAM despite it doesn't need to be mapped, because it serves as a \"swap\" copy to evict\n  least recently used textures from VRAM.\n  - Use `VkImageCreateInfo::usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT`\n  - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO_PREFER_HOST,\n    as VMA needs a hint here to differentiate from the previous case.\n- A buffer that you want to map and write from the CPU, directly read from the GPU\n  (e.g. as a uniform or vertex buffer), but you have a clear preference to place it in device or\n  host memory due to its large size.\n  - Use `VkBufferCreateInfo::usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT`\n  - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or #VMA_MEMORY_USAGE_AUTO_PREFER_HOST\n  - Use VmaAllocationCreateInfo::flags = #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT\n\n\n\\page configuration Configuration\n\nPlease check \"CONFIGURATION SECTION\" in the code to find macros that you can define\nbefore each include of this file or change directly in this file to provide\nyour own implementation of basic facilities like assert, `min()` and `max()` functions,\nmutex, atomic etc.\nThe library uses its own implementation of containers by default, but you can switch to using\nSTL containers instead.\n\nFor example, define `VMA_ASSERT(expr)` before including the library to provide\ncustom implementation of the assertion, compatible with your project.\nBy default it is defined to standard C `assert(expr)` in `_DEBUG` configuration\nand empty otherwise.\n\n\\section config_Vulkan_functions Pointers to Vulkan functions\n\nThere are multiple ways to import pointers to Vulkan functions in the library.\nIn the simplest case you don't need to do anything.\nIf the compilation or linking of your program or the initialization of the #VmaAllocator\ndoesn't work for you, you can try to reconfigure it.\n\nFirst, the allocator tries to fetch pointers to Vulkan functions linked statically,\nlike this:\n\n\\code\nm_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;\n\\endcode\n\nIf you want to disable this feature, set configuration macro: `#define VMA_STATIC_VULKAN_FUNCTIONS 0`.\n\nSecond, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions.\nYou can fetch them e.g. using functions `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` or\nby using a helper library like [volk](https://github.com/zeux/volk).\n\nThird, VMA tries to fetch remaining pointers that are still null by calling\n`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` on its own.\nYou need to only fill in VmaVulkanFunctions::vkGetInstanceProcAddr and VmaVulkanFunctions::vkGetDeviceProcAddr.\nOther pointers will be fetched automatically.\nIf you want to disable this feature, set configuration macro: `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0`.\n\nFinally, all the function pointers required by the library (considering selected\nVulkan version and enabled extensions) are checked with `VMA_ASSERT` if they are not null.\n\n\n\\section custom_memory_allocator Custom host memory allocator\n\nIf you use custom allocator for CPU memory rather than default operator `new`\nand `delete` from C++, you can make this library using your allocator as well\nby filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These\nfunctions will be passed to Vulkan, as well as used by the library itself to\nmake any CPU-side allocations.\n\n\\section allocation_callbacks Device memory allocation callbacks\n\nThe library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.\nYou can setup callbacks to be informed about these calls, e.g. for the purpose\nof gathering some statistics. To do it, fill optional member\nVmaAllocatorCreateInfo::pDeviceMemoryCallbacks.\n\n\\section heap_memory_limit Device heap memory limit\n\nWhen device memory of certain heap runs out of free space, new allocations may\nfail (returning error code) or they may succeed, silently pushing some existing_\nmemory blocks from GPU VRAM to system RAM (which degrades performance). This\nbehavior is implementation-dependent - it depends on GPU vendor and graphics\ndriver.\n\nOn AMD cards it can be controlled while creating Vulkan device object by using\nVK_AMD_memory_overallocation_behavior extension, if available.\n\nAlternatively, if you want to test how your program behaves with limited amount of Vulkan device\nmemory available without switching your graphics card to one that really has\nsmaller VRAM, you can use a feature of this library intended for this purpose.\nTo do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.\n\n\n\n\\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation\n\nVK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve\nperformance on some GPUs. It augments Vulkan API with possibility to query\ndriver whether it prefers particular buffer or image to have its own, dedicated\nallocation (separate `VkDeviceMemory` block) for better efficiency - to be able\nto do some internal optimizations. The extension is supported by this library.\nIt will be used automatically when enabled.\n\nIt has been promoted to core Vulkan 1.1, so if you use eligible Vulkan version\nand inform VMA about it by setting VmaAllocatorCreateInfo::vulkanApiVersion,\nyou are all set.\n\nOtherwise, if you want to use it as an extension:\n\n1 . When creating Vulkan device, check if following 2 device extensions are\nsupported (call `vkEnumerateDeviceExtensionProperties()`).\nIf yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`).\n\n- VK_KHR_get_memory_requirements2\n- VK_KHR_dedicated_allocation\n\nIf you enabled these extensions:\n\n2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating\nyour #VmaAllocator to inform the library that you enabled required extensions\nand you want the library to use them.\n\n\\code\nallocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;\n\nvmaCreateAllocator(&allocatorInfo, &allocator);\n\\endcode\n\nThat is all. The extension will be automatically used whenever you create a\nbuffer using vmaCreateBuffer() or image using vmaCreateImage().\n\nWhen using the extension together with Vulkan Validation Layer, you will receive\nwarnings like this:\n\n_vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer._\n\nIt is OK, you should just ignore it. It happens because you use function\n`vkGetBufferMemoryRequirements2KHR()` instead of standard\n`vkGetBufferMemoryRequirements()`, while the validation layer seems to be\nunaware of it.\n\nTo learn more about this extension, see:\n\n- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap50.html#VK_KHR_dedicated_allocation)\n- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5)\n\n\n\n\\page vk_ext_memory_priority VK_EXT_memory_priority\n\nVK_EXT_memory_priority is a device extension that allows to pass additional \"priority\"\nvalue to Vulkan memory allocations that the implementation may use prefer certain\nbuffers and images that are critical for performance to stay in device-local memory\nin cases when the memory is over-subscribed, while some others may be moved to the system memory.\n\nVMA offers convenient usage of this extension.\nIf you enable it, you can pass \"priority\" parameter when creating allocations or custom pools\nand the library automatically passes the value to Vulkan using this extension.\n\nIf you want to use this extension in connection with VMA, follow these steps:\n\n\\section vk_ext_memory_priority_initialization Initialization\n\n1) Call `vkEnumerateDeviceExtensionProperties` for the physical device.\nCheck if the extension is supported - if returned array of `VkExtensionProperties` contains \"VK_EXT_memory_priority\".\n\n2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.\nAttach additional structure `VkPhysicalDeviceMemoryPriorityFeaturesEXT` to `VkPhysicalDeviceFeatures2::pNext` to be returned.\nCheck if the device feature is really supported - check if `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority` is true.\n\n3) While creating device with `vkCreateDevice`, enable this extension - add \"VK_EXT_memory_priority\"\nto the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.\n\n4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.\nFill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.\nEnable this device feature - attach additional structure `VkPhysicalDeviceMemoryPriorityFeaturesEXT` to\n`VkPhysicalDeviceFeatures2::pNext` chain and set its member `memoryPriority` to `VK_TRUE`.\n\n5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you\nhave enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT\nto VmaAllocatorCreateInfo::flags.\n\n\\section vk_ext_memory_priority_usage Usage\n\nWhen using this extension, you should initialize following member:\n\n- VmaAllocationCreateInfo::priority when creating a dedicated allocation with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\n- VmaPoolCreateInfo::priority when creating a custom pool.\n\nIt should be a floating-point value between `0.0f` and `1.0f`, where recommended default is `0.5f`.\nMemory allocated with higher value can be treated by the Vulkan implementation as higher priority\nand so it can have lower chances of being pushed out to system memory, experiencing degraded performance.\n\nIt might be a good idea to create performance-critical resources like color-attachment or depth-stencil images\nas dedicated and set high priority to them. For example:\n\n\\code\nVkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };\nimgCreateInfo.imageType = VK_IMAGE_TYPE_2D;\nimgCreateInfo.extent.width = 3840;\nimgCreateInfo.extent.height = 2160;\nimgCreateInfo.extent.depth = 1;\nimgCreateInfo.mipLevels = 1;\nimgCreateInfo.arrayLayers = 1;\nimgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;\nimgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;\nimgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;\nimgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;\nimgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;\n\nVmaAllocationCreateInfo allocCreateInfo = {};\nallocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;\nallocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;\nallocCreateInfo.priority = 1.0f;\n\nVkImage img;\nVmaAllocation alloc;\nvmaCreateImage(allocator, &imgCreateInfo, &allocCreateInfo, &img, &alloc, nullptr);\n\\endcode\n\n`priority` member is ignored in the following situations:\n\n- Allocations created in custom pools: They inherit the priority, along with all other allocation parameters\n  from the parametrs passed in #VmaPoolCreateInfo when the pool was created.\n- Allocations created in default pools: They inherit the priority from the parameters\n  VMA used when creating default pools, which means `priority == 0.5f`.\n\n\n\\page vk_amd_device_coherent_memory VK_AMD_device_coherent_memory\n\nVK_AMD_device_coherent_memory is a device extension that enables access to\nadditional memory types with `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and\n`VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flag. It is useful mostly for\nallocation of buffers intended for writing \"breadcrumb markers\" in between passes\nor draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases.\n\nWhen the extension is available but has not been enabled, Vulkan physical device\nstill exposes those memory types, but their usage is forbidden. VMA automatically\ntakes care of that - it returns `VK_ERROR_FEATURE_NOT_PRESENT` when an attempt\nto allocate memory of such type is made.\n\nIf you want to use this extension in connection with VMA, follow these steps:\n\n\\section vk_amd_device_coherent_memory_initialization Initialization\n\n1) Call `vkEnumerateDeviceExtensionProperties` for the physical device.\nCheck if the extension is supported - if returned array of `VkExtensionProperties` contains \"VK_AMD_device_coherent_memory\".\n\n2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.\nAttach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to `VkPhysicalDeviceFeatures2::pNext` to be returned.\nCheck if the device feature is really supported - check if `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true.\n\n3) While creating device with `vkCreateDevice`, enable this extension - add \"VK_AMD_device_coherent_memory\"\nto the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.\n\n4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.\nFill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.\nEnable this device feature - attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to\n`VkPhysicalDeviceFeatures2::pNext` and set its member `deviceCoherentMemory` to `VK_TRUE`.\n\n5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you\nhave enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT\nto VmaAllocatorCreateInfo::flags.\n\n\\section vk_amd_device_coherent_memory_usage Usage\n\nAfter following steps described above, you can create VMA allocations and custom pools\nout of the special `DEVICE_COHERENT` and `DEVICE_UNCACHED` memory types on eligible\ndevices. There are multiple ways to do it, for example:\n\n- You can request or prefer to allocate out of such memory types by adding\n  `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` to VmaAllocationCreateInfo::requiredFlags\n  or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with\n  other ways of \\ref choosing_memory_type, like setting VmaAllocationCreateInfo::usage.\n- If you manually found memory type index to use for this purpose, force allocation\n  from this specific index by setting VmaAllocationCreateInfo::memoryTypeBits `= 1u << index`.\n\n\\section vk_amd_device_coherent_memory_more_information More information\n\nTo learn more about this extension, see [VK_AMD_device_coherent_memory in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_AMD_device_coherent_memory.html)\n\nExample use of this extension can be found in the code of the sample and test suite\naccompanying this library.\n\n\n\\page enabling_buffer_device_address Enabling buffer device address\n\nDevice extension VK_KHR_buffer_device_address\nallow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code.\nIt has been promoted to core Vulkan 1.2.\n\nIf you want to use this feature in connection with VMA, follow these steps:\n\n\\section enabling_buffer_device_address_initialization Initialization\n\n1) (For Vulkan version < 1.2) Call `vkEnumerateDeviceExtensionProperties` for the physical device.\nCheck if the extension is supported - if returned array of `VkExtensionProperties` contains\n\"VK_KHR_buffer_device_address\".\n\n2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.\nAttach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to `VkPhysicalDeviceFeatures2::pNext` to be returned.\nCheck if the device feature is really supported - check if `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress` is true.\n\n3) (For Vulkan version < 1.2) While creating device with `vkCreateDevice`, enable this extension - add\n\"VK_KHR_buffer_device_address\" to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.\n\n4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.\nFill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.\nEnable this device feature - attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to\n`VkPhysicalDeviceFeatures2::pNext` and set its member `bufferDeviceAddress` to `VK_TRUE`.\n\n5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you\nhave enabled this feature - add #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT\nto VmaAllocatorCreateInfo::flags.\n\n\\section enabling_buffer_device_address_usage Usage\n\nAfter following steps described above, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA.\nThe library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to\nallocated memory blocks wherever it might be needed.\n\nPlease note that the library supports only `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*`.\nThe second part of this functionality related to \"capture and replay\" is not supported,\nas it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage.\n\n\\section enabling_buffer_device_address_more_information More information\n\nTo learn more about this extension, see [VK_KHR_buffer_device_address in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address)\n\nExample use of this extension can be found in the code of the sample and test suite\naccompanying this library.\n\n\\page general_considerations General considerations\n\n\\section general_considerations_thread_safety Thread safety\n\n- The library has no global state, so separate #VmaAllocator objects can be used\n  independently.\n  There should be no need to create multiple such objects though - one per `VkDevice` is enough.\n- By default, all calls to functions that take #VmaAllocator as first parameter\n  are safe to call from multiple threads simultaneously because they are\n  synchronized internally when needed.\n  This includes allocation and deallocation from default memory pool, as well as custom #VmaPool.\n- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT\n  flag, calls to functions that take such #VmaAllocator object must be\n  synchronized externally.\n- Access to a #VmaAllocation object must be externally synchronized. For example,\n  you must not call vmaGetAllocationInfo() and vmaMapMemory() from different\n  threads at the same time if you pass the same #VmaAllocation object to these\n  functions.\n- #VmaVirtualBlock is not safe to be used from multiple threads simultaneously.\n\n\\section general_considerations_versioning_and_compatibility Versioning and compatibility\n\nThe library uses [**Semantic Versioning**](https://semver.org/),\nwhich means version numbers follow convention: Major.Minor.Patch (e.g. 2.3.0), where:\n\n- Incremented Patch version means a release is backward- and forward-compatible,\n  introducing only some internal improvements, bug fixes, optimizations etc.\n  or changes that are out of scope of the official API described in this documentation.\n- Incremented Minor version means a release is backward-compatible,\n  so existing code that uses the library should continue to work, while some new\n  symbols could have been added: new structures, functions, new values in existing\n  enums and bit flags, new structure members, but not new function parameters.\n- Incrementing Major version means a release could break some backward compatibility.\n\nAll changes between official releases are documented in file \"CHANGELOG.md\".\n\n\\warning Backward compatibility is considered on the level of C++ source code, not binary linkage.\nAdding new members to existing structures is treated as backward compatible if initializing\nthe new members to binary zero results in the old behavior.\nYou should always fully initialize all library structures to zeros and not rely on their\nexact binary size.\n\n\\section general_considerations_validation_layer_warnings Validation layer warnings\n\nWhen using this library, you can meet following types of warnings issued by\nVulkan validation layer. They don't necessarily indicate a bug, so you may need\nto just ignore them.\n\n- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.*\n  - It happens when VK_KHR_dedicated_allocation extension is enabled.\n    `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it.\n- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.*\n  - It happens when you map a buffer or image, because the library maps entire\n    `VkDeviceMemory` block, where different types of images and buffers may end\n    up together, especially on GPUs with unified memory like Intel.\n- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.*\n  - It may happen when you use [defragmentation](@ref defragmentation).\n\n\\section general_considerations_allocation_algorithm Allocation algorithm\n\nThe library uses following algorithm for allocation, in order:\n\n-# Try to find free range of memory in existing blocks.\n-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size.\n-# If failed, try to create such block with size / 2, size / 4, size / 8.\n-# If failed, try to allocate separate `VkDeviceMemory` for this allocation,\n   just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.\n-# If failed, choose other memory type that meets the requirements specified in\n   VmaAllocationCreateInfo and go to point 1.\n-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.\n\n\\section general_considerations_features_not_supported Features not supported\n\nFeatures deliberately excluded from the scope of this library:\n\n-# **Data transfer.** Uploading (streaming) and downloading data of buffers and images\n   between CPU and GPU memory and related synchronization is responsibility of the user.\n   Defining some \"texture\" object that would automatically stream its data from a\n   staging copy in CPU memory to GPU memory would rather be a feature of another,\n   higher-level library implemented on top of VMA.\n   VMA doesn't record any commands to a `VkCommandBuffer`. It just allocates memory.\n-# **Recreation of buffers and images.** Although the library has functions for\n   buffer and image creation: vmaCreateBuffer(), vmaCreateImage(), you need to\n   recreate these objects yourself after defragmentation. That is because the big\n   structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in\n   #VmaAllocation object.\n-# **Handling CPU memory allocation failures.** When dynamically creating small C++\n   objects in CPU memory (not Vulkan memory), allocation failures are not checked\n   and handled gracefully, because that would complicate code significantly and\n   is usually not needed in desktop PC applications anyway.\n   Success of an allocation is just checked with an assert.\n-# **Code free of any compiler warnings.** Maintaining the library to compile and\n   work correctly on so many different platforms is hard enough. Being free of\n   any warnings, on any version of any compiler, is simply not feasible.\n   There are many preprocessor macros that make some variables unused, function parameters unreferenced,\n   or conditional expressions constant in some configurations.\n   The code of this library should not be bigger or more complicated just to silence these warnings.\n   It is recommended to disable such warnings instead.\n-# This is a C++ library with C interface. **Bindings or ports to any other programming languages** are welcome as external projects but\n   are not going to be included into this repository.\n*/\n"
  },
  {
    "path": "Source/Plugin/RHI/xmake.lua",
    "content": "target(\"RHI.Vulkan\")\n    set_kind(\"shared\")\n\n    add_options(\"CUDA_ENABLE\")\n    if has_config(\"CUDA_ENABLE\") then\n        add_links(\"advapi32\")\n    end\n\n    add_rules(\"plugin\")\n    add_defines(\"VK_NO_PROTOTYPES\")\n\n    if is_plat(\"windows\") then\n        add_defines(\"VK_USE_PLATFORM_WIN32_KHR\")\n    end\n\n    add_files(\"Vulkan/**.cpp\")\n    add_headerfiles(\"Vulkan/**.hpp\")\n\n    add_deps(\"Core\", \"RHI\")\n    add_packages(\"volk\")\n\n    target(\"Plugin\")\n        add_deps(\"RHI.Vulkan\")\n    target_end()\n\n    set_group(\"Plugin/RHI\")\ntarget_end()\n\nif has_config(\"CUDA_ENABLE\") and is_plat(\"windows\")  then\n    target(\"RHI.CUDA\")\n        set_kind(\"shared\")\n\n        add_rules(\"plugin\")\n\n        add_files(\"CUDA/**.cpp\")\n        add_headerfiles(\"CUDA/**.hpp\")\n\n        add_deps(\"Core\", \"RHI\")\n        add_packages(\"volk\", \"cuda\")\n        add_links(\"cudart\", \"cuda\")\n        \n        target(\"Plugin\")\n            add_deps(\"RHI.CUDA\")\n        target_end()\n\n        set_group(\"Plugin/RHI\")\n    target_end()\nend\n"
  },
  {
    "path": "Source/Plugin/RenderPass/Bloom.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <bitset>\n\nusing namespace Ilum;\n\nclass Bloom : public RenderPass<Bloom>\n{\n\tstruct Config\n\t{\n\t\tfloat threshold = 0.75f;\n\t\tfloat radius    = 0.75f;\n\t\tfloat intensity = 1.f;\n\t};\n\n\tstruct PipelineDesc\n\t{\n\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = nullptr;\n\t\tShaderMeta                        shader_meta;\n\t};\n\n\tstruct BloomPassData\n\t{\n\t\tstd::unique_ptr<RHITexture>                mask = nullptr;\n\t\tstd::array<std::unique_ptr<RHITexture>, 4> level{nullptr};\n\t\tstd::array<std::unique_ptr<RHITexture>, 4> blur{nullptr};\n\t};\n\n  public:\n\tBloom() = default;\n\n\t~Bloom() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"Bloom\")\n\t\t    .SetCategory(\"PostProcess\")\n\t\t    .SetConfig(Config())\n\t\t    .ReadTexture2D(handle++, \"Input\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\n\t\tauto bloom_mask          = CreatePipelineDesc(renderer, \"BloomMask\");\n\t\tauto bloom_down_sampling = CreatePipelineDesc(renderer, \"BloomDownSampling\");\n\t\tauto bloom_blur          = CreatePipelineDesc(renderer, \"BloomBlur\");\n\t\tauto bloom_up_sampling   = CreatePipelineDesc(renderer, \"BloomUpSampling\");\n\t\tauto bloom_blend         = CreatePipelineDesc(renderer, \"BloomBlend\");\n\n\t\tstd::shared_ptr<RHIBuffer> uniform_buffer = rhi_context->CreateBuffer<Config>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto input  = render_graph.GetTexture(desc.GetPin(\"Input\").handle);\n\t\t\tauto output = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\n\t\t\tauto *gpu_scene  = black_board.Get<GPUScene>();\n\t\t\tauto *view       = black_board.Get<View>();\n\t\t\tauto *bloom_data = black_board.Get<BloomPassData>();\n\n\t\t\tif (!bloom_data->mask ||\n\t\t\t    (bloom_data->mask->GetDesc().width != input->GetDesc().width ||\n\t\t\t     bloom_data->mask->GetDesc().height != input->GetDesc().height))\n\t\t\t{\n\t\t\t\tbloom_data->mask = rhi_context->CreateTexture2D(input->GetDesc().width, input->GetDesc().height, RHIFormat::R32G32B32A32_FLOAT, RHITextureUsage::UnorderedAccess | RHITextureUsage::ShaderResource, false);\n\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{bloom_data->mask.get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess}}, {});\n\t\t\t}\n\n\t\t\tif (!bloom_data->level[0] ||\n\t\t\t    (bloom_data->level[0]->GetDesc().width != (input->GetDesc().width >> 1) ||\n\t\t\t     bloom_data->level[0]->GetDesc().height != (input->GetDesc().height >> 1)))\n\t\t\t{\n\t\t\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t\t\t{\n\t\t\t\t\tbloom_data->level[i] = rhi_context->CreateTexture2D(input->GetDesc().width >> (i + 1), input->GetDesc().height >> (i + 1), RHIFormat::R32G32B32A32_FLOAT, RHITextureUsage::UnorderedAccess | RHITextureUsage::ShaderResource, false);\n\t\t\t\t}\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {TextureStateTransition{bloom_data->level[0].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t\t     TextureStateTransition{bloom_data->level[1].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t\t     TextureStateTransition{bloom_data->level[2].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t\t     TextureStateTransition{bloom_data->level[3].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess}},\n\t\t\t\t    {});\n\t\t\t}\n\n\t\t\tif (!bloom_data->blur[0] ||\n\t\t\t    (bloom_data->blur[0]->GetDesc().width != (input->GetDesc().width >> 1) ||\n\t\t\t     bloom_data->blur[0]->GetDesc().height != (input->GetDesc().height >> 1)))\n\t\t\t{\n\t\t\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t\t\t{\n\t\t\t\t\tbloom_data->blur[i] = rhi_context->CreateTexture2D(input->GetDesc().width >> (i + 1), input->GetDesc().height >> (i + 1), RHIFormat::R32G32B32A32_FLOAT, RHITextureUsage::UnorderedAccess | RHITextureUsage::ShaderResource, false);\n\t\t\t\t}\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {TextureStateTransition{bloom_data->blur[0].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t\t     TextureStateTransition{bloom_data->blur[1].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t\t     TextureStateTransition{bloom_data->blur[2].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t\t     TextureStateTransition{bloom_data->blur[3].get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess}},\n\t\t\t\t    {});\n\t\t\t}\n\n\t\t\tuniform_buffer->CopyToDevice(config.Convert<Config>(), sizeof(Config));\n\n\t\t\t// Masking\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Bloom Mask\");\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(bloom_mask.shader_meta);\n\t\t\t\tdescriptor->BindTexture(\"BloomMaskInput\", input, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"BloomMaskOutput\", bloom_data->mask.get(), RHITextureDimension::Texture2D)\n\t\t\t\t    .BindBuffer(\"ConfigBuffer\", uniform_buffer.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(bloom_mask.pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(input->GetDesc().width, input->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Resource Transition\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{bloom_data->mask.get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource}}, {});\n\t\t\t}\n\n\t\t\t// Down Sampling\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Bloom Down Sampling\");\n\t\t\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t\t\t{\n\t\t\t\t\tcmd_buffer->BeginMarker(fmt::format(\"Bloom Down Sampling - {}\", i));\n\t\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(bloom_down_sampling.shader_meta);\n\t\t\t\t\tdescriptor->BindTexture(\"BloomDownSamplingInput\", i == 0 ? bloom_data->mask.get() : bloom_data->level[i - 1].get(), RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"BloomDownSamplingOutput\", bloom_data->level[i].get(), RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindSampler(\"BloomDownSampleSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()));\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(bloom_down_sampling.pipeline_state.get());\n\t\t\t\t\tcmd_buffer->Dispatch(bloom_data->level[i]->GetDesc().width, bloom_data->level[i]->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{bloom_data->level[i].get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource}}, {});\n\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t}\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Blurring\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Bloom Blur\");\n\t\t\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t\t\t{\n\t\t\t\t\tcmd_buffer->BeginMarker(fmt::format(\"Bloom Blur - {}\", i));\n\t\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(bloom_blur.shader_meta);\n\t\t\t\t\tdescriptor->BindTexture(\"BloomBlurInput\", bloom_data->level[i].get(), RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"BloomBlurOutput\", bloom_data->blur[i].get(), RHITextureDimension::Texture2D);\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(bloom_blur.pipeline_state.get());\n\t\t\t\t\tcmd_buffer->Dispatch(bloom_data->blur[i]->GetDesc().width, bloom_data->blur[i]->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t}\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Resource Transition\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {\n\t\t\t\t        TextureStateTransition{bloom_data->blur[0].get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[1].get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[2].get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[3].get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource},\n\t\t\t\t        TextureStateTransition{bloom_data->level[0].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->level[1].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->level[2].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->level[3].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t    },\n\t\t\t\t    {});\n\t\t\t}\n\n\t\t\t// Up Sampling\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Bloom Up Sampling\");\n\t\t\t\tfor (uint32_t i = 3; i >= 1; i--)\n\t\t\t\t{\n\t\t\t\t\tcmd_buffer->BeginMarker(fmt::format(\"Bloom Up Sampling - {}\", i));\n\t\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(bloom_up_sampling.shader_meta);\n\t\t\t\t\tdescriptor->BindTexture(\"BloomUpSamplingLow\", i == 3 ? bloom_data->blur[i].get() : bloom_data->level[i].get(), RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"BloomUpSamplingHigh\", bloom_data->blur[i - 1].get(), RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"BloomUpSamplingOutput\", bloom_data->level[i - 1].get(), RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindBuffer(\"ConfigBuffer\", uniform_buffer.get());\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(bloom_up_sampling.pipeline_state.get());\n\t\t\t\t\tcmd_buffer->Dispatch(bloom_data->level[i - 1]->GetDesc().width, bloom_data->level[i - 1]->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{bloom_data->level[i - 1].get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource}}, {});\n\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t}\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Blend\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Bloom Blend\");\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(bloom_blend.shader_meta);\n\t\t\t\tdescriptor->BindTexture(\"BloomBlendBloom\", bloom_data->level[0].get(), RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"BloomBlendInput\", input, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"BloomBlendOutput\", output, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindBuffer(\"ConfigBuffer\", uniform_buffer.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(bloom_blend.pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(output->GetDesc().width, output->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Resource Transition\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {\n\t\t\t\t        TextureStateTransition{bloom_data->level[0].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->level[1].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->level[2].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[0].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[1].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[2].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->blur[3].get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t        TextureStateTransition{bloom_data->mask.get(), RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess},\n\t\t\t\t    },\n\t\t\t\t    {});\n\t\t\t}\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t\tauto *config_data = config->Convert<Config>();\n\n\t\tImGui::DragFloat(\"Threshold\", &config_data->threshold, 0.01f, 0.f, std::numeric_limits<float>::max());\n\t\tImGui::DragFloat(\"Radius\", &config_data->radius, 0.01f, 0.f, 1.f);\n\t\tImGui::DragFloat(\"Intensity\", &config_data->intensity, 0.01f, 0.f, std::numeric_limits<float>::max());\n\t}\n\n\tPipelineDesc CreatePipelineDesc(Renderer *renderer, const std::string &entry_point)\n\t{\n\t\tPipelineDesc pipeline_desc;\n\n\t\tauto shader               = renderer->RequireShader(\"Source/Shaders/PostProcess/Bloom.hlsl\", entry_point, RHIShaderStage::Compute);\n\t\tpipeline_desc.shader_meta = renderer->RequireShaderMeta(shader);\n\n\t\tpipeline_desc.pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(renderer->GetRHIContext()->CreatePipelineState()));\n\t\tpipeline_desc.pipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\n\t\treturn pipeline_desc;\n\t}\n};\n\nCONFIGURATION_PASS(Bloom)"
  },
  {
    "path": "Source/Plugin/RenderPass/CompositePass.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <bitset>\n\nusing namespace Ilum;\n\nclass CompositePass : public RenderPass<CompositePass>\n{\n  public:\n\tCompositePass() = default;\n\n\t~CompositePass() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"CompositePass\")\n\t\t    .SetCategory(\"Shading\")\n\t\t    .ReadTexture2D(handle++, \"Env DI\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"Light DI\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"Environment\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"AO\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\n\t\tauto pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto light_direct_illumination = render_graph.GetTexture(desc.GetPin(\"Light DI\").handle);\n\t\t\tauto env_direct_illumination   = render_graph.GetTexture(desc.GetPin(\"Env DI\").handle);\n\t\t\tauto environment               = render_graph.GetTexture(desc.GetPin(\"Environment\").handle);\n\t\t\tauto ao                        = render_graph.GetTexture(desc.GetPin(\"AO\").handle);\n\t\t\tauto output                    = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\n\t\t\tauto *gpu_scene = black_board.Get<GPUScene>();\n\t\t\tauto *view      = black_board.Get<View>();\n\n\t\t\tauto shader = renderer->RequireShader(\"Source/Shaders/Shading/Composite.hlsl\", \"CSmain\", RHIShaderStage::Compute,\n\t\t\t                                      {\n\t\t\t                                          light_direct_illumination ? \"HAS_LIGHT_DIRECT_ILLUMINATION\" : \"NO_LIGHT_DIRECT_ILLUMINATION\",\n\t\t\t                                          env_direct_illumination ? \"HAS_ENV_DIRECT_ILLUMINATION\" : \"NO_ENV_DIRECT_ILLUMINATION\",\n\t\t\t                                          ao ? \"HAS_AMBIENT_OCCLUSION\" : \"NO_AMBIENT_OCCLUSION\",\n\t\t\t                                          environment ? \"HAS_ENVIRONMENT\" : \"NO_ENVIRONMENT\",\n\t\t\t                                      });\n\n\t\t\tShaderMeta shader_meta = renderer->RequireShaderMeta(shader);\n\n\t\t\tpipeline_state->ClearShader();\n\t\t\tpipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\n\t\t\tauto descriptor = rhi_context->CreateDescriptor(shader_meta);\n\n\t\t\tdescriptor->BindTexture(\"Output\", output, RHITextureDimension::Texture2D);\n\n\t\t\tif (light_direct_illumination)\n\t\t\t{\n\t\t\t\tdescriptor->BindTexture(\"LightDirectIllumination\", light_direct_illumination, RHITextureDimension::Texture2D);\n\t\t\t}\n\n\t\t\tif (env_direct_illumination)\n\t\t\t{\n\t\t\t\tdescriptor->BindTexture(\"EnvDirectIllumination\", env_direct_illumination, RHITextureDimension::Texture2D);\n\t\t\t}\n\n\t\t\tif (environment)\n\t\t\t{\n\t\t\t\tdescriptor->BindTexture(\"Environment\", environment, RHITextureDimension::Texture2D);\n\t\t\t}\n\n\t\t\tif (ao)\n\t\t\t{\n\t\t\t\tdescriptor->BindTexture(\"AmbientOcclusion\", ao, RHITextureDimension::Texture2D);\n\t\t\t}\n\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\tcmd_buffer->Dispatch(output->GetDesc().width, output->GetDesc().height, 1, 8, 8, 1);\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(CompositePass)"
  },
  {
    "path": "Source/Plugin/RenderPass/CopyImageRGBA16.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <Core/Core.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBuilder.hpp>\n#include <Renderer/Renderer.hpp>\n\n#include <imgui.h>\n\nusing namespace Ilum;\n\nclass CopyImageRGBA16 : public RenderPass<CopyImageRGBA16>\n{\n  public:\n\tCopyImageRGBA16() = default;\n\n\t~CopyImageRGBA16() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Rasterization)\n\t\t    .SetName(\"CopyImageRGBA16\")\n\t\t    .SetCategory(\"Transfer\")\n\t\t    .ReadTexture2D(handle++, \"Input\", RHIResourceState::TransferSource)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R16G16B16A16_FLOAT, RHIResourceState::TransferDest);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto input = render_graph.GetTexture(desc.GetPin(\"Input\").handle);\n\t\t\tauto output = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\t\t\tcmd_buffer->BlitTexture(input, TextureRange{}, RHIResourceState::TransferSource,\n\t\t\t                        output, TextureRange{}, RHIResourceState::TransferDest);\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(CopyImageRGBA16)"
  },
  {
    "path": "Source/Plugin/RenderPass/Debug.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/RenderPass/Deferred.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/RenderPass/FXAA.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <bitset>\n\nusing namespace Ilum;\n\nclass FXAA : public RenderPass<FXAA>\n{\n\tenum class Quality\n\t{\n\t\tLow,\n\t\tMedium,\n\t\tHigh\n\t};\n\n\tstruct Config\n\t{\n\t\tfloat   fixed_threshold    = 0.8333f;\n\t\tfloat   relative_threshold = 0.166f;\n\t\tfloat   subpixel_blending  = 0.7f;\n\t\tQuality quality            = Quality::High;\n\t};\n\n  public:\n\tFXAA() = default;\n\n\t~FXAA() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"FXAA\")\n\t\t    .SetCategory(\"PostProcess\")\n\t\t    .SetConfig(Config())\n\t\t    .ReadTexture2D(handle++, \"Input\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tconst char *fxaa_qualities[] = {\"FXAA_QUALITY_LOW\", \"FXAA_QUALITY_MEDIUM\", \"FXAA_QUALITY_HIGH\"};\n\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\n\t\tauto pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\n\t\tstd::shared_ptr<RHIBuffer> config_buffer = rhi_context->CreateBuffer<Config>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto input  = render_graph.GetTexture(desc.GetPin(\"Input\").handle);\n\t\t\tauto output = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\n\t\t\tauto *gpu_scene = black_board.Get<GPUScene>();\n\t\t\tauto *view      = black_board.Get<View>();\n\n\t\t\tconfig_buffer->CopyToDevice(config.Convert<Config>(), sizeof(Config));\n\n\t\t\tauto       shader      = renderer->RequireShader(\"Source/Shaders/PostProcess/FXAA.hlsl\", \"CSmain\", RHIShaderStage::Compute, {fxaa_qualities[static_cast<int32_t>(config.Convert<Config>()->quality)]});\n\t\t\tShaderMeta shader_meta = renderer->RequireShaderMeta(shader);\n\t\t\tauto       descriptor  = rhi_context->CreateDescriptor(shader_meta);\n\n\t\t\tpipeline_state->ClearShader();\n\t\t\tpipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\n\t\t\tdescriptor->BindTexture(\"Input\", input, RHITextureDimension::Texture2D)\n\t\t\t    .BindTexture(\"Output\", output, RHITextureDimension::Texture2D)\n\t\t\t    .BindSampler(\"Sampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t    .BindBuffer(\"ConfigBuffer\", config_buffer.get());\n\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\tcmd_buffer->Dispatch(output->GetDesc().width, output->GetDesc().height, 1, 8, 8, 1);\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t\tauto *config_data = config->Convert<Config>();\n\n\t\tconst char *qualities[] = {\"Low\", \"Medium\", \"High\"};\n\n\t\tImGui::Combo(\"Quality\", reinterpret_cast<int32_t *>(&config_data->quality), qualities, 3);\n\t\tImGui::SliderFloat(\"Fixed Threshold\", &config_data->fixed_threshold, 0.0312f, 0.0833f, \"%.4f\");\n\t\tImGui::SliderFloat(\"Relative Threshold\", &config_data->relative_threshold, 0.063f, 0.333f, \"%.4f\");\n\t\tImGui::SliderFloat(\"Subpixel Blending\", &config_data->subpixel_blending, 0.f, 1.f, \"%.2f\");\n\t}\n};\n\nCONFIGURATION_PASS(FXAA)"
  },
  {
    "path": "Source/Plugin/RenderPass/Forward.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/RenderPass/ForwardPlus.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/RenderPass/IBL.cpp",
    "content": "#include \"IPass.hpp\"\n\nusing namespace Ilum;\n\n#define IRRADIANCE_CUBEMAP_SIZE 128\n#define IRRADIANCE_WORK_GROUP_SIZE 8\n#define SH_INTERMEDIATE_SIZE (IRRADIANCE_CUBEMAP_SIZE / IRRADIANCE_WORK_GROUP_SIZE)\n#define CUBEMAP_FACE_NUM 6\n#define PREFILTER_MAP_SIZE 256\n#define PREFILTER_MIP_LEVELS 5\n\nclass IBL : public RenderPass<IBL>\n{\n\tenum class EnvironmentMapType\n\t{\n\t\tSkybox,\n\t\tProcedure\n\t};\n\n\tstruct Config\n\t{\n\t\tEnvironmentMapType type = EnvironmentMapType::Skybox;\n\n\t\tsize_t hash = 0;\n\t};\n\n  public:\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Rasterization)\n\t\t    .SetName(\"IBL\")\n\t\t    .SetCategory(\"Shading\")\n\t\t    .SetConfig(Config())\n\t\t    .WriteTexture2D(handle++, \"IrradianceSH\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess, 9, 1)\n\t\t    .WriteTexture2D(handle++, \"PrefilterMap\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess, PREFILTER_MAP_SIZE, PREFILTER_MAP_SIZE, CUBEMAP_FACE_NUM, PREFILTER_MIP_LEVELS);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\n\t\tstruct PipelineInfo\n\t\t{\n\t\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = nullptr;\n\n\t\t\tShaderMeta shader_meta;\n\t\t};\n\n\t\tPipelineInfo cubemap_sh_projection;\n\t\tPipelineInfo cubemap_sh_add;\n\t\tPipelineInfo cubemap_prefilter;\n\n\t\t{\n\t\t\tauto shader = renderer->RequireShader(\"Source/Shaders/Shading/IBL.hlsl\", \"CubemapSHProjection\", RHIShaderStage::Compute);\n\n\t\t\tcubemap_sh_projection.pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\t\tcubemap_sh_projection.pipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\t\t\tcubemap_sh_projection.shader_meta = renderer->RequireShaderMeta(shader);\n\t\t}\n\n\t\t{\n\t\t\tauto shader = renderer->RequireShader(\"Source/Shaders/Shading/IBL.hlsl\", \"CubemapSHAdd\", RHIShaderStage::Compute);\n\n\t\t\tcubemap_sh_add.pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\t\tcubemap_sh_add.pipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\t\t\tcubemap_sh_add.shader_meta = renderer->RequireShaderMeta(shader);\n\t\t}\n\n\t\t{\n\t\t\tauto shader = renderer->RequireShader(\"Source/Shaders/Shading/IBL.hlsl\", \"CubmapPrefilter\", RHIShaderStage::Compute);\n\n\t\t\tcubemap_prefilter.pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\t\tcubemap_prefilter.pipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\t\t\tcubemap_prefilter.shader_meta = renderer->RequireShaderMeta(shader);\n\t\t}\n\n\t\tstd::shared_ptr<RHIBuffer>  config_buffer   = std::move(rhi_context->CreateBuffer<Config>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU));\n\t\tstd::shared_ptr<RHITexture> sh_intermediate = std::move(rhi_context->CreateTexture2DArray(SH_INTERMEDIATE_SIZE * 9, SH_INTERMEDIATE_SIZE, 6, RHIFormat::R32G32B32A32_FLOAT, RHITextureUsage::UnorderedAccess | RHITextureUsage::ShaderResource, false));\n\n\t\t{\n\t\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\t\t\tcmd_buffer->Begin();\n\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t                                        TextureStateTransition{\n\t\t\t                                            sh_intermediate.get(),\n\t\t\t                                            RHIResourceState::Undefined,\n\t\t\t                                            RHIResourceState::ShaderResource,\n\t\t\t                                        },\n\t\t\t                                    },\n\t\t\t                                    {});\n\t\t\tcmd_buffer->End();\n\t\t\trhi_context->Execute(cmd_buffer);\n\t\t}\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto irradiance_sh = render_graph.GetTexture(desc.GetPin(\"IrradianceSH\").handle);\n\t\t\tauto prefilter_map = render_graph.GetTexture(desc.GetPin(\"PrefilterMap\").handle);\n\n\t\t\tauto   *gpu_scene   = black_board.Get<GPUScene>();\n\t\t\tauto   *view        = black_board.Get<View>();\n\t\t\tConfig *config_data = config.Convert<Config>();\n\n\t\t\tif (gpu_scene->texture.texture_cube)\n\t\t\t{\n\t\t\t\tif (config_data->hash != Hash(gpu_scene->texture.texture_cube, irradiance_sh, prefilter_map))\n\t\t\t\t{\n\t\t\t\t\tconfig_data->hash = Hash(gpu_scene->texture.texture_cube, irradiance_sh, prefilter_map);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Diffuse Environment PRT\n\t\t\t\t{\n\t\t\t\t\tcmd_buffer->BeginMarker(\"Diffuse Environment PRT\");\n\n\t\t\t\t\t// Resource Transition\n\t\t\t\t\t{\n\t\t\t\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t\t\t\t                                        TextureStateTransition{\n\t\t\t\t\t\t                                            sh_intermediate.get(),\n\t\t\t\t\t\t                                            RHIResourceState::ShaderResource,\n\t\t\t\t\t\t                                            RHIResourceState::UnorderedAccess,\n\t\t\t\t\t\t                                        },\n\t\t\t\t\t\t                                    },\n\t\t\t\t\t\t                                    {});\n\t\t\t\t\t}\n\n\t\t\t\t\t// Cubemap SH Projection\n\t\t\t\t\t{\n\t\t\t\t\t\tcmd_buffer->BeginMarker(\"Cubemap SH Projection\");\n\t\t\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(cubemap_sh_projection.shader_meta);\n\t\t\t\t\t\tdescriptor->BindTexture(\"Skybox\", gpu_scene->texture.texture_cube, RHITextureDimension::TextureCube)\n\t\t\t\t\t\t    .BindSampler(\"SkyboxSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t\t\t\t    .BindTexture(\"SHIntermediate\", sh_intermediate.get(), RHITextureDimension::Texture2DArray);\n\t\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\t\tcmd_buffer->BindPipelineState(cubemap_sh_projection.pipeline_state.get());\n\t\t\t\t\t\tcmd_buffer->Dispatch(IRRADIANCE_CUBEMAP_SIZE, IRRADIANCE_CUBEMAP_SIZE, 6, IRRADIANCE_WORK_GROUP_SIZE, IRRADIANCE_WORK_GROUP_SIZE, 1);\n\t\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Resource Transition\n\t\t\t\t\t{\n\t\t\t\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t\t\t\t                                        TextureStateTransition{\n\t\t\t\t\t\t                                            sh_intermediate.get(),\n\t\t\t\t\t\t                                            RHIResourceState::UnorderedAccess,\n\t\t\t\t\t\t                                            RHIResourceState::ShaderResource,\n\t\t\t\t\t\t                                        },\n\t\t\t\t\t\t                                    },\n\t\t\t\t\t\t                                    {});\n\t\t\t\t\t}\n\n\t\t\t\t\t// Cubemap SH Add\n\t\t\t\t\t{\n\t\t\t\t\t\tcmd_buffer->BeginMarker(\"Cubemap SH Add\");\n\t\t\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(cubemap_sh_add.shader_meta);\n\t\t\t\t\t\tdescriptor->BindTexture(\"IrradianceSH\", irradiance_sh, RHITextureDimension::Texture2D)\n\t\t\t\t\t\t    .BindTexture(\"SHIntermediate\", sh_intermediate.get(), RHITextureDimension::Texture2DArray);\n\t\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\t\tcmd_buffer->BindPipelineState(cubemap_sh_add.pipeline_state.get());\n\t\t\t\t\t\tcmd_buffer->Dispatch(9, SH_INTERMEDIATE_SIZE, CUBEMAP_FACE_NUM, 1, SH_INTERMEDIATE_SIZE, CUBEMAP_FACE_NUM);\n\t\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t\t}\n\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t}\n\n\t\t\t\t// Specular Prefilter\n\t\t\t\t{\n\t\t\t\t\tcmd_buffer->BeginMarker(\"Cubemap Prefilter\");\n\t\t\t\t\tfor (uint32_t i = 0; i < PREFILTER_MIP_LEVELS; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(cubemap_prefilter.shader_meta);\n\t\t\t\t\t\tdescriptor->BindTexture(\"Skybox\", gpu_scene->texture.texture_cube, RHITextureDimension::TextureCube)\n\t\t\t\t\t\t    .BindSampler(\"SkyboxSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t\t\t\t    .BindTexture(\"PrefilterMap\", prefilter_map, TextureRange{RHITextureDimension::Texture2DArray, i, 1, 0, 6});\n\t\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\t\tcmd_buffer->BindPipelineState(cubemap_prefilter.pipeline_state.get());\n\t\t\t\t\t\tcmd_buffer->Dispatch(PREFILTER_MAP_SIZE << i, PREFILTER_MAP_SIZE << i, 6, 8, 8, 1);\n\t\t\t\t\t}\n\t\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(IBL)"
  },
  {
    "path": "Source/Plugin/RenderPass/IPass.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBlackboard.hpp>\n#include <RenderGraph/RenderGraphBuilder.hpp>\n#include <Renderer/RenderData.hpp>\n#include <Renderer/Renderer.hpp>\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nclass RenderPassDesc;\nclass RenderGraphBuilder;\nclass Renderer;\n}        // namespace Ilum\n\nstruct ImGuiContext;\n\nusing namespace Ilum;\n\ntemplate <typename T>\nclass RenderPass\n{\n  public:\n\tRenderPass() = default;\n\n\t~RenderPass() = default;\n\n\tstatic T &GetInstance()\n\t{\n\t\tstatic T instance;\n\t\treturn instance;\n\t}\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\treturn RenderPassDesc{};\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\n#define CONFIGURATION_PASS(Pass)                                                                                                                   \\\n\textern \"C\"                                                                                                                                     \\\n\t{                                                                                                                                              \\\n\t\tEXPORT_API void Create(RenderPassDesc *desc, size_t &handle)                                                                           \\\n\t\t{                                                                                                                                          \\\n\t\t\t*desc = Pass::GetInstance().Create(handle);                                                                                        \\\n\t\t}                                                                                                                                          \\\n\t\tEXPORT_API void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer) \\\n\t\t{                                                                                                                                          \\\n\t\t\tPass::GetInstance().CreateCallback(task, desc, builder, renderer);                                                                     \\\n\t\t}                                                                                                                                          \\\n\t\tEXPORT_API void OnImGui(Variant *config, ImGuiContext *context)                                                                            \\\n\t\t{                                                                                                                                          \\\n\t\t\tImGui::SetCurrentContext(context);                                                                                                     \\\n\t\t\tPass::GetInstance().OnImGui(config);                                                                                                   \\\n\t\t}                                                                                                                                          \\\n\t}"
  },
  {
    "path": "Source/Plugin/RenderPass/PassData.hpp",
    "content": "#pragma once\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nstruct ShadowMapCache\n{\n\t// Texture2D Array\n\tstd::unique_ptr<RHITexture> shadow_map = nullptr;\n\n\t// Texture2D Array\n\tstd::unique_ptr<RHITexture> cascade_shadow_map = nullptr;\n\n\t// TextureCube Array\n\tstd::unique_ptr<RHITexture> omni_shadow_map = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Plugin/RenderPass/PathTracing.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <Material/MaterialData.hpp>\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Scene.hpp>\n\nusing namespace Ilum;\n\nclass PathTracing : public RenderPass<PathTracing>\n{\n\tstruct Config\n\t{\n\t\tuint32_t max_bounce      = 5;\n\t\tuint32_t max_spp         = 100;\n\t\tuint32_t frame_count     = 0;\n\t\tfloat    clamp_threshold = 4.f;\n\t\tuint32_t     anti_aliasing   = 1;\n\t};\n\n  public:\n\tPathTracing() = default;\n\n\t~PathTracing() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::RayTracing)\n\t\t    .SetName(\"PathTracing\")\n\t\t    .SetCategory(\"RayTracing\")\n\t\t    .SetConfig(Config())\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tstruct\n\t\t{\n\t\t\tstd::shared_ptr<RHIPipelineState> pipeline = nullptr;\n\t\t} pipeline;\n\n\t\tpipeline.pipeline = std::shared_ptr<RHIPipelineState>(std::move(renderer->GetRHIContext()->CreatePipelineState()));\n\n\t\tstd::shared_ptr<RHIBuffer> config_buffer = std::shared_ptr<RHIBuffer>(std::move(renderer->GetRHIContext()->CreateBuffer(sizeof(Config), RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU)));\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto  output      = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\t\t\tauto *gpu_scene   = black_board.Get<GPUScene>();\n\t\t\tauto *view        = black_board.Get<View>();\n\t\t\tauto *rhi_context = renderer->GetRHIContext();\n\t\t\tauto *config_data = config.Convert<Config>();\n\n\t\t\tconfig_buffer->CopyToDevice(config_data, sizeof(Config));\n\n\t\t\tif (renderer->GetScene()->IsUpdate())\n\t\t\t{\n\t\t\t\tconfig_data->frame_count = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconfig_data->frame_count = glm::clamp(config_data->frame_count, 0u, config_data->max_spp);\n\t\t\t}\n\n\t\t\tif (config_data->frame_count == config_data->max_spp)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Setup material pipeline\n\t\t\tShaderMeta meta;\n\t\t\t{\n\t\t\t\tpipeline.pipeline->ClearShader();\n\n\t\t\t\tauto *raygen_shader     = renderer->RequireShader(\"Source/Shaders/RayTracing/PathTracing.hlsl\", \"RayGenMain\", RHIShaderStage::RayGen, {\"RAYGEN_SHADER\", \"RAYTRACING_PIPELINE\", gpu_scene->texture.texture_cube ? \"USE_SKYBOX\" : \"NO_SKYBOX\"});\n\t\t\t\tauto *closesthit_shader = renderer->RequireShader(\"Source/Shaders/RayTracing/PathTracing.hlsl\", \"ClosesthitMain\", RHIShaderStage::ClosestHit, {\"CLOSESTHIT_SHADER\", \"RAYTRACING_PIPELINE\"}, {\"Material/Material.hlsli\"});\n\t\t\t\tauto *miss_shader       = renderer->RequireShader(\"Source/Shaders/RayTracing/PathTracing.hlsl\", \"MissMain\", RHIShaderStage::Miss, {\"MISS_SHADER\", \"RAYTRACING_PIPELINE\"});\n\n\t\t\t\tmeta += renderer->RequireShaderMeta(raygen_shader);\n\t\t\t\tmeta += renderer->RequireShaderMeta(closesthit_shader);\n\t\t\t\tmeta += renderer->RequireShaderMeta(miss_shader);\n\n\t\t\t\tpipeline.pipeline->SetShader(RHIShaderStage::RayGen, raygen_shader);\n\t\t\t\tpipeline.pipeline->SetShader(RHIShaderStage::ClosestHit, closesthit_shader);\n\t\t\t\tpipeline.pipeline->SetShader(RHIShaderStage::Miss, miss_shader);\n\n\t\t\t\tfor (const auto &data : gpu_scene->material.data)\n\t\t\t\t{\n\t\t\t\t\tauto *material_closesthit_shader = renderer->RequireShader(\"Source/Shaders/RayTracing/PathTracing.hlsl\", \"ClosesthitMain\", RHIShaderStage::ClosestHit, {\"CLOSESTHIT_SHADER\", \"RAYTRACING_PIPELINE\", data->signature}, {data->shader});\n\t\t\t\t\tpipeline.pipeline->SetShader(RHIShaderStage::ClosestHit, material_closesthit_shader);\n\t\t\t\t\tmeta += renderer->RequireShaderMeta(material_closesthit_shader);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (gpu_scene->opaque_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\t\tdescriptor->BindAccelerationStructure(\"TopLevelAS\", gpu_scene->opaque_tlas.get())\n\t\t\t\t    .BindTexture(\"Output\", output, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindBuffer(\"ConfigBuffer\", config_buffer.get())\n\t\t\t\t    .BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get())\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->mesh_buffer.index_buffers)\n\t\t\t\t    .BindTexture(\"Textures\", gpu_scene->texture.texture_2d, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindSampler(\"Samplers\", gpu_scene->samplers)\n\t\t\t\t    .BindBuffer(\"MaterialOffsets\", gpu_scene->material.material_offset.get())\n\t\t\t\t    .BindBuffer(\"MaterialBuffer\", gpu_scene->material.material_buffer.get())\n\t\t\t\t    .BindBuffer(\"PointLightBuffer\", gpu_scene->light.point_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"SpotLightBuffer\", gpu_scene->light.spot_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"DirectionalLightBuffer\", gpu_scene->light.directional_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"RectLightBuffer\", gpu_scene->light.rect_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tif (gpu_scene->texture.texture_cube)\n\t\t\t\t{\n\t\t\t\t\tdescriptor->BindTexture(\"Skybox\", gpu_scene->texture.texture_cube, RHITextureDimension::TextureCube)\n\t\t\t\t\t    .BindSampler(\"SkyboxSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()));\n\t\t\t\t}\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->TraceRay(output->GetDesc().width, output->GetDesc().height, 1);\n\n\t\t\t\tconfig_data->frame_count++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconfig_data->frame_count = 0;\n\t\t\t}\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t\tauto *config_data = config->Convert<Config>();\n\n\t\tImGui::Text(\"SPP: %d\", config_data->frame_count);\n\n\t\t if (ImGui::Checkbox(\"Anti-Aliasing\", reinterpret_cast<bool *>(&config_data->anti_aliasing)))\n\t\t{\n\t\t\tconfig_data->frame_count = 0;\n\t\t }\n\n\t\tif (ImGui::SliderInt(\"Max Bounce\", reinterpret_cast<int32_t *>(&config_data->max_bounce), 1, 100))\n\t\t{\n\t\t\tconfig_data->frame_count = 0;\n\t\t}\n\n\t\tif (ImGui::DragInt(\"Max SPP\", reinterpret_cast<int32_t *>(&config_data->max_spp), 0.1f, 1, std::numeric_limits<int32_t>::max()))\n\t\t{\n\t\t\tconfig_data->frame_count = 0;\n\t\t}\n\n\t\tImGui::ProgressBar(static_cast<float>(config_data->frame_count) / static_cast<float>(config_data->max_spp),\n\t\t                   ImVec2(0.f, 0.f),\n\t\t                   (std::to_string(config_data->frame_count) + \"/\" + std::to_string(config_data->max_spp)).c_str());\n\n\t\tif (ImGui::DragFloat(\"Clamp Threshold\", &config_data->clamp_threshold, 0.1f, 0.0f, std::numeric_limits<float>::max()))\n\t\t{\n\t\t\tconfig_data->frame_count = 0;\n\t\t}\n\t}\n};\n\nCONFIGURATION_PASS(PathTracing)"
  },
  {
    "path": "Source/Plugin/RenderPass/Present.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <Core/Core.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBuilder.hpp>\n#include <Renderer/Renderer.hpp>\n\n#include <imgui.h>\n\nusing namespace Ilum;\n\nclass Present : public RenderPass<Present>\n{\n  public:\n\tPresent() = default;\n\n\t~Present() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::None)\n\t\t    .SetName(\"Present\")\n\t\t    .SetCategory(\"Output\")\n\t\t    .ReadTexture2D(handle++, \"Present\", RHIResourceState::ShaderResource);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard& black_board) {\n\t\t\tauto  texture = render_graph.GetTexture(desc.GetPin(\"Present\").handle);\n\t\t\trenderer->SetPresentTexture(texture);\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(Present)"
  },
  {
    "path": "Source/Plugin/RenderPass/RayTracedAO.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <Material/MaterialData.hpp>\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Scene.hpp>\n\nusing namespace Ilum;\n\nclass RayTracedAO : public RenderPass<RayTracedAO>\n{\n\tstruct Config\n\t{\n\t\tuint32_t max_bounce      = 5;\n\t\tuint32_t max_spp         = 100;\n\t\tuint32_t frame_count     = 0;\n\t\tfloat    clamp_threshold = 4.f;\n\t\tuint32_t anti_aliasing   = 1;\n\t};\n\n\tstruct PipelineDesc\n\t{\n\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = nullptr;\n\t\tShaderMeta                        shader_meta;\n\t};\n\n\tstruct RayTracedPassData\n\t{\n\t\tstd::unique_ptr<RHITexture>                raytrace = nullptr;\n\t\tstd::array<std::unique_ptr<RHITexture>, 2> ao{nullptr};\n\t\tstd::array<std::unique_ptr<RHITexture>, 2> history_length{nullptr};\n\t\tstd::array<std::unique_ptr<RHITexture>, 2> bilateral_blur{nullptr};\n\t};\n\n  public:\n\tRayTracedAO() = default;\n\n\t~RayTracedAO() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::RayTracing)\n\t\t    .SetName(\"RayTracedAO\")\n\t\t    .SetCategory(\"AO\")\n\t\t    .SetConfig(Config())\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tstruct\n\t\t{\n\t\t\tstd::shared_ptr<RHIPipelineState> pipeline = nullptr;\n\t\t} pipeline;\n\n\t\tpipeline.pipeline = std::shared_ptr<RHIPipelineState>(std::move(renderer->GetRHIContext()->CreatePipelineState()));\n\n\t\tstd::shared_ptr<RHIBuffer> config_buffer = std::shared_ptr<RHIBuffer>(std::move(renderer->GetRHIContext()->CreateBuffer(sizeof(Config), RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU)));\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto  output      = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\t\t\tauto *gpu_scene   = black_board.Get<GPUScene>();\n\t\t\tauto *view        = black_board.Get<View>();\n\t\t\tauto *rhi_context = renderer->GetRHIContext();\n\t\t\tauto *config_data = config.Convert<Config>();\n\n\t\t\tconfig_buffer->CopyToDevice(config_data, sizeof(Config));\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(RayTracedAO)"
  },
  {
    "path": "Source/Plugin/RenderPass/RayTracingReflection.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/RenderPass/RayTracingShadow.cpp",
    "content": ""
  },
  {
    "path": "Source/Plugin/RenderPass/SSAO.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <random>\n\nusing namespace Ilum;\n\n#define SSAO_NOISE_DIM 4\n#define SSAO_KERNEL_SIZE 64\n\nclass SSAO : public RenderPass<SSAO>\n{\n  public:\n\tSSAO() = default;\n\n\t~SSAO() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"SSAO\")\n\t\t    .SetCategory(\"AO\")\n\t\t    .ReadTexture2D(handle++, \"PositionDepth\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"Normal\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\n\t\tstruct PipelineInfo\n\t\t{\n\t\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = nullptr;\n\t\t\tShaderMeta                        shader_meta;\n\t\t};\n\n\t\tPipelineInfo ssao_pipeline;\n\t\tPipelineInfo blur_pipeline;\n\n\t\t{\n\t\t\tauto shader = renderer->RequireShader(\"Source/Shaders/AmbientOcclusion/SSAO.hlsl\", \"SSAO\", RHIShaderStage::Compute);\n\n\t\t\tssao_pipeline.shader_meta    = renderer->RequireShaderMeta(shader);\n\t\t\tssao_pipeline.pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\t\tssao_pipeline.pipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\t\t}\n\n\t\t{\n\t\t\tauto shader = renderer->RequireShader(\"Source/Shaders/AmbientOcclusion/SSAO.hlsl\", \"SSAOBlur\", RHIShaderStage::Compute);\n\n\t\t\tblur_pipeline.shader_meta    = renderer->RequireShaderMeta(shader);\n\t\t\tblur_pipeline.pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\t\tblur_pipeline.pipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\t\t}\n\n\t\tstd::default_random_engine            rnd_engine(0);\n\t\tstd::uniform_real_distribution<float> rnd_dist(0.0f, 1.0f);\n\n\t\tstd::shared_ptr<RHIBuffer> sample_buffer = rhi_context->CreateBuffer<glm::vec4>(SSAO_KERNEL_SIZE, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\t\t// Update sample buffer\n\t\t{\n\t\t\tstd::vector<glm::vec4> ssao_kernal(SSAO_KERNEL_SIZE);\n\t\t\tfor (uint32_t i = 0; i < SSAO_KERNEL_SIZE; ++i)\n\t\t\t{\n\t\t\t\tglm::vec3 sample(rnd_dist(rnd_engine) * 2.0 - 1.0, rnd_dist(rnd_engine) * 2.0 - 1.0, rnd_dist(rnd_engine));\n\t\t\t\tsample = glm::normalize(sample);\n\t\t\t\tsample *= rnd_dist(rnd_engine);\n\t\t\t\tfloat scale    = float(i) / float(SSAO_KERNEL_SIZE);\n\t\t\t\tscale          = glm::mix(0.1f, 1.0f, scale * scale);\n\t\t\t\tssao_kernal[i] = glm::vec4(sample * scale, 0.0f);\n\t\t\t}\n\t\t\tsample_buffer->CopyToDevice(ssao_kernal.data(), ssao_kernal.size() * sizeof(glm::vec4));\n\t\t}\n\n\t\tstd::shared_ptr<RHITexture> noise_texture = rhi_context->CreateTexture2D(SSAO_NOISE_DIM, SSAO_NOISE_DIM, RHIFormat::R32G32B32A32_FLOAT, RHITextureUsage::Transfer | RHITextureUsage::ShaderResource, false);\n\t\t// Update noise texture\n\t\t{\n\t\t\tstd::vector<glm::vec4> ssao_noise(SSAO_NOISE_DIM * SSAO_NOISE_DIM);\n\t\t\tfor (unsigned int i = 0; i < SSAO_NOISE_DIM * SSAO_NOISE_DIM; i++)\n\t\t\t{\n\t\t\t\tssao_noise[i] = glm::vec4(rnd_dist(rnd_engine) * 2.0f - 1.0f, rnd_dist(rnd_engine) * 2.0f - 1.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t\tauto staging_buffer = rhi_context->CreateBuffer<glm::vec4>(SSAO_NOISE_DIM * SSAO_NOISE_DIM, RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\tstaging_buffer->CopyToDevice(ssao_noise.data(), ssao_noise.size() * sizeof(glm::vec4));\n\t\t\t{\n\t\t\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Transfer);\n\t\t\t\tcmd_buffer->Begin();\n\t\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t\t                                        TextureStateTransition{noise_texture.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest},\n\t\t\t\t                                    },\n\t\t\t\t                                    {});\n\t\t\t\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), noise_texture.get(), 0, 0, 1);\n\t\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t\t                                        TextureStateTransition{noise_texture.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource},\n\t\t\t\t                                    },\n\t\t\t\t                                    {});\n\t\t\t\tcmd_buffer->End();\n\t\t\t\trhi_context->Execute(cmd_buffer);\n\t\t\t}\n\t\t}\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto normal         = render_graph.GetTexture(desc.GetPin(\"Normal\").handle);\n\t\t\tauto position_depth = render_graph.GetTexture(desc.GetPin(\"PositionDepth\").handle);\n\t\t\tauto output         = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\n\t\t\tauto *view = black_board.Get<View>();\n\n\t\t\t// SSAO\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"SSAO\");\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(ssao_pipeline.shader_meta);\n\t\t\t\tdescriptor->BindTexture(\"Normal\", normal, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"PositionDepth\", position_depth, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"NoiseTexture\", noise_texture.get(), RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"SSAOMap\", output, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindBuffer(\"SampleBuffer\", sample_buffer.get())\n\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get())\n\t\t\t\t    .BindSampler(\"TexSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()));\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(ssao_pipeline.pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(output->GetDesc().width, output->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Sync\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t\t                                        TextureStateTransition{output, RHIResourceState::UnorderedAccess, RHIResourceState::UnorderedAccess},\n\t\t\t\t                                    },\n\t\t\t\t                                    {});\n\t\t\t}\n\n\t\t\t// SSAO Blur\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"SSAO Blur\");\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(blur_pipeline.shader_meta);\n\t\t\t\tdescriptor->BindTexture(\"SSAOMap\", output, RHITextureDimension::Texture2D);\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(blur_pipeline.pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(output->GetDesc().width, output->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(SSAO)"
  },
  {
    "path": "Source/Plugin/RenderPass/ShadowMapPass.cpp",
    "content": "#include \"IPass.hpp\"\n#include \"PassData.hpp\"\n\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Scene.hpp>\n\nusing namespace Ilum;\n\nclass ShadowMapPass : public RenderPass<ShadowMapPass>\n{\n\tstruct PipelineDesc\n\t{\n\t\tstd::shared_ptr<RHIPipelineState> pipeline = nullptr;\n\n\t\tShaderMeta meta;\n\t};\n\n\tenum class ShadowMapResolution\n\t{\n\t\tVeryLow,\n\t\tLow,\n\t\tMedium,\n\t\tHigh,\n\t\tVeryHigh\n\t};\n\n\tconst std::unordered_map<ShadowMapResolution, uint32_t> shadow_map_resolution =\n\t    {\n\t        {ShadowMapResolution::VeryHigh, 2048},\n\t        {ShadowMapResolution::High, 1536},\n\t        {ShadowMapResolution::Medium, 1024},\n\t        {ShadowMapResolution::Low, 682},\n\t        {ShadowMapResolution::VeryLow, 341},\n\t    };\n\n\tstruct Config\n\t{\n\t\tShadowMapResolution shadow_map_resolution         = ShadowMapResolution::Medium;\n\t\tShadowMapResolution cascade_shadow_map_resolution = ShadowMapResolution::Medium;\n\t\tShadowMapResolution omni_map_resolution           = ShadowMapResolution::Medium;\n\n\t\tfloat bias  = 16.f;\n\t\tfloat slope = 4.5f;\n\t};\n\n  public:\n\tShadowMapPass() = default;\n\n\t~ShadowMapPass() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Rasterization)\n\t\t    .SetConfig(Config())\n\t\t    .SetName(\"ShadowMapPass\")\n\t\t    .SetCategory(\"Shadow\")\n\t\t    .WriteTexture2D(handle++, \"ShadowMap\", RHIFormat::D32_FLOAT, RHIResourceState::DepthWrite, 1024, 1024)\n\t\t    .WriteTexture2D(handle++, \"CascadeShadowMap\", RHIFormat::D32_FLOAT, RHIResourceState::DepthWrite, 1024, 1024, 4)\n\t\t    .WriteTexture2D(handle++, \"OmniShadowMap\", RHIFormat::D32_FLOAT, RHIResourceState::DepthWrite, 1024, 1024, 6);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto mesh_shadow_pipeline                 = CreatePipeline(\"Source/Shaders/Shadow/ShadowMap.hlsl\", renderer, false);\n\t\tauto skinned_mesh_shadow_pipeline         = CreatePipeline(\"Source/Shaders/Shadow/ShadowMap.hlsl\", renderer, true);\n\t\tauto mesh_cascade_shadow_pipeline         = CreatePipeline(\"Source/Shaders/Shadow/CascadeShadowMap.hlsl\", renderer, false);\n\t\tauto skinned_mesh_cascade_shadow_pipeline = CreatePipeline(\"Source/Shaders/Shadow/CascadeShadowMap.hlsl\", renderer, true);\n\t\tauto mesh_omni_shadow_pipeline            = CreatePipeline(\"Source/Shaders/Shadow/OmniShadowMap.hlsl\", renderer, false);\n\t\tauto skinned_mesh_omni_shadow_pipeline    = CreatePipeline(\"Source/Shaders/Shadow/OmniShadowMap.hlsl\", renderer, true);\n\n\t\tstd::shared_ptr<RHIRenderTarget> shadowmap_render_target         = std::shared_ptr<RHIRenderTarget>(std::move(renderer->GetRHIContext()->CreateRenderTarget()));\n\t\tstd::shared_ptr<RHIRenderTarget> cascade_shadowmap_render_target = std::shared_ptr<RHIRenderTarget>(std::move(renderer->GetRHIContext()->CreateRenderTarget()));\n\t\tstd::shared_ptr<RHIRenderTarget> omni_shadowmap_render_target    = std::shared_ptr<RHIRenderTarget>(std::move(renderer->GetRHIContext()->CreateRenderTarget()));\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto   *rhi_context = renderer->GetRHIContext();\n\t\t\tauto   *scene       = renderer->GetScene();\n\t\t\tauto   *gpu_scene   = black_board.Get<GPUScene>();\n\t\t\tConfig *config_data = config.Convert<Config>();\n\n\t\t\tauto *shadow_map         = render_graph.GetTexture(desc.GetPin(\"ShadowMap\").handle);\n\t\t\tauto *cascade_shadow_map = render_graph.GetTexture(desc.GetPin(\"CascadeShadowMap\").handle);\n\t\t\tauto *omni_shadow_map    = render_graph.GetTexture(desc.GetPin(\"OmniShadowMap\").handle);\n\n\t\t\tauto *shadow_map_cache = black_board.Has<ShadowMapCache>() ? black_board.Get<ShadowMapCache>() : black_board.Add<ShadowMapCache>();\n\n\t\t\t// Release old shadow map\n\t\t\t{\n\t\t\t\tif (shadow_map_cache->shadow_map)\n\t\t\t\t{\n\t\t\t\t\tshadow_map_cache->shadow_map = nullptr;\n\t\t\t\t}\n\n\t\t\t\tif (shadow_map_cache->cascade_shadow_map)\n\t\t\t\t{\n\t\t\t\t\tshadow_map_cache->cascade_shadow_map = nullptr;\n\t\t\t\t}\n\n\t\t\t\tif (shadow_map_cache->omni_shadow_map)\n\t\t\t\t{\n\t\t\t\t\tshadow_map_cache->omni_shadow_map = nullptr;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Render shadow map for spot light\n\t\t\t{\n\t\t\t\tauto     spot_lights = scene->GetComponents<Cmpt::SpotLight>();\n\t\t\t\tuint32_t layers      = 0;\n\t\t\t\tfor (auto &light : spot_lights)\n\t\t\t\t{\n\t\t\t\t\tlayers += static_cast<uint32_t>(light->CastShadow());\n\t\t\t\t}\n\t\t\t\tuint32_t size = shadow_map_resolution.at(config_data->shadow_map_resolution);\n\n\t\t\t\tif (!shadow_map ||\n\t\t\t\t    shadow_map->GetDesc().width != size ||\n\t\t\t\t    shadow_map->GetDesc().layers < spot_lights.size())\n\t\t\t\t{\n\t\t\t\t\tshadow_map_cache->shadow_map = render_graph.SetTexture(desc.GetPin(\"ShadowMap\").handle, std::move(rhi_context->CreateTexture2DArray(size, size, layers, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false)));\n\t\t\t\t\tshadow_map                   = render_graph.GetTexture(desc.GetPin(\"ShadowMap\").handle);\n\n\t\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t\t\t\t\t                                        shadow_map,\n\t\t\t\t\t                                        RHIResourceState::Undefined,\n\t\t\t\t\t                                        RHIResourceState::DepthWrite,\n\t\t\t\t\t                                        TextureRange{RHITextureDimension::Texture2DArray, 0, 1, 0, layers}}},\n\t\t\t\t\t                                    {});\n\t\t\t\t}\n\n\t\t\t\tRenderShadowMap(cmd_buffer, mesh_shadow_pipeline, skinned_mesh_shadow_pipeline, renderer, scene, gpu_scene, config_data, shadow_map, shadowmap_render_target.get());\n\t\t\t}\n\n\t\t\t// Render cascade shadow map for directional light\n\t\t\t{\n\t\t\t\tauto     directional_lights = scene->GetComponents<Cmpt::DirectionalLight>();\n\t\t\t\tuint32_t size               = shadow_map_resolution.at(config_data->cascade_shadow_map_resolution);\n\t\t\t\tuint32_t layers             = glm::max(static_cast<uint32_t>(directional_lights.size() * 4ull), 1u);\n\n\t\t\t\tif (!cascade_shadow_map ||\n\t\t\t\t    cascade_shadow_map->GetDesc().width != size ||\n\t\t\t\t    cascade_shadow_map->GetDesc().layers < directional_lights.size() * 4)\n\t\t\t\t{\n\t\t\t\t\tshadow_map_cache->cascade_shadow_map = render_graph.SetTexture(desc.GetPin(\"CascadeShadowMap\").handle, std::move(rhi_context->CreateTexture2DArray(size, size, layers, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false)));\n\t\t\t\t\tcascade_shadow_map                   = render_graph.GetTexture(desc.GetPin(\"CascadeShadowMap\").handle);\n\t\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t\t\t\t\t                                        cascade_shadow_map,\n\t\t\t\t\t                                        RHIResourceState::Undefined,\n\t\t\t\t\t                                        RHIResourceState::DepthWrite,\n\t\t\t\t\t                                        TextureRange{RHITextureDimension::Texture2DArray, 0, 1, 0, layers}}},\n\t\t\t\t\t                                    {});\n\t\t\t\t}\n\n\t\t\t\tRenderCascadeShadowMap(cmd_buffer, mesh_cascade_shadow_pipeline, skinned_mesh_cascade_shadow_pipeline, renderer, scene, gpu_scene, config_data, cascade_shadow_map, cascade_shadowmap_render_target.get());\n\t\t\t}\n\n\t\t\t// Render omnidirection shadow map for point light\n\t\t\t{\n\t\t\t\tauto     point_lights = scene->GetComponents<Cmpt::PointLight>();\n\t\t\t\tuint32_t layers       = glm::max(static_cast<uint32_t>(point_lights.size() * 6ull), 1u);\n\t\t\t\tuint32_t size         = shadow_map_resolution.at(config_data->omni_map_resolution);\n\n\t\t\t\tif (!omni_shadow_map ||\n\t\t\t\t    omni_shadow_map->GetDesc().width != size ||\n\t\t\t\t    omni_shadow_map->GetDesc().layers < point_lights.size() * 6)\n\t\t\t\t{\n\t\t\t\t\tshadow_map_cache->omni_shadow_map = render_graph.SetTexture(desc.GetPin(\"OmniShadowMap\").handle, std::move(rhi_context->CreateTexture2DArray(size, size, layers, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget | RHITextureUsage::ShaderResource, false)));\n\t\t\t\t\tomni_shadow_map                   = render_graph.GetTexture(desc.GetPin(\"OmniShadowMap\").handle);\n\t\t\t\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t\t\t\t\t                                        omni_shadow_map,\n\t\t\t\t\t                                        RHIResourceState::Undefined,\n\t\t\t\t\t                                        RHIResourceState::DepthWrite,\n\t\t\t\t\t                                        TextureRange{RHITextureDimension::Texture2DArray, 0, 1, 0, layers}}},\n\t\t\t\t\t                                    {});\n\t\t\t\t}\n\t\t\t\tRenderOmniShadowMap(cmd_buffer, mesh_omni_shadow_pipeline, skinned_mesh_omni_shadow_pipeline, renderer, scene, gpu_scene, config_data, omni_shadow_map, omni_shadowmap_render_target.get());\n\t\t\t}\n\t\t};\n\t}\n\n\tPipelineDesc\n\t    CreatePipeline(const std::string &path, Renderer *renderer, bool has_skinned)\n\t{\n\t\tPipelineDesc pipeline_desc;\n\n\t\tpipeline_desc.pipeline = std::shared_ptr<RHIPipelineState>(std::move(renderer->GetRHIContext()->CreatePipelineState()));\n\n\t\tRasterizationState rasterization_state;\n\t\trasterization_state.cull_mode  = RHICullMode::None;\n\t\trasterization_state.front_face = RHIFrontFace::Clockwise;\n\t\tpipeline_desc.pipeline->SetRasterizationState(rasterization_state);\n\n\t\tDepthStencilState depth_stencil_state  = {};\n\t\tdepth_stencil_state.depth_write_enable = true;\n\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\tpipeline_desc.pipeline->SetDepthStencilState(depth_stencil_state);\n\n\t\tif (renderer->GetRHIContext()->IsFeatureSupport(RHIFeature::MeshShading))\n\t\t{\n\t\t\tauto *task_shader = renderer->RequireShader(path, \"ASmain\", RHIShaderStage::Task, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\t\t\tauto *mesh_shader = renderer->RequireShader(path, \"MSmain\", RHIShaderStage::Mesh, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\t\t\tauto *frag_shader = renderer->RequireShader(path, \"PSmain\", RHIShaderStage::Fragment, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Task, task_shader);\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Mesh, mesh_shader);\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Fragment, frag_shader);\n\n\t\t\tpipeline_desc.meta = renderer->RequireShaderMeta(task_shader);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(mesh_shader);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(frag_shader);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto *vertex_shader = renderer->RequireShader(path, \"VSmain\", RHIShaderStage::Vertex, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\t\t\tauto *frag_shader   = renderer->RequireShader(path, \"FSmain\", RHIShaderStage::Fragment, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Fragment, frag_shader);\n\n\t\t\tif (has_skinned)\n\t\t\t{\n\t\t\t\tVertexInputState vertex_input_state = {};\n\t\t\t\tvertex_input_state.input_bindings   = {\n                    VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex), RHIVertexInputRate::Vertex}};\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 3, 0, RHIFormat::R32G32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, texcoord0)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 5, 0, RHIFormat::R32G32B32A32_SINT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, bones[0])},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 6, 0, RHIFormat::R32G32B32A32_SINT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, bones[4])},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Weights, 7, 0, RHIFormat::R32G32B32A32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, weights[0])},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Weights, 8, 0, RHIFormat::R32G32B32A32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, weights[4])},\n\t\t\t\t};\n\n\t\t\t\tpipeline_desc.pipeline->SetVertexInputState(vertex_input_state);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tVertexInputState vertex_input_state = {};\n\t\t\t\tvertex_input_state.input_bindings   = {\n                    VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::Mesh>::Vertex), RHIVertexInputRate::Vertex}};\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 3, 0, RHIFormat::R32G32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, texcoord0)},\n\t\t\t\t};\n\n\t\t\t\tpipeline_desc.pipeline->SetVertexInputState(vertex_input_state);\n\t\t\t}\n\n\t\t\tpipeline_desc.meta = renderer->RequireShaderMeta(vertex_shader);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(frag_shader);\n\t\t}\n\n\t\treturn pipeline_desc;\n\t}\n\n\tvoid RenderShadowMap(\n\t    RHICommand         *cmd_buffer,\n\t    const PipelineDesc &mesh_pipeline,\n\t    const PipelineDesc &skinned_mesh_pipeline,\n\t    Renderer           *renderer,\n\t    Scene              *scene,\n\t    GPUScene           *gpu_scene,\n\t    Config             *config,\n\t    RHITexture         *shadow_map,\n\t    RHIRenderTarget    *render_target)\n\t{\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\t\tauto  spot_lights = scene->GetComponents<Cmpt::SpotLight>();\n\n\t\tRasterizationState rasterization_state;\n\t\trasterization_state.cull_mode         = RHICullMode::None;\n\t\trasterization_state.front_face        = RHIFrontFace::Clockwise;\n\t\trasterization_state.depth_bias_enable = true;\n\t\trasterization_state.depth_bias        = config->bias;\n\t\trasterization_state.depth_bias_slope  = config->slope;\n\t\tmesh_pipeline.pipeline->SetRasterizationState(rasterization_state);\n\t\tskinned_mesh_pipeline.pipeline->SetRasterizationState(rasterization_state);\n\n\t\trender_target->Clear();\n\t\trender_target->Set(shadow_map, RHITextureDimension::Texture2DArray, DepthStencilAttachment{});\n\n\t\tif (rhi_context->IsFeatureSupport(RHIFeature::MeshShading))\n\t\t{\n\t\t\tcmd_buffer->BeginMarker(\"Spot Light Shadow Mapping [Mesh Shader]\");\n\n\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\n\t\t\tcmd_buffer->BeginRenderPass(render_target);\n\n\t\t\t// Draw Opaque Mesh\n\t\t\tif (gpu_scene->opaque_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->mesh_buffer.index_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->mesh_buffer.meshlet_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->mesh_buffer.meshlet_data_buffers)\n\t\t\t\t    .BindBuffer(\"SpotLightBuffer\", gpu_scene->light.spot_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_mesh.max_meshlet_count, gpu_scene->opaque_mesh.instance_count, static_cast<uint32_t>(spot_lights.size()), 32, 1, 1);\n\t\t\t}\n\n\t\t\t// Draw Skinned Mesh\n\t\t\tif (gpu_scene->opaque_skinned_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation.bone_matrics)\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->skinned_mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->skinned_mesh_buffer.index_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_data_buffers)\n\t\t\t\t    .BindBuffer(\"SpotLightBuffer\", gpu_scene->light.spot_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_skinned_mesh.max_meshlet_count, gpu_scene->opaque_skinned_mesh.instance_count, static_cast<uint32_t>(spot_lights.size()), 32, 1, 1);\n\t\t\t}\n\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t\tcmd_buffer->EndMarker();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// cmd_buffer->BeginMarker(\"Spot Light Shadow Mapping\");\n\n\t\t\t// cmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\t// cmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\t// cmd_buffer->BeginRenderPass(render_target);\n\n\t\t\t//// Draw Mesh\n\t\t\t// if (gpu_scene->mesh_buffer.instance_count > 0)\n\t\t\t//{\n\t\t\t//\tauto meshes = renderer->GetScene()->GetComponents<Cmpt::MeshRenderer>();\n\n\t\t\t//\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t//\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->mesh_buffer.instances.get());\n\n\t\t\t//\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t//\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\n\t\t\t//\tuint32_t instance_id = 0;\n\t\t\t//\tfor (auto &mesh : meshes)\n\t\t\t//\t{\n\t\t\t//\t\tauto &submeshes = mesh->GetSubmeshes();\n\t\t\t//\t\tfor (auto &submesh : submeshes)\n\t\t\t//\t\t{\n\t\t\t//\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::Mesh>(submesh);\n\t\t\t//\t\t\tif (resource)\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t//\t\t\t\tinstance_id++;\n\t\t\t//\t\t\t}\n\t\t\t//\t\t}\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t//// Draw Skinned Mesh\n\t\t\t// if (gpu_scene->skinned_mesh_buffer.instance_count > 0)\n\t\t\t//{\n\t\t\t//\tauto skinned_meshes = renderer->GetScene()->GetComponents<Cmpt::SkinnedMeshRenderer>();\n\n\t\t\t//\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t//\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->skinned_mesh_buffer.instances.get())\n\t\t\t//\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation_buffer.bone_matrics);\n\n\t\t\t//\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t//\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\n\t\t\t//\tuint32_t instance_id = 0;\n\t\t\t//\tfor (auto &skinned_mesh : skinned_meshes)\n\t\t\t//\t{\n\t\t\t//\t\tauto &submeshes = skinned_mesh->GetSubmeshes();\n\t\t\t//\t\tfor (auto &submesh : submeshes)\n\t\t\t//\t\t{\n\t\t\t//\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::SkinnedMesh>(submesh);\n\t\t\t//\t\t\tif (resource)\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t//\t\t\t\tinstance_id++;\n\t\t\t//\t\t\t}\n\t\t\t//\t\t}\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t// cmd_buffer->EndRenderPass();\n\t\t\t// cmd_buffer->EndMarker();\n\t\t}\n\t}\n\n\tvoid RenderCascadeShadowMap(\n\t    RHICommand         *cmd_buffer,\n\t    const PipelineDesc &mesh_pipeline,\n\t    const PipelineDesc &skinned_mesh_pipeline,\n\t    Renderer           *renderer,\n\t    Scene              *scene,\n\t    GPUScene           *gpu_scene,\n\t    Config             *config,\n\t    RHITexture         *cascade_shadow_map,\n\t    RHIRenderTarget    *render_target)\n\t{\n\t\tauto *rhi_context        = renderer->GetRHIContext();\n\t\tauto  directional_lights = scene->GetComponents<Cmpt::DirectionalLight>();\n\n\t\tRasterizationState rasterization_state;\n\t\trasterization_state.cull_mode         = RHICullMode::None;\n\t\trasterization_state.front_face        = RHIFrontFace::Clockwise;\n\t\trasterization_state.depth_bias_enable = true;\n\t\trasterization_state.depth_bias        = config->bias;\n\t\trasterization_state.depth_bias_slope  = config->slope;\n\t\tmesh_pipeline.pipeline->SetRasterizationState(rasterization_state);\n\t\tskinned_mesh_pipeline.pipeline->SetRasterizationState(rasterization_state);\n\n\t\trender_target->Clear();\n\t\trender_target->Set(cascade_shadow_map, RHITextureDimension::Texture2DArray, DepthStencilAttachment{});\n\n\t\tif (rhi_context->IsFeatureSupport(RHIFeature::MeshShading))\n\t\t{\n\t\t\tcmd_buffer->BeginMarker(\"Directional Light Shadow Mapping [Mesh Shader]\");\n\n\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\n\t\t\tcmd_buffer->BeginRenderPass(render_target);\n\n\t\t\t// Draw Mesh\n\t\t\tif (gpu_scene->opaque_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->mesh_buffer.index_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->mesh_buffer.meshlet_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->mesh_buffer.meshlet_data_buffers)\n\t\t\t\t    .BindBuffer(\"DirectionalLightBuffer\", gpu_scene->light.directional_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_mesh.max_meshlet_count, gpu_scene->opaque_mesh.instance_count, static_cast<uint32_t>(directional_lights.size() * 4), 32, 1, 1);\n\t\t\t}\n\n\t\t\t// Draw Opaque Skinned Mesh\n\t\t\tif (gpu_scene->opaque_skinned_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation.bone_matrics)\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->skinned_mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->skinned_mesh_buffer.index_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_data_buffers)\n\t\t\t\t    .BindBuffer(\"DirectionalLightBuffer\", gpu_scene->light.directional_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_skinned_mesh.max_meshlet_count, gpu_scene->opaque_skinned_mesh.instance_count, static_cast<uint32_t>(directional_lights.size() * 4), 32, 1, 1);\n\t\t\t}\n\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t\tcmd_buffer->EndMarker();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// cmd_buffer->BeginMarker(\"Spot Light Shadow Mapping\");\n\n\t\t\t// cmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\t// cmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\t// cmd_buffer->BeginRenderPass(render_target);\n\n\t\t\t//// Draw Mesh\n\t\t\t// if (gpu_scene->mesh_buffer.instance_count > 0)\n\t\t\t//{\n\t\t\t//\tauto meshes = renderer->GetScene()->GetComponents<Cmpt::MeshRenderer>();\n\n\t\t\t//\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t//\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->mesh_buffer.instances.get());\n\n\t\t\t//\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t//\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\n\t\t\t//\tuint32_t instance_id = 0;\n\t\t\t//\tfor (auto &mesh : meshes)\n\t\t\t//\t{\n\t\t\t//\t\tauto &submeshes = mesh->GetSubmeshes();\n\t\t\t//\t\tfor (auto &submesh : submeshes)\n\t\t\t//\t\t{\n\t\t\t//\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::Mesh>(submesh);\n\t\t\t//\t\t\tif (resource)\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t//\t\t\t\tinstance_id++;\n\t\t\t//\t\t\t}\n\t\t\t//\t\t}\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t//// Draw Skinned Mesh\n\t\t\t// if (gpu_scene->skinned_mesh_buffer.instance_count > 0)\n\t\t\t//{\n\t\t\t//\tauto skinned_meshes = renderer->GetScene()->GetComponents<Cmpt::SkinnedMeshRenderer>();\n\n\t\t\t//\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t//\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->skinned_mesh_buffer.instances.get())\n\t\t\t//\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation_buffer.bone_matrics);\n\n\t\t\t//\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t//\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\n\t\t\t//\tuint32_t instance_id = 0;\n\t\t\t//\tfor (auto &skinned_mesh : skinned_meshes)\n\t\t\t//\t{\n\t\t\t//\t\tauto &submeshes = skinned_mesh->GetSubmeshes();\n\t\t\t//\t\tfor (auto &submesh : submeshes)\n\t\t\t//\t\t{\n\t\t\t//\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::SkinnedMesh>(submesh);\n\t\t\t//\t\t\tif (resource)\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t//\t\t\t\tinstance_id++;\n\t\t\t//\t\t\t}\n\t\t\t//\t\t}\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t// cmd_buffer->EndRenderPass();\n\t\t\t// cmd_buffer->EndMarker();\n\t\t}\n\t\t// cmd_buffer->ResourceStateTransition({TextureStateTransition{\n\t\t//                                         shadow_map_data->cascade_shadow_map.get(),\n\t\t//                                         RHIResourceState::DepthWrite,\n\t\t//                                         RHIResourceState::ShaderResource,\n\t\t//                                         TextureRange{RHITextureDimension::Texture2DArray, 0, 1, 0, layers}}},\n\t\t//                                     {});\n\t}\n\n\tvoid RenderOmniShadowMap(\n\t    RHICommand         *cmd_buffer,\n\t    const PipelineDesc &mesh_pipeline,\n\t    const PipelineDesc &skinned_mesh_pipeline,\n\t    Renderer           *renderer,\n\t    Scene              *scene,\n\t    GPUScene           *gpu_scene,\n\t    Config             *config,\n\t    RHITexture         *omni_shadow_map,\n\t    RHIRenderTarget    *render_target)\n\t{\n\t\tauto *rhi_context  = renderer->GetRHIContext();\n\t\tauto  point_lights = scene->GetComponents<Cmpt::PointLight>();\n\n\t\trender_target->Clear();\n\t\trender_target->Set(omni_shadow_map, RHITextureDimension::Texture2DArray, DepthStencilAttachment{});\n\n\t\tif (rhi_context->IsFeatureSupport(RHIFeature::MeshShading))\n\t\t{\n\t\t\tcmd_buffer->BeginMarker(\"Point Light Shadow Mapping [Mesh Shader]\");\n\n\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\n\t\t\tcmd_buffer->BeginRenderPass(render_target);\n\n\t\t\t// Draw Opaque Mesh\n\t\t\tif (gpu_scene->opaque_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->mesh_buffer.index_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->mesh_buffer.meshlet_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->mesh_buffer.meshlet_data_buffers)\n\t\t\t\t    .BindBuffer(\"PointLightBuffer\", gpu_scene->light.point_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_mesh.max_meshlet_count, gpu_scene->opaque_mesh.instance_count, static_cast<uint32_t>(point_lights.size() * 6), 32, 1, 1);\n\t\t\t}\n\n\t\t\t// Draw Opaque Skinned Mesh\n\t\t\tif (gpu_scene->opaque_skinned_mesh.instance_count > 0)\n\t\t\t{\n\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation.bone_matrics)\n\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->skinned_mesh_buffer.vertex_buffers)\n\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->skinned_mesh_buffer.index_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_buffers)\n\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_data_buffers)\n\t\t\t\t    .BindBuffer(\"PointLightBuffer\", gpu_scene->light.point_light_buffer.get())\n\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get());\n\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_skinned_mesh.max_meshlet_count, gpu_scene->opaque_skinned_mesh.instance_count, static_cast<uint32_t>(point_lights.size() * 6), 32, 1, 1);\n\t\t\t}\n\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t\tcmd_buffer->EndMarker();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// cmd_buffer->BeginMarker(\"Spot Light Shadow Mapping\");\n\n\t\t\t// cmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\t// cmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\t// cmd_buffer->BeginRenderPass(render_target);\n\n\t\t\t//// Draw Mesh\n\t\t\t// if (gpu_scene->mesh_buffer.instance_count > 0)\n\t\t\t//{\n\t\t\t//\tauto meshes = renderer->GetScene()->GetComponents<Cmpt::MeshRenderer>();\n\n\t\t\t//\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t//\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->mesh_buffer.instances.get());\n\n\t\t\t//\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t//\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\n\t\t\t//\tuint32_t instance_id = 0;\n\t\t\t//\tfor (auto &mesh : meshes)\n\t\t\t//\t{\n\t\t\t//\t\tauto &submeshes = mesh->GetSubmeshes();\n\t\t\t//\t\tfor (auto &submesh : submeshes)\n\t\t\t//\t\t{\n\t\t\t//\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::Mesh>(submesh);\n\t\t\t//\t\t\tif (resource)\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t//\t\t\t\tinstance_id++;\n\t\t\t//\t\t\t}\n\t\t\t//\t\t}\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t//// Draw Skinned Mesh\n\t\t\t// if (gpu_scene->skinned_mesh_buffer.instance_count > 0)\n\t\t\t//{\n\t\t\t//\tauto skinned_meshes = renderer->GetScene()->GetComponents<Cmpt::SkinnedMeshRenderer>();\n\n\t\t\t//\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t//\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->skinned_mesh_buffer.instances.get())\n\t\t\t//\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation_buffer.bone_matrics);\n\n\t\t\t//\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t//\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\n\t\t\t//\tuint32_t instance_id = 0;\n\t\t\t//\tfor (auto &skinned_mesh : skinned_meshes)\n\t\t\t//\t{\n\t\t\t//\t\tauto &submeshes = skinned_mesh->GetSubmeshes();\n\t\t\t//\t\tfor (auto &submesh : submeshes)\n\t\t\t//\t\t{\n\t\t\t//\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::SkinnedMesh>(submesh);\n\t\t\t//\t\t\tif (resource)\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t//\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t//\t\t\t\tinstance_id++;\n\t\t\t//\t\t\t}\n\t\t\t//\t\t}\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t// cmd_buffer->EndRenderPass();\n\t\t\t// cmd_buffer->EndMarker();\n\t\t}\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t\tConfig *config_data = config->Convert<Config>();\n\n\t\tImGui::PushItemWidth(ImGui::GetContentRegionAvail().x / 2.f);\n\t\tImGui::DragFloat(\"Depth Bias\", &config_data->bias, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\t\tImGui::DragFloat(\"Depth Slope\", &config_data->slope, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\n\t\tconst char *resolution[] = {\"VeryLow\", \"Low\", \"Medium\", \"High\", \"VeryHigh\"};\n\t\tImGui::Text(\"Shadow Map Resolution\");\n\t\tImGui::Combo(\"Spot Light\", reinterpret_cast<int32_t *>(&config_data->shadow_map_resolution), resolution, 5);\n\t\tImGui::Combo(\"Point Light\", reinterpret_cast<int32_t *>(&config_data->omni_map_resolution), resolution, 5);\n\t\tImGui::Combo(\"Directional Light\", reinterpret_cast<int32_t *>(&config_data->cascade_shadow_map_resolution), resolution, 5);\n\n\t\tImGui::PopItemWidth();\n\t}\n};\n\nCONFIGURATION_PASS(ShadowMapPass)"
  },
  {
    "path": "Source/Plugin/RenderPass/SkyboxPass.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <imgui.h>\n\nusing namespace Ilum;\n\nclass SkyboxPass : public RenderPass<SkyboxPass>\n{\n  public:\n\tSkyboxPass() = default;\n\n\t~SkyboxPass() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Rasterization)\n\t\t    .SetName(\"SkyboxPass\")\n\t\t    .SetCategory(\"Shading\")\n\t\t    .ReadTexture2D(handle++, \"Depth\", RHIResourceState::DepthRead)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R16G16B16A16_FLOAT, RHIResourceState::RenderTarget);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *rhi_context    = renderer->GetRHIContext();\n\t\tauto  pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\tauto  render_target  = std::shared_ptr<RHIRenderTarget>(std::move(rhi_context->CreateRenderTarget()));\n\n\t\tauto vertex_shader   = renderer->RequireShader(\"Source/Shaders/Shading/Skybox.hlsl\", \"VSmain\", RHIShaderStage::Vertex);\n\t\tauto fragment_shader = renderer->RequireShader(\"Source/Shaders/Shading/Skybox.hlsl\", \"PSmain\", RHIShaderStage::Fragment);\n\n\t\tShaderMeta shader_meta = renderer->RequireShaderMeta(vertex_shader);\n\t\tshader_meta += renderer->RequireShaderMeta(fragment_shader);\n\n\t\tBlendState blend_state;\n\t\tblend_state.attachment_states.resize(1);\n\n\t\tDepthStencilState depth_stencil_state;\n\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\tdepth_stencil_state.depth_write_enable = false;\n\t\tdepth_stencil_state.compare            = RHICompareOp::Less;\n\n\t\tRasterizationState rasterization_state;\n\t\trasterization_state.cull_mode = RHICullMode::None;\n\t\trasterization_state.front_face = RHIFrontFace::Clockwise;\n\n\t\tpipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\tpipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader);\n\t\tpipeline_state->SetBlendState(blend_state);\n\t\tpipeline_state->SetDepthStencilState(depth_stencil_state);\n\t\tpipeline_state->SetRasterizationState(rasterization_state);\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto depth = render_graph.GetTexture(desc.GetPin(\"Depth\").handle);\n\t\t\tauto output = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\n\t\t\tauto *gpu_scene = black_board.Get<GPUScene>();\n\t\t\tauto *view = black_board.Get<View>();\n\n\t\t\trender_target->Clear();\n\t\t\trender_target->Set(0, output, TextureRange{}, ColorAttachment{});\n\t\t\trender_target->Set(depth, TextureRange{}, DepthStencilAttachment{RHILoadAction::Load});\n\n\t\t\tif (gpu_scene->texture.texture_cube)\n\t\t\t{\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(shader_meta);\n\n\t\t\t\tdescriptor->BindTexture(\"Skybox\", gpu_scene->texture.texture_cube, RHITextureDimension::TextureCube)\n\t\t\t\t    .BindSampler(\"SkyboxSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t\t\t.BindBuffer(\"ViewBuffer\", view->buffer.get());\n\n\t\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\t\tcmd_buffer->BeginRenderPass(render_target.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\tcmd_buffer->Draw(36);\n\t\t\t\tcmd_buffer->EndRenderPass();\n\t\t\t}\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(SkyboxPass)"
  },
  {
    "path": "Source/Plugin/RenderPass/Tonemapping.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <bitset>\n\nusing namespace Ilum;\n\nclass Tonemapping : public RenderPass<Tonemapping>\n{\n\tstruct Config\n\t{\n\t\tfloat   brightness    = 1.f;\n\t\tfloat   contrast      = 1.f;\n\t\tfloat   saturation    = 1.f;\n\t\tfloat   vignette      = 0.f;\n\t\tfloat   avg_lum       = 1.f;\n\t\tint32_t auto_exposure = 0;\n\t\tfloat   Ywhite        = 0.5f;        // Burning white\n\t\tfloat   key           = 0.5f;        // Log-average luminance\n\t};\n\n  public:\n\tTonemapping() = default;\n\n\t~Tonemapping() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"Tonemapping\")\n\t\t    .SetCategory(\"PostProcess\")\n\t\t    .SetConfig(Config())\n\t\t    .ReadTexture2D(handle++, \"Input\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Output\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *rhi_context    = renderer->GetRHIContext();\n\t\tauto  shader      = renderer->RequireShader(\"Source/Shaders/PostProcess/Tonemapping.hlsl\", \"CSmain\", RHIShaderStage::Compute);\n\t\tShaderMeta shader_meta    = renderer->RequireShaderMeta(shader);\n\n\t\tauto  pipeline_state = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\t\tpipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\n\t\tstd::shared_ptr<RHIBuffer> uniform_buffer = rhi_context->CreateBuffer<Config>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto input  = render_graph.GetTexture(desc.GetPin(\"Input\").handle);\n\t\t\tauto output = render_graph.GetTexture(desc.GetPin(\"Output\").handle);\n\n\t\t\tauto *gpu_scene = black_board.Get<GPUScene>();\n\t\t\tauto *view      = black_board.Get<View>();\n\n\t\t\tuniform_buffer->CopyToDevice(config.Convert<Config>(), sizeof(Config));\n\n\t\t\tauto descriptor = rhi_context->CreateDescriptor(shader_meta);\n\n\t\t\tdescriptor->BindTexture(\"Input\", input, RHITextureDimension::Texture2D)\n\t\t\t    .BindTexture(\"Output\", output, RHITextureDimension::Texture2D)\n\t\t\t    .BindSampler(\"TexSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t\t.BindBuffer(\"UniformBuffer\", uniform_buffer.get());\n\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\tcmd_buffer->Dispatch(output->GetDesc().width, output->GetDesc().height, 1, 8, 8, 1);\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t\tauto *config_data = config->Convert<Config>();\n\n\t\tstd::bitset<8> b(config_data->auto_exposure);\n\n\t\tbool auto_exposure = b.test(0);\n\n\t\t//ImGui::Checkbox(\"Auto Exposure\", &auto_exposure);\n\t\tImGui::SliderFloat(\"Exposure\", &config_data->avg_lum, 0.001f, 5.0f, \"%.3f\");\n\t\tImGui::SliderFloat(\"Brightness\", &config_data->brightness, 0.0f, 2.0f, \"%.3f\");\n\t\tImGui::SliderFloat(\"Contrast\", &config_data->contrast, 0.0f, 2.0f, \"%.3f\");\n\t\tImGui::SliderFloat(\"Saturation\", &config_data->saturation, 0.0f, 5.0f, \"%.3f\");\n\t\tImGui::SliderFloat(\"Vignette\", &config_data->vignette, 0.0f, 2.0f, \"%.3f\");\n\n\t\tif (auto_exposure)\n\t\t{\n\t\t\tbool localExposure = b.test(1);\n\t\t\tif (ImGui::TreeNode(\"Auto Settings\"))\n\t\t\t{\n\t\t\t\tImGui::Checkbox(\"Local\", &localExposure);\n\t\t\t\tImGui::SliderFloat(\"Burning White\", &config_data->Ywhite, 0.f, 1.f, \"%.3f\");\n\t\t\t\tImGui::SliderFloat(\"Brightness\", &config_data->key, 0.f, 1.f, \"%.3f\");\n\t\t\t\tb.set(1, localExposure);\n\t\t\t\tImGui::End();\n\t\t\t}\n\t\t}\n\n\t\tb.set(0, auto_exposure);\n\n\t\tconfig_data->auto_exposure = b.to_ulong();\n\t}\n};\n\nCONFIGURATION_PASS(Tonemapping)"
  },
  {
    "path": "Source/Plugin/RenderPass/Triangle.cpp",
    "content": "#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBuilder.hpp>\n#include <Renderer/Renderer.hpp>\n#include <Scene/Component/AllComponent.hpp>\n#include <Scene/Entity.hpp>\n#include <Scene/Scene.hpp>\n\n#include <imgui.h>\n\n#include <iostream>\n\nusing namespace Ilum;\n\nstruct Config\n{\n\tfloat a = 1.f;\n};\n\nextern \"C\"\n{\n\t__declspec(dllexport) void CreateDesc(RenderPassDesc *desc)\n\t{\n\t\tdesc->SetBindPoint(BindPoint::Rasterization)\n\t\t    .Write(\"Output\", RenderResourceDesc::Type::Texture, RHIResourceState::RenderTarget)\n\t\t    .SetConfig(Config());\n\t}\n\n\t__declspec(dllexport) void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tauto *vertex_shader   = renderer->RequireShader(\"Source/Shaders/DrawUV.hlsl\", \"VSmain\", RHIShaderStage::Vertex);\n\t\tauto *fragment_shader = renderer->RequireShader(\"Source/Shaders/DrawUV.hlsl\", \"PSmain\", RHIShaderStage::Fragment);\n\n\t\tShaderMeta meta;\n\t\tmeta += renderer->RequireShaderMeta(vertex_shader);\n\t\tmeta += renderer->RequireShaderMeta(fragment_shader);\n\n\t\tstd::shared_ptr<RHIDescriptor>    descriptor     = std::move(renderer->GetRHIContext()->CreateDescriptor(meta));\n\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = std::move(renderer->GetRHIContext()->CreatePipelineState());\n\t\tstd::shared_ptr<RHIRenderTarget>  render_target  = std::move(renderer->GetRHIContext()->CreateRenderTarget());\n\n\t\tpipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\tpipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader);\n\n\t\tBlendState bend_state;\n\t\tbend_state.attachment_states.resize(1);\n\t\tpipeline_state->SetBlendState(bend_state);\n\n\t\tRasterizationState rasterization_state;\n\t\trasterization_state.cull_mode  = RHICullMode::None;\n\t\trasterization_state.front_face = RHIFrontFace::Clockwise;\n\t\tpipeline_state->SetRasterizationState(rasterization_state);\n\n\t\tfloat factor = 1.f;\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, rttr::variant &config) {\n\t\t\tConfig config_ = config.convert<Config>();\n\n\t\t\trender_target->Clear()\n\t\t\t    .Set(0, render_graph.GetTexture(desc.resources.at(\"Output\").handle), RHITextureDimension::Texture2D, ColorAttachment{});\n\t\t\tcmd_buffer->BindDescriptor(descriptor.get());\n\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\tcmd_buffer->BeginRenderPass(render_target.get());\n\t\t\tdescriptor->SetConstant(\"a\", config_.a).BindBuffer(\"View\", renderer->GetViewBuffer());\n\t\t\trenderer->GetScene()->Execute([&](Entity &entity) {\n\t\t\t\tauto transform = entity.GetComponent<TransformComponent>().world_transform;\n\t\t\t\tdescriptor->SetConstant(\"transform\", transform);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\tcmd_buffer->Draw(3, 1);\n\t\t\t});\n\t\t\tcmd_buffer->EndRenderPass();\n\t\t};\n\t}\n\n\t__declspec(dllexport) bool OnImGui(rttr::variant *config, ImGuiContext *context)\n\t{\n\t\tImGui::SetCurrentContext(context);\n\n\t\tConfig config_ = config->convert<Config>();\n\n\t\tbool update = ImGui::DragFloat(\"a\", &config_.a, 0.01f, 0.f, 100.f, \"%.3f\");\n\n\t\tif (update)\n\t\t{\n\t\t\t*config = config_;\n\t\t}\n\n\t\treturn update;\n\t}\n}"
  },
  {
    "path": "Source/Plugin/RenderPass/VisibilityBufferVisualization.cpp",
    "content": "#include \"IPass.hpp\"\n\nusing namespace Ilum;\n\nclass VisibilityBufferVisualization : public RenderPass<VisibilityBufferVisualization>\n{\n  public:\n\tVisibilityBufferVisualization() = default;\n\n\t~VisibilityBufferVisualization() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"VisibilityBufferVisualization\")\n\t\t    .SetCategory(\"RenderPath\")\n\t\t    .ReadTexture2D(handle++, \"Visibility Buffer\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"Depth Buffer\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Instance ID\", RHIFormat::R8G8B8A8_UNORM, RHIResourceState::UnorderedAccess)\n\t\t    .WriteTexture2D(handle++, \"Primitive ID\", RHIFormat::R8G8B8A8_UNORM, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tShaderMeta meta;\n\n\t\tauto *shader = renderer->RequireShader(\"Source/Shaders/RenderPath/VisibilityBufferVisualization.hlsl\", \"CSmain\", RHIShaderStage::Compute);\n\t\tmeta += renderer->RequireShaderMeta(shader);\n\n\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = std::move(renderer->GetRHIContext()->CreatePipelineState());\n\n\t\tpipeline_state->SetShader(RHIShaderStage::Compute, shader);\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto *visibility_buffer   = render_graph.GetTexture(desc.GetPin(\"Visibility Buffer\").handle);\n\t\t\tauto *depth_buffer        = render_graph.GetTexture(desc.GetPin(\"Depth Buffer\").handle);\n\t\t\tauto *instance_id_buffer  = render_graph.GetTexture(desc.GetPin(\"Instance ID\").handle);\n\t\t\tauto *primitive_id_buffer = render_graph.GetTexture(desc.GetPin(\"Primitive ID\").handle);\n\n\t\t\tauto *descriptor = renderer->GetRHIContext()->CreateDescriptor(meta);\n\n\t\t\tdescriptor->BindTexture(\"VisibilityBuffer\", visibility_buffer, RHITextureDimension::Texture2D)\n\t\t\t    .BindTexture(\"DepthBuffer\", depth_buffer, RHITextureDimension::Texture2D)\n\t\t\t    .BindTexture(\"InstanceID\", instance_id_buffer, RHITextureDimension::Texture2D)\n\t\t\t    .BindTexture(\"PrimitiveID\", primitive_id_buffer, RHITextureDimension::Texture2D);\n\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\tcmd_buffer->Dispatch(visibility_buffer->GetDesc().width, visibility_buffer->GetDesc().height, 1, 32, 32, 1);\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n};\n\nCONFIGURATION_PASS(VisibilityBufferVisualization)\n"
  },
  {
    "path": "Source/Plugin/RenderPass/VisibilityGeometryPass.cpp",
    "content": "#include \"IPass.hpp\"\n\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Scene.hpp>\n\nusing namespace Ilum;\n\nclass VisibilityGeometryPass : public RenderPass<VisibilityGeometryPass>\n{\n\tstruct PipelineDesc\n\t{\n\t\tstd::shared_ptr<RHIPipelineState> pipeline = nullptr;\n\t\tShaderMeta                        meta;\n\t};\n\n  public:\n\tVisibilityGeometryPass() = default;\n\n\t~VisibilityGeometryPass() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Rasterization)\n\t\t    .SetName(\"VisibilityGeometryPass\")\n\t\t    .SetCategory(\"RenderPath\")\n\t\t    .WriteTexture2D(handle++, \"Visibility Buffer\", RHIFormat::R32_UINT, RHIResourceState::RenderTarget)\n\t\t    .WriteTexture2D(handle++, \"Depth Buffer\", RHIFormat::D32_FLOAT, RHIResourceState::DepthWrite);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tstd::shared_ptr<RHIRenderTarget> render_target = std::shared_ptr<RHIRenderTarget>(std::move(renderer->GetRHIContext()->CreateRenderTarget()));\n\n\t\tauto mesh_pipeline = CreatePipeline(renderer, false);\n\t\tauto skinned_mesh_pipeline = CreatePipeline(renderer, true);\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto  visibility_buffer = render_graph.GetTexture(desc.GetPin(\"Visibility Buffer\").handle);\n\t\t\tauto  depth_stencil     = render_graph.GetTexture(desc.GetPin(\"Depth Buffer\").handle);\n\t\t\tauto *rhi_context       = renderer->GetRHIContext();\n\t\t\tauto *gpu_scene         = black_board.Get<GPUScene>();\n\t\t\tauto *view              = black_board.Get<View>();\n\n\t\t\trender_target->Clear();\n\t\t\trender_target->Set(0, visibility_buffer, TextureRange{}, ColorAttachment{});\n\t\t\trender_target->Set(depth_stencil, TextureRange{}, DepthStencilAttachment{});\n\n\t\t\t// Mesh Shading\n\t\t\tif (rhi_context->IsFeatureSupport(RHIFeature::MeshShading))\n\t\t\t{\n\t\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\t\tcmd_buffer->BeginRenderPass(render_target.get());\n\n\t\t\t\t// Draw Opaque Mesh\n\t\t\t\tif (gpu_scene->opaque_mesh.instance_count > 0)\n\t\t\t\t{\n\t\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get())\n\t\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->mesh_buffer.vertex_buffers)\n\t\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->mesh_buffer.index_buffers)\n\t\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->mesh_buffer.meshlet_buffers)\n\t\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->mesh_buffer.meshlet_data_buffers);\n\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\t\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_mesh.max_meshlet_count, gpu_scene->opaque_mesh.instance_count, 1, 32, 1, 1);\n\t\t\t\t}\n\n\t\t\t\t// Draw Opaque Skinned Mesh\n\t\t\t\tif (gpu_scene->opaque_skinned_mesh.instance_count > 0)\n\t\t\t\t{\n\t\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get())\n\t\t\t\t\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation.bone_matrics)\n\t\t\t\t\t    .BindBuffer(\"VertexBuffer\", gpu_scene->skinned_mesh_buffer.vertex_buffers)\n\t\t\t\t\t    .BindBuffer(\"IndexBuffer\", gpu_scene->skinned_mesh_buffer.index_buffers)\n\t\t\t\t\t    .BindBuffer(\"MeshletBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_buffers)\n\t\t\t\t\t    .BindBuffer(\"MeshletDataBuffer\", gpu_scene->skinned_mesh_buffer.meshlet_data_buffers);\n\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\t\t\t\t\tcmd_buffer->DrawMeshTask(gpu_scene->opaque_skinned_mesh.max_meshlet_count, gpu_scene->opaque_skinned_mesh.instance_count, 1, 32, 1, 1);\n\t\t\t\t}\n\n\t\t\t\tcmd_buffer->EndRenderPass();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcmd_buffer->SetViewport(static_cast<float>(render_target->GetWidth()), static_cast<float>(render_target->GetHeight()));\n\t\t\t\tcmd_buffer->SetScissor(render_target->GetWidth(), render_target->GetHeight());\n\t\t\t\tcmd_buffer->BeginRenderPass(render_target.get());\n\n\t\t\t\t// Draw Opaque Mesh\n\t\t\t\tif (gpu_scene->opaque_mesh.instance_count > 0)\n\t\t\t\t{\n\t\t\t\t\tauto meshes = renderer->GetScene()->GetComponents<Cmpt::MeshRenderer>();\n\n\t\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(mesh_pipeline.meta);\n\t\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get());\n\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(mesh_pipeline.pipeline.get());\n\n\t\t\t\t\tuint32_t instance_id = 0;\n\t\t\t\t\tfor (auto &mesh : meshes)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto &submeshes = mesh->GetSubmeshes();\n\t\t\t\t\t\tfor (auto &submesh : submeshes)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::Mesh>(submesh);\n\t\t\t\t\t\t\tif (resource)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t\t\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t\t\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t\t\t\t\t\tinstance_id++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Draw Opaque Skinned Mesh\n\t\t\t\tif (gpu_scene->opaque_skinned_mesh.instance_count > 0)\n\t\t\t\t{\n\t\t\t\t\tauto skinned_meshes = renderer->GetScene()->GetComponents<Cmpt::SkinnedMeshRenderer>();\n\n\t\t\t\t\tauto *descriptor = rhi_context->CreateDescriptor(skinned_mesh_pipeline.meta);\n\t\t\t\t\tdescriptor->BindBuffer(\"InstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get())\n\t\t\t\t\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation.bone_matrics);\n\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(skinned_mesh_pipeline.pipeline.get());\n\n\t\t\t\t\tuint32_t instance_id = 0;\n\t\t\t\t\tfor (auto &skinned_mesh : skinned_meshes)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto &submeshes = skinned_mesh->GetSubmeshes();\n\t\t\t\t\t\tfor (auto &submesh : submeshes)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tauto *resource = renderer->GetResourceManager()->Get<ResourceType::SkinnedMesh>(submesh);\n\t\t\t\t\t\t\tif (resource)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcmd_buffer->BindVertexBuffer(0, resource->GetVertexBuffer());\n\t\t\t\t\t\t\t\tcmd_buffer->BindIndexBuffer(resource->GetIndexBuffer());\n\t\t\t\t\t\t\t\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(resource->GetIndexCount()), 1, 0, 0, instance_id);\n\t\t\t\t\t\t\t\tinstance_id++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcmd_buffer->EndRenderPass();\n\t\t\t}\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t}\n\n\tPipelineDesc CreatePipeline(Renderer *renderer, bool has_skinned)\n\t{\n\t\tauto *rhi_context = renderer->GetRHIContext();\n\n\t\tPipelineDesc pipeline_desc;\n\t\tpipeline_desc.pipeline = std::shared_ptr<RHIPipelineState>(std::move(rhi_context->CreatePipelineState()));\n\n\t\tif (rhi_context->IsFeatureSupport(RHIFeature::MeshShading))\n\t\t{\n\t\t\tauto *task_shader = renderer->RequireShader(\"Source/Shaders/RenderPath/VisibilityGeometryPass.hlsl\", \"ASmain\", RHIShaderStage::Task, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\t\t\tauto *mesh_shader = renderer->RequireShader(\"Source/Shaders/RenderPath/VisibilityGeometryPass.hlsl\", \"MSmain\", RHIShaderStage::Mesh, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\t\t\tauto *frag_shader = renderer->RequireShader(\"Source/Shaders/RenderPath/VisibilityGeometryPass.hlsl\", \"PSmain\", RHIShaderStage::Fragment, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Task, task_shader);\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Mesh, mesh_shader);\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Fragment, frag_shader);\n\n\t\t\tBlendState blend_state;\n\t\t\tblend_state.attachment_states.resize(1);\n\t\t\tpipeline_desc.pipeline->SetBlendState(blend_state);\n\n\t\t\tRasterizationState rasterization_state;\n\t\t\trasterization_state.cull_mode  = RHICullMode::None;\n\t\t\trasterization_state.front_face = RHIFrontFace::Clockwise;\n\t\t\tpipeline_desc.pipeline->SetRasterizationState(rasterization_state);\n\n\t\t\tDepthStencilState depth_stencil_state  = {};\n\t\t\tdepth_stencil_state.depth_write_enable = true;\n\t\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\t\tpipeline_desc.pipeline->SetDepthStencilState(depth_stencil_state);\n\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(task_shader);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(mesh_shader);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(frag_shader);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto *vertex_shader = renderer->RequireShader(\"Source/Shaders/RenderPath/VisibilityGeometryPass.hlsl\", \"VSmain\", RHIShaderStage::Vertex, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\t\t\tauto *frag_shader   = renderer->RequireShader(\"Source/Shaders/RenderPath/VisibilityGeometryPass.hlsl\", \"FSmain\", RHIShaderStage::Fragment, {has_skinned ? \"HAS_SKINNED\" : \"NO_SKINNED\"});\n\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Vertex, vertex_shader);\n\t\t\tpipeline_desc.pipeline->SetShader(RHIShaderStage::Fragment, frag_shader);\n\n\t\t\tBlendState blend_state;\n\t\t\tblend_state.attachment_states.resize(1);\n\t\t\tpipeline_desc.pipeline->SetBlendState(blend_state);\n\n\t\t\tRasterizationState rasterization_state;\n\t\t\trasterization_state.cull_mode  = RHICullMode::None;\n\t\t\trasterization_state.front_face = RHIFrontFace::Clockwise;\n\t\t\tpipeline_desc.pipeline->SetRasterizationState(rasterization_state);\n\n\t\t\tDepthStencilState depth_stencil_state  = {};\n\t\t\tdepth_stencil_state.depth_write_enable = true;\n\t\t\tdepth_stencil_state.depth_test_enable  = true;\n\t\t\tpipeline_desc.pipeline->SetDepthStencilState(depth_stencil_state);\n\n\t\t\tVertexInputState vertex_input_state = {};\n\t\t\tif (has_skinned)\n\t\t\t{\n\t\t\t\tvertex_input_state.input_bindings = {\n\t\t\t\t    VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex), RHIVertexInputRate::Vertex}};\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 3, 0, RHIFormat::R32G32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, texcoord0)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 5, 0, RHIFormat::R32G32B32A32_SINT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, bones[0])},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Indices, 6, 0, RHIFormat::R32G32B32A32_SINT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, bones[4])},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Weights, 7, 0, RHIFormat::R32G32B32A32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, weights[0])},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Blend_Weights, 8, 0, RHIFormat::R32G32B32A32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, weights[4])},\n\t\t\t\t};\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvertex_input_state.input_bindings = {\n\t\t\t\t    VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::Mesh>::Vertex), RHIVertexInputRate::Vertex}};\n\t\t\t\tvertex_input_state.input_attributes = {\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, position)},\n\t\t\t\t    VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 3, 0, RHIFormat::R32G32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, texcoord0)},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tpipeline_desc.pipeline->SetVertexInputState(vertex_input_state);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(vertex_shader);\n\t\t\tpipeline_desc.meta += renderer->RequireShaderMeta(frag_shader);\n\t\t}\n\n\t\treturn pipeline_desc;\n\t}\n};\n\nCONFIGURATION_PASS(VisibilityGeometryPass)"
  },
  {
    "path": "Source/Plugin/RenderPass/VisibilityLightingPass.cpp",
    "content": "#include \"IPass.hpp\"\n#include \"PassData.hpp\"\n\n#include <Material/MaterialData.hpp>\n#include <Resource/ResourceManager.hpp>\n\nusing namespace Ilum;\n\nclass VisibilityLightingPass : public RenderPass<VisibilityLightingPass>\n{\n\tenum class ShadowFilterMode\n\t{\n\t\tNone,\n\t\tHard,\n\t\tPCF,\n\t\tPCSS\n\t};\n\n\tstruct Config\n\t{\n\t\tShadowFilterMode shadow_filter_mode = ShadowFilterMode::PCF;\n\t};\n\n\tstd::unordered_map<ShadowFilterMode, const char *> shadow_filter_modes = {\n\t    {ShadowFilterMode::None, \"SHADOW_FILTER_NONE\"},\n\t    {ShadowFilterMode::Hard, \"SHADOW_FILTER_HARD\"},\n\t    {ShadowFilterMode::PCF, \"SHADOW_FILTER_PCF\"},\n\t    {ShadowFilterMode::PCSS, \"SHADOW_FILTER_PCSS\"},\n\t};\n\n  public:\n\tVisibilityLightingPass() = default;\n\n\t~VisibilityLightingPass() = default;\n\n\tvirtual RenderPassDesc Create(size_t &handle)\n\t{\n\t\tRenderPassDesc desc;\n\t\treturn desc.SetBindPoint(BindPoint::Compute)\n\t\t    .SetName(\"VisibilityLightingPass\")\n\t\t    .SetCategory(\"RenderPath\")\n\t\t    .SetConfig(Config())\n\t\t    .ReadTexture2D(handle++, \"Visibility Buffer\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"Depth Buffer\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"ShadowMap\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"CascadeShadowMap\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"OmniShadowMap\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"IrradianceSH\", RHIResourceState::ShaderResource)\n\t\t    .ReadTexture2D(handle++, \"PrefilterMap\", RHIResourceState::ShaderResource)\n\t\t    .WriteTexture2D(handle++, \"Position Depth\", RHIFormat::R32G32B32A32_FLOAT, RHIResourceState::UnorderedAccess)\n\t\t    .WriteTexture2D(handle++, \"Normal Roughness\", RHIFormat::R8G8B8A8_UNORM, RHIResourceState::UnorderedAccess)\n\t\t    .WriteTexture2D(handle++, \"Albedo Metallic\", RHIFormat::R8G8B8A8_UNORM, RHIResourceState::UnorderedAccess)\n\t\t    .WriteTexture2D(handle++, \"Env DI\", RHIFormat::R16G16B16A16_FLOAT, RHIResourceState::UnorderedAccess)\n\t\t    .WriteTexture2D(handle++, \"Light DI\", RHIFormat::R16G16B16A16_FLOAT, RHIResourceState::UnorderedAccess);\n\t}\n\n\tvirtual void CreateCallback(RenderGraph::RenderTask *task, const RenderPassDesc &desc, RenderGraphBuilder &builder, Renderer *renderer)\n\t{\n\t\tstd::shared_ptr<RHIPipelineState> pipeline_state = std::move(renderer->GetRHIContext()->CreatePipelineState());\n\n\t\tstruct LightingPassData\n\t\t{\n\t\t\tstd::unique_ptr<RHIBuffer> material_count_buffer   = nullptr;\n\t\t\tstd::unique_ptr<RHIBuffer> material_offset_buffer  = nullptr;\n\t\t\tstd::unique_ptr<RHIBuffer> material_pixel_buffer   = nullptr;\n\t\t\tstd::unique_ptr<RHIBuffer> indirect_command_buffer = nullptr;\n\t\t};\n\n\t\t*task = [=](RenderGraph &render_graph, RHICommand *cmd_buffer, Variant &config, RenderGraphBlackboard &black_board) {\n\t\t\tauto *visibility_buffer         = render_graph.GetTexture(desc.GetPin(\"Visibility Buffer\").handle);\n\t\t\tauto *depth_buffer              = render_graph.GetTexture(desc.GetPin(\"Depth Buffer\").handle);\n\t\t\tauto *shadow_map                = render_graph.GetTexture(desc.GetPin(\"ShadowMap\").handle);\n\t\t\tauto *cascade_shadow_map        = render_graph.GetTexture(desc.GetPin(\"CascadeShadowMap\").handle);\n\t\t\tauto *omni_shadow_map           = render_graph.GetTexture(desc.GetPin(\"OmniShadowMap\").handle);\n\t\t\tauto *irradiance_sh             = render_graph.GetTexture(desc.GetPin(\"IrradianceSH\").handle);\n\t\t\tauto *prefilter_map             = render_graph.GetTexture(desc.GetPin(\"PrefilterMap\").handle);\n\t\t\tauto *env_direct_illumination   = render_graph.GetTexture(desc.GetPin(\"Env DI\").handle);\n\t\t\tauto *light_direct_illumination = render_graph.GetTexture(desc.GetPin(\"Light DI\").handle);\n\t\t\tauto *position_depth            = render_graph.GetTexture(desc.GetPin(\"Position Depth\").handle);\n\t\t\tauto *normal_roughness          = render_graph.GetTexture(desc.GetPin(\"Normal Roughness\").handle);\n\t\t\tauto *albedo_metallic           = render_graph.GetTexture(desc.GetPin(\"Albedo Metallic\").handle);\n\n\t\t\tConfig *config_data = config.Convert<Config>();\n\n\t\t\tGPUScene   *gpu_scene   = black_board.Get<GPUScene>();\n\t\t\tView       *view        = black_board.Get<View>();\n\t\t\tRHIContext *rhi_context = renderer->GetRHIContext();\n\n\t\t\tLightingPassData *pass_data = black_board.Has<LightingPassData>() ? black_board.Get<LightingPassData>() : black_board.Add<LightingPassData>();\n\n\t\t\tsize_t material_count = renderer->GetResourceManager()->GetValidResourceCount<ResourceType::Material>() + 1;\n\n\t\t\tbool has_mesh              = gpu_scene->opaque_mesh.instance_count != 0;\n\t\t\tbool has_skinned_mesh      = gpu_scene->opaque_skinned_mesh.instance_count != 0;\n\t\t\tbool has_point_light       = gpu_scene->light.info.point_light_count != 0;\n\t\t\tbool has_spot_light        = gpu_scene->light.info.spot_light_count != 0;\n\t\t\tbool has_directional_light = gpu_scene->light.info.directional_light_count != 0;\n\t\t\tbool has_rect_light        = gpu_scene->light.info.rect_light_count != 0;\n\t\t\tbool has_env_light         = gpu_scene->texture.texture_cube != nullptr;\n\n\t\t\tif (!pass_data->material_count_buffer ||\n\t\t\t    pass_data->material_count_buffer->GetDesc().size != material_count * sizeof(uint32_t))\n\t\t\t{\n\t\t\t\tpass_data->material_count_buffer = rhi_context->CreateBuffer<uint32_t>(material_count, RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t}\n\n\t\t\tif (!pass_data->material_offset_buffer ||\n\t\t\t    pass_data->material_offset_buffer->GetDesc().size != material_count * sizeof(uint32_t))\n\t\t\t{\n\t\t\t\tpass_data->material_offset_buffer = rhi_context->CreateBuffer<uint32_t>(material_count, RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t}\n\n\t\t\tif (!pass_data->material_pixel_buffer ||\n\t\t\t    pass_data->material_pixel_buffer->GetDesc().size != static_cast<size_t>(visibility_buffer->GetDesc().width * visibility_buffer->GetDesc().height) * sizeof(uint32_t))\n\t\t\t{\n\t\t\t\tpass_data->material_pixel_buffer = rhi_context->CreateBuffer<uint32_t>(visibility_buffer->GetDesc().width * visibility_buffer->GetDesc().height, RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t}\n\n\t\t\tif (!pass_data->indirect_command_buffer ||\n\t\t\t    pass_data->indirect_command_buffer->GetDesc().size != material_count * sizeof(RHIDispatchIndirectCommand))\n\t\t\t{\n\t\t\t\tpass_data->indirect_command_buffer = rhi_context->CreateBuffer<RHIDispatchIndirectCommand>(material_count, RHIBufferUsage::Indirect | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {},\n\t\t\t\t    {BufferStateTransition{\n\t\t\t\t        pass_data->indirect_command_buffer.get(),\n\t\t\t\t        RHIResourceState::Undefined,\n\t\t\t\t        RHIResourceState::IndirectBuffer}});\n\t\t\t}\n\n\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t    {TextureStateTransition{\n\t\t\t         light_direct_illumination,\n\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t         RHIResourceState::TransferDest},\n\t\t\t     TextureStateTransition{\n\t\t\t         position_depth,\n\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t         RHIResourceState::TransferDest},\n\t\t\t     TextureStateTransition{\n\t\t\t         normal_roughness,\n\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t         RHIResourceState::TransferDest},\n\t\t\t     TextureStateTransition{\n\t\t\t         albedo_metallic,\n\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t         RHIResourceState::TransferDest}},\n\t\t\t    {BufferStateTransition{\n\t\t\t         pass_data->indirect_command_buffer.get(),\n\t\t\t         RHIResourceState::IndirectBuffer,\n\t\t\t         RHIResourceState::TransferDest},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->material_offset_buffer.get(),\n\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t         RHIResourceState::TransferDest},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->material_count_buffer.get(),\n\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t         RHIResourceState::TransferDest}});\n\n\t\t\tcmd_buffer->FillTexture(light_direct_illumination, RHIResourceState::TransferDest, TextureRange{}, glm::vec4(0.f));\n\t\t\tcmd_buffer->FillTexture(position_depth, RHIResourceState::TransferDest, TextureRange{}, glm::vec4(0.f));\n\t\t\tcmd_buffer->FillTexture(normal_roughness, RHIResourceState::TransferDest, TextureRange{}, glm::vec4(0.f));\n\t\t\tcmd_buffer->FillTexture(albedo_metallic, RHIResourceState::TransferDest, TextureRange{}, glm::vec4(0.f));\n\t\t\tcmd_buffer->FillBuffer(pass_data->material_offset_buffer.get(), RHIResourceState::TransferDest, pass_data->material_offset_buffer->GetDesc().size);\n\t\t\tcmd_buffer->FillBuffer(pass_data->material_count_buffer.get(), RHIResourceState::TransferDest, pass_data->material_count_buffer->GetDesc().size);\n\t\t\tcmd_buffer->FillBuffer(pass_data->indirect_command_buffer.get(), RHIResourceState::TransferDest, pass_data->indirect_command_buffer->GetDesc().size);\n\n\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t    {TextureStateTransition{\n\t\t\t         light_direct_illumination,\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     TextureStateTransition{\n\t\t\t         position_depth,\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     TextureStateTransition{\n\t\t\t         normal_roughness,\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     TextureStateTransition{\n\t\t\t         albedo_metallic,\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess}},\n\t\t\t    {BufferStateTransition{\n\t\t\t         pass_data->material_offset_buffer.get(),\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->indirect_command_buffer.get(),\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->material_count_buffer.get(),\n\t\t\t         RHIResourceState::TransferDest,\n\t\t\t         RHIResourceState::UnorderedAccess}});\n\n\t\t\t// Collect material count\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Collect Material Count\");\n\t\t\t\tauto *shader = renderer->RequireShader(\n\t\t\t\t    \"Source/Shaders/RenderPath/VisibilityLightingPass.hlsl\",\n\t\t\t\t    \"CollectMaterialCount\",\n\t\t\t\t    RHIShaderStage::Compute,\n\t\t\t\t    {\n\t\t\t\t        has_mesh ? \"HAS_MESH\" : \"NO_MESH\",\n\t\t\t\t        has_skinned_mesh ? \"HAS_SKINNED_MESH\" : \"NO_SKINNED_MESH\",\n\t\t\t\t    });\n\t\t\t\tauto meta = renderer->RequireShaderMeta(shader);\n\t\t\t\tpipeline_state->ClearShader().SetShader(RHIShaderStage::Compute, shader);\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\t\tdescriptor->BindTexture(\"VisibilityBuffer\", visibility_buffer, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"DepthBuffer\", depth_buffer, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindBuffer(\"MeshInstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"SkinnedMeshInstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"MaterialCountBuffer\", pass_data->material_count_buffer.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(visibility_buffer->GetDesc().width, visibility_buffer->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {},\n\t\t\t\t    {BufferStateTransition{\n\t\t\t\t        pass_data->material_count_buffer.get(),\n\t\t\t\t        RHIResourceState::UnorderedAccess,\n\t\t\t\t        RHIResourceState::ShaderResource}});\n\t\t\t}\n\n\t\t\t// Calculate material offset\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Calculate Material Offset\");\n\t\t\t\tauto *shader = renderer->RequireShader(\n\t\t\t\t    \"Source/Shaders/RenderPath/VisibilityLightingPass.hlsl\",\n\t\t\t\t    \"CalculateMaterialOffset\",\n\t\t\t\t    RHIShaderStage::Compute);\n\t\t\t\tauto meta = renderer->RequireShaderMeta(shader);\n\t\t\t\tpipeline_state->ClearShader().SetShader(RHIShaderStage::Compute, shader);\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\t\tdescriptor->BindBuffer(\"MaterialCountBuffer\", pass_data->material_count_buffer.get())\n\t\t\t\t    .BindBuffer(\"MaterialOffsetBuffer\", pass_data->material_offset_buffer.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(static_cast<uint32_t>(material_count), 1, 1, 128, 1, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Write -> Read\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {},\n\t\t\t\t    {BufferStateTransition{\n\t\t\t\t        pass_data->material_offset_buffer.get(),\n\t\t\t\t        RHIResourceState::UnorderedAccess,\n\t\t\t\t        RHIResourceState::ShaderResource}});\n\t\t\t}\n\n\t\t\t// Calculate pixel buffer\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Calculate Pixel Buffer\");\n\t\t\t\tauto *shader = renderer->RequireShader(\n\t\t\t\t    \"Source/Shaders/RenderPath/VisibilityLightingPass.hlsl\",\n\t\t\t\t    \"CalculatePixelBuffer\",\n\t\t\t\t    RHIShaderStage::Compute,\n\t\t\t\t    {\n\t\t\t\t        has_mesh ? \"HAS_MESH\" : \"NO_MESH\",\n\t\t\t\t        has_skinned_mesh ? \"HAS_SKINNED_MESH\" : \"NO_SKINNED_MESH\",\n\t\t\t\t    });\n\t\t\t\tauto meta = renderer->RequireShaderMeta(shader);\n\t\t\t\tpipeline_state->ClearShader().SetShader(RHIShaderStage::Compute, shader);\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\t\tdescriptor->BindTexture(\"VisibilityBuffer\", visibility_buffer, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindTexture(\"DepthBuffer\", depth_buffer, RHITextureDimension::Texture2D)\n\t\t\t\t    .BindBuffer(\"MeshInstanceBuffer\", gpu_scene->opaque_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"SkinnedMeshInstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get())\n\t\t\t\t    .BindBuffer(\"MaterialCountBuffer\", pass_data->material_count_buffer.get())\n\t\t\t\t    .BindBuffer(\"MaterialOffsetBuffer\", pass_data->material_offset_buffer.get())\n\t\t\t\t    .BindBuffer(\"MaterialPixelBuffer\", pass_data->material_pixel_buffer.get())\n\t\t\t\t    .BindBuffer(\"IndirectCommandBuffer\", pass_data->indirect_command_buffer.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(visibility_buffer->GetDesc().width, visibility_buffer->GetDesc().height, 1, 8, 8, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {},\n\t\t\t\t    {BufferStateTransition{\n\t\t\t\t        pass_data->indirect_command_buffer.get(),\n\t\t\t\t        RHIResourceState::UnorderedAccess,\n\t\t\t\t        RHIResourceState::UnorderedAccess}});\n\t\t\t}\n\n\t\t\t// Calculate indirect argument\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Calculate Indirect Argument\");\n\t\t\t\tauto *shader = renderer->RequireShader(\n\t\t\t\t    \"Source/Shaders/RenderPath/VisibilityLightingPass.hlsl\",\n\t\t\t\t    \"CalculateIndirectArgument\",\n\t\t\t\t    RHIShaderStage::Compute);\n\t\t\t\tauto meta = renderer->RequireShaderMeta(shader);\n\t\t\t\tpipeline_state->ClearShader().SetShader(RHIShaderStage::Compute, shader);\n\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\t\tdescriptor->BindBuffer(\"IndirectCommandBuffer\", pass_data->indirect_command_buffer.get());\n\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\tcmd_buffer->Dispatch(static_cast<uint32_t>(material_count), 1, 1, 8, 1, 1);\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\t// Write -> Read\n\t\t\t{\n\t\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t\t    {},\n\t\t\t\t    {BufferStateTransition{\n\t\t\t\t         pass_data->material_pixel_buffer.get(),\n\t\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t\t         RHIResourceState::ShaderResource},\n\t\t\t\t     BufferStateTransition{\n\t\t\t\t         pass_data->indirect_command_buffer.get(),\n\t\t\t\t         RHIResourceState::UnorderedAccess,\n\t\t\t\t         RHIResourceState::IndirectBuffer}});\n\t\t\t}\n\n\t\t\t// Dispatch\n\t\t\t{\n\t\t\t\tcmd_buffer->BeginMarker(\"Dispatch Indirect\");\n\t\t\t\tfor (size_t i = 0; i < material_count; i++)\n\t\t\t\t{\n\t\t\t\t\tauto *shader = renderer->RequireShader(\n\t\t\t\t\t    \"Source/Shaders/RenderPath/VisibilityLightingPass.hlsl\",\n\t\t\t\t\t    \"DispatchIndirect\",\n\t\t\t\t\t    RHIShaderStage::Compute,\n\t\t\t\t\t    {\n\t\t\t\t\t        has_mesh ? \"HAS_MESH\" : \"NO_MESH\",\n\t\t\t\t\t        has_skinned_mesh ? \"HAS_SKINNED_MESH\" : \"NO_SKINNED_MESH\",\n\t\t\t\t\t        has_point_light ? \"HAS_POINT_LIGHT\" : \"NO_POINT_LIGHT\",\n\t\t\t\t\t        has_spot_light ? \"HAS_SPOT_LIGHT\" : \"NO_SPOT_LIGHT\",\n\t\t\t\t\t        has_directional_light ? \"HAS_DIRECTIONAL_LIGHT\" : \"NO_DIRECTIONAL_LIGHT\",\n\t\t\t\t\t        has_rect_light ? \"HAS_RECT_LIGHT\" : \"NO_RECT_LIGHT\",\n\t\t\t\t\t        has_env_light ? \"HAS_ENV_LIGHT\" : \"NO_ENV_LIGHT\",\n\t\t\t\t\t        shadow_map ? \"HAS_SHADOW_MAP\" : \"NO_SHADOW_MAP\",\n\t\t\t\t\t        cascade_shadow_map ? \"HAS_CASCADE_SHADOW_MAP\" : \"NO_CASCADE_SHADOW_MAP\",\n\t\t\t\t\t        omni_shadow_map ? \"HAS_OMNI_SHADOW_MAP\" : \"NO_OMNI_SHADOW_MAP\",\n\t\t\t\t\t        irradiance_sh ? \"HAS_IRRADIANCE_SH\" : \"NO_IRRADIANCE_SH\",\n\t\t\t\t\t        prefilter_map ? \"HAS_PREFILTER_MAP\" : \"NO_PREFILTER_MAP\",\n\t\t\t\t\t        shadow_filter_modes.at(config_data->shadow_filter_mode),\n\t\t\t\t\t        \"DISPATCH_INDIRECT\",\n\t\t\t\t\t        \"MATERIAL_ID=\" + std::to_string(i),\n\t\t\t\t\t        i == 0 ? \"DEFAULT_MATERIAL\" : gpu_scene->material.data[i - 1]->signature,\n\t\t\t\t\t    },\n\t\t\t\t\t    {\n\t\t\t\t\t        i == 0 ? \"../Material/Material.hlsli\" : gpu_scene->material.data[i - 1]->shader,\n\t\t\t\t\t    });\n\t\t\t\t\tauto meta = renderer->RequireShaderMeta(shader);\n\t\t\t\t\tpipeline_state->ClearShader().SetShader(RHIShaderStage::Compute, shader);\n\t\t\t\t\tauto descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\t\t\tdescriptor->BindTexture(\"VisibilityBuffer\", visibility_buffer, RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindBuffer(\"ViewBuffer\", view->buffer.get())\n\t\t\t\t\t    .BindBuffer(\"LightInfoBuffer\", gpu_scene->light.light_info_buffer.get())\n\t\t\t\t\t    .BindSampler(\"ShadowMapSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t\t\t    .BindBuffer(\"MaterialPixelBuffer\", pass_data->material_pixel_buffer.get())\n\t\t\t\t\t    .BindBuffer(\"MaterialCountBuffer\", pass_data->material_count_buffer.get())\n\t\t\t\t\t    .BindBuffer(\"MaterialOffsetBuffer\", pass_data->material_offset_buffer.get())\n\t\t\t\t\t    .BindTexture(\"Textures\", gpu_scene->texture.texture_2d, RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindSampler(\"Samplers\", gpu_scene->samplers)\n\t\t\t\t\t    .BindBuffer(\"MaterialOffsets\", gpu_scene->material.material_offset.get())\n\t\t\t\t\t    .BindBuffer(\"MaterialBuffer\", gpu_scene->material.material_buffer.get())\n\t\t\t\t\t    .BindTexture(\"LightDirectIllumination\", light_direct_illumination, RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"EnvDirectIllumination\", env_direct_illumination, RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"PositionDepth\", position_depth, RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"NormalRoughness\", normal_roughness, RHITextureDimension::Texture2D)\n\t\t\t\t\t    .BindTexture(\"AlbedoMetallic\", albedo_metallic, RHITextureDimension::Texture2D);\n\n\t\t\t\t\tif (has_mesh)\n\t\t\t\t\t{\n\t\t\t\t\t\tdescriptor->BindBuffer(\"MeshVertexBuffer\", gpu_scene->mesh_buffer.vertex_buffers)\n\t\t\t\t\t\t    .BindBuffer(\"MeshIndexBuffer\", gpu_scene->mesh_buffer.index_buffers)\n\t\t\t\t\t\t    .BindBuffer(\"MeshInstanceBuffer\", gpu_scene->opaque_mesh.instances.get());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (has_skinned_mesh)\n\t\t\t\t\t{\n\t\t\t\t\t\tdescriptor->BindBuffer(\"SkinnedMeshVertexBuffer\", gpu_scene->skinned_mesh_buffer.vertex_buffers)\n\t\t\t\t\t\t    .BindBuffer(\"SkinnedMeshIndexBuffer\", gpu_scene->skinned_mesh_buffer.index_buffers)\n\t\t\t\t\t\t    .BindBuffer(\"BoneMatrices\", gpu_scene->animation.bone_matrics)\n\t\t\t\t\t\t    .BindBuffer(\"SkinnedMeshInstanceBuffer\", gpu_scene->opaque_skinned_mesh.instances.get());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (has_point_light)\n\t\t\t\t\t{\n\t\t\t\t\t\tdescriptor->BindBuffer(\"PointLightBuffer\", gpu_scene->light.point_light_buffer.get());\n\t\t\t\t\t\tif (omni_shadow_map)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescriptor->BindTexture(\"PointLightShadow\", omni_shadow_map, RHITextureDimension::TextureCubeArray);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (has_spot_light)\n\t\t\t\t\t{\n\t\t\t\t\t\tdescriptor->BindBuffer(\"SpotLightBuffer\", gpu_scene->light.spot_light_buffer.get());\n\t\t\t\t\t\tif (shadow_map)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescriptor->BindTexture(\"SpotLightShadow\", shadow_map, RHITextureDimension::Texture2DArray);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (has_directional_light)\n\t\t\t\t\t{\n\t\t\t\t\t\tdescriptor->BindBuffer(\"DirectionalLightBuffer\", gpu_scene->light.directional_light_buffer.get());\n\t\t\t\t\t\tif (cascade_shadow_map)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescriptor->BindTexture(\"DirectionalLightShadow\", cascade_shadow_map, RHITextureDimension::Texture2DArray);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (has_rect_light)\n\t\t\t\t\t{\n\t\t\t\t\t\tdescriptor->BindBuffer(\"RectLightBuffer\", gpu_scene->light.rect_light_buffer.get());\n\t\t\t\t\t}\n\n\t\t\t\t\tif (has_env_light)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (irradiance_sh)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescriptor->BindTexture(\"IrradianceSH\", irradiance_sh, RHITextureDimension::Texture2D);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (prefilter_map)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescriptor->BindTexture(\"PrefilterMap\", prefilter_map, RHITextureDimension::TextureCube)\n\t\t\t\t\t\t\t    .BindSampler(\"PrefilterMapSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()))\n\t\t\t\t\t\t\t    .BindTexture(\"GGXPreintegration\", black_board.Get<LUT>()->ggx.get(), RHITextureDimension::Texture2D);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\t\t\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\t\t\t\t\tcmd_buffer->DispatchIndirect(pass_data->indirect_command_buffer.get(), i * sizeof(RHIDispatchIndirectCommand));\n\t\t\t\t}\n\t\t\t\tcmd_buffer->EndMarker();\n\t\t\t}\n\n\t\t\tcmd_buffer->ResourceStateTransition(\n\t\t\t    {},\n\t\t\t    {BufferStateTransition{\n\t\t\t         pass_data->indirect_command_buffer.get(),\n\t\t\t         RHIResourceState::IndirectBuffer,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->material_offset_buffer.get(),\n\t\t\t         RHIResourceState::ShaderResource,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->material_pixel_buffer.get(),\n\t\t\t         RHIResourceState::ShaderResource,\n\t\t\t         RHIResourceState::UnorderedAccess},\n\t\t\t     BufferStateTransition{\n\t\t\t         pass_data->material_count_buffer.get(),\n\t\t\t         RHIResourceState::ShaderResource,\n\t\t\t         RHIResourceState::UnorderedAccess}});\n\t\t};\n\t}\n\n\tvirtual void OnImGui(Variant *config)\n\t{\n\t\tConfig *config_data = config->Convert<Config>();\n\n\t\tconst char *const shadow_filter_modes[] = {\"None\", \"Hard\", \"PCF\", \"PCSS\"};\n\t\tImGui::Combo(\"Shadow Filter Mode\", reinterpret_cast<int32_t *>(&config_data->shadow_filter_mode), shadow_filter_modes, 4);\n\t}\n};\n\nCONFIGURATION_PASS(VisibilityLightingPass)\n"
  },
  {
    "path": "Source/Plugin/RenderPass/xmake.lua",
    "content": "function add_pass_plugin(category, name)\n    target(string.format(\"RenderPass.%s.%s\", category, name))\n\n    set_kind(\"shared\")\n    set_group(string.format(\"Plugin/RenderPass/%s\", category))\n\n    add_rules(\"plugin\")\n    add_files(string.format(\"%s.cpp\", name))\n    add_headerfiles(\"IPass.hpp\", \"PassData.hpp\")\n    add_includedirs(\"./\")\n    add_deps(\"Core\", \"RHI\", \"RenderGraph\", \"Renderer\", \"Scene\", \"Resource\", \"Geometry\", \"Material\")\n    add_packages(\"imgui\")\n\n    target(\"Plugin\")\n        add_deps(string.format(\"RenderPass.%s.%s\", category, name))\n    target_end()\n\n    target_end()\nend\n\nadd_pass_plugin(\"Output\", \"Present\")\nadd_pass_plugin(\"Transfer\", \"CopyImageRGBA16\")\nadd_pass_plugin(\"RayTracing\", \"PathTracing\")\nadd_pass_plugin(\"RenderPath\", \"VisibilityGeometryPass\")\nadd_pass_plugin(\"RenderPath\", \"VisibilityLightingPass\")\nadd_pass_plugin(\"RenderPath\", \"VisibilityBufferVisualization\")\nadd_pass_plugin(\"Shading\", \"IBL\")\nadd_pass_plugin(\"Shading\", \"SkyBoxPass\")\nadd_pass_plugin(\"Shading\", \"ShadowMapPass\")\nadd_pass_plugin(\"Shading\", \"CompositePass\")\nadd_pass_plugin(\"PostProcess\", \"Bloom\")\nadd_pass_plugin(\"PostProcess\", \"FXAA\")\nadd_pass_plugin(\"PostProcess\", \"Tonemapping\")\nadd_pass_plugin(\"Shadow\", \"ShadowMapPass\")\nadd_pass_plugin(\"AO\", \"SSAO\")\nadd_pass_plugin(\"AO\", \"RayTracedAO\")\n"
  },
  {
    "path": "Source/Plugin/xmake.lua",
    "content": "includes(\"RHI\")\nincludes(\"Editor\")\nincludes(\"Importer\")\nincludes(\"Geometry\")\nincludes(\"RenderPass\")\nincludes(\"MaterialNode\")"
  },
  {
    "path": "Source/Runtime/Core/Private/JobSystem.cpp",
    "content": "#include \"JobSystem.hpp\"\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nSpinLock::SpinLock() :\n    m_flag{ATOMIC_FLAG_INIT}\n{\n}\n\nvoid SpinLock::Lock()\n{\n\twhile (m_flag.test_and_set(std::memory_order_acquire))\n\t\t;\n}\n\nvoid SpinLock::Unlock()\n{\n\tm_flag.clear(std::memory_order_release);\n}\n\nThreadPool::ThreadPool(uint32_t max_threads_num)\n{\n\tfor (uint32_t i = 0; i < max_threads_num; i++)\n\t{\n\t\tm_workers.emplace_back(\n\t\t    [this]() {\n\t\t\t    while (true)\n\t\t\t    {\n\t\t\t\t    std::function<void()> task;\n\n\t\t\t\t    {\n\t\t\t\t\t    std::unique_lock<std::mutex> lock(m_mutex);\n\t\t\t\t\t    m_condition.wait(lock, [this]() { return m_stop || !m_task_queue.Empty(); });\n\t\t\t\t\t    if (m_stop && m_task_queue.Empty())\n\t\t\t\t\t    {\n\t\t\t\t\t\t    return;\n\t\t\t\t\t    }\n\t\t\t\t\t    m_task_queue.TryPop(task);\n\t\t\t\t    }\n\n\t\t\t\t    task();\n\t\t\t    }\n\t\t    });\n\t}\n}\n\nThreadPool ::~ThreadPool()\n{\n\t{\n\t\tstd::unique_lock<std::mutex> lock(m_mutex);\n\t\tm_stop = true;\n\t}\n\n\tm_condition.notify_all();\n\tfor (auto &worker : m_workers)\n\t{\n\t\tworker.join();\n\t}\n}\n\nsize_t ThreadPool::GetThreadCount() const\n{\n\treturn m_workers.size();\n}\n\nvoid ThreadPool::WaitAll()\n{\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\t\tm_condition.notify_all();\n\t}\n\n\tfor (auto &worker : m_workers)\n\t{\n\t\tif (worker.joinable())\n\t\t{\n\t\t\tworker.join();\n\t\t}\n\t}\n}\n\nJobNode::JobNode(std::function<void()> &&task) :\n    m_task(task)\n{\n}\n\nstd::type_index JobNode::GetType()\n{\n\treturn typeid(JobNode);\n}\n\nvoid JobNode::Percede(JobNode *node)\n{\n\tif (!node)\n\t{\n\t\treturn;\n\t}\n\n\tm_successors.push_back(node);\n\tnode->m_dependents.push_back(this);\n\tnode->m_unfinish_dependents++;\n}\n\nvoid JobNode::Succeed(JobNode *node)\n{\n\tif (!node)\n\t{\n\t\treturn;\n\t}\n\n\tnode->m_successors.push_back(this);\n\tthis->m_dependents.push_back(node);\n\tthis->m_unfinish_dependents++;\n}\n\nbool JobNode::Compile()\n{\n\treturn true;\n}\n\nvoid JobNode::Run()\n{\n\tassert(m_unfinish_dependents == 0 && \"Some dependents haven't completed yet\");\n\n\tm_task();\n\n\tm_unfinish_dependents = static_cast<uint32_t>(m_dependents.size());\n\n\tfor (auto *node : m_successors)\n\t{\n\t\tnode->m_unfinish_dependents.fetch_sub(1, std::memory_order_relaxed);\n\t}\n}\n\nstd::type_index JobGraph::GetType()\n{\n\treturn typeid(JobGraph);\n}\n\nJobGraph &JobGraph::AddNode(JobNode *node)\n{\n\tm_nodes.push_back(node);\n\treturn *this;\n}\n\nbool JobGraph::Compile()\n{\n\tstd::queue<JobNode *>  queue;\n\tstd::vector<JobNode *> result;\n\n\tstd::unordered_map<JobNode *, uint32_t> in_degree;\n\n\tfor (auto *node : m_nodes)\n\t{\n\t\tif (in_degree.find(node) != in_degree.end())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tin_degree[node] = static_cast<uint32_t>(node->m_dependents.size());\n\t\tif (in_degree[node] == 0)\n\t\t{\n\t\t\tqueue.push(node);\n\t\t}\n\t}\n\n\twhile (!queue.empty())\n\t{\n\t\tauto *t = queue.front();\n\t\tqueue.pop();\n\n\t\tif (!t->Compile())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tresult.push_back(t);\n\n\t\tfor (auto *node : t->m_successors)\n\t\t{\n\t\t\tin_degree[node]--;\n\t\t\tif (in_degree[node] == 0)\n\t\t\t{\n\t\t\t\tqueue.push(node);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (result.size() == m_nodes.size())\n\t{\n\t\tm_nodes = std::move(result);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nvoid JobGraph::Run()\n{\n\tCompile();\n\n\tfor (auto &node : m_nodes)\n\t{\n\t\tnode->Run();\n\t}\n}\n\nJobSystem::JobSystem()\n{\n\tm_thread_pool = std::make_unique<ThreadPool>(std::thread::hardware_concurrency() - 1);\n}\n\nJobSystem::~JobSystem()\n{\n\tm_thread_pool.reset();\n}\n\nJobSystem &JobSystem::GetInstance()\n{\n\tstatic JobSystem job_system;\n\treturn job_system;\n}\n\nsize_t JobSystem::GetThreadCount()\n{\n\treturn m_thread_pool->GetThreadCount();\n}\n\nvoid JobSystem::Execute(JobHandle &handle, JobGraph &graph)\n{\n\tstd::unordered_set<JobNode *> finished_nodes;\n\n\thandle.m_counter.fetch_add(static_cast<uint32_t>(graph.m_nodes.size()));\n\n\twhile (handle.m_counter > 0)\n\t{\n\t\tfor (auto &node : graph.m_nodes)\n\t\t{\n\t\t\tif (node->m_unfinish_dependents == 0 && finished_nodes.find(node) == finished_nodes.end())\n\t\t\t{\n\t\t\t\tfinished_nodes.insert(node);\n\n\t\t\t\tif (node->GetType() == typeid(JobNode))\n\t\t\t\t{\n\t\t\t\t\tm_thread_pool->AddTask([&node, &handle]() {\n\t\t\t\t\t\tnode->Run();\n\t\t\t\t\t\thandle.m_counter.fetch_sub(1);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_thread_pool->AddTask([&node, &handle, this]() {\n\t\t\t\t\t\thandle.m_counter.fetch_sub(1);\n\t\t\t\t\t\tExecute(handle, *static_cast<JobGraph *>(node));\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid JobSystem::Execute(JobHandle &handle, JobNode &node)\n{\n\thandle.m_counter.fetch_add(1);\n\n\tm_thread_pool->AddTask([&node, &handle]() { node.Run();handle.m_counter.fetch_sub(1); });\n}\n\nvoid JobSystem::Dispatch(JobHandle &handle, uint32_t job_count, uint32_t group_size, const std::function<void(uint32_t)> &task)\n{\n\tuint32_t group_count = (job_count + group_size - 1) / group_size;\n\n\thandle.m_counter.fetch_add(group_count);\n\n\tfor (uint32_t group_id = 0; group_id < group_count; group_id++)\n\t{\n\t\tm_thread_pool->AddTask([task, &handle, group_id]() {\n\t\t\ttask(group_id);\n\t\t\thandle.m_counter.fetch_sub(1);\n\t\t});\n\t}\n}\n\nbool JobSystem::IsBusy(const JobHandle &handle)\n{\n\treturn handle.m_counter.load() > 0;\n}\n\nvoid JobSystem::Wait(const JobHandle &handle)\n{\n\twhile (IsBusy(handle))\n\t{\n\t\t// wait...\n\t}\n}\n\nvoid JobSystem::WaitAll()\n{\n\tm_thread_pool->WaitAll();\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Private/Log.cpp",
    "content": "#include \"Log.hpp\"\n\n#include <spdlog/async.h>\n#include <spdlog/details/log_msg_buffer.h>\n#include <spdlog/sinks/basic_file_sink.h>\n\nnamespace Ilum\n{\nclass Sink : public spdlog::sinks::base_sink<std::mutex>\n{\n  public:\n\tstruct LogMsg\n\t{\n\t\tspdlog::level::level_enum level;\n\t\tstd::string               msg;\n\t};\n\n  public:\n\t// Thread unsafe\n\tconst std::deque<LogMsg> &GetLogs() const\n\t{\n\t\treturn m_log_msgs;\n\t}\n\n\t// Thread safe\n\tstd::vector<LogMsg> CopyLogs() const\n\t{\n\t\tstd::lock_guard<std::mutex> lock(const_cast<std::mutex &>(base_sink<std::mutex>::mutex_));\n\t\tstd::vector<LogMsg>         res(m_log_msgs.begin(), m_log_msgs.end());\n\t\treturn res;\n\t}\n\n\tvoid Clear()\n\t{\n\t\tstd::lock_guard<std::mutex> lock(base_sink<std::mutex>::mutex_);\n\t\tm_log_msgs.clear();\n\t}\n\n  protected:\n\tvirtual void sink_it_(const spdlog::details::log_msg &msg) override\n\t{\n\t\tspdlog::details::log_msg_buffer buffer(msg);\n\t\tspdlog::memory_buf_t            formatted;\n\t\tbase_sink<std::mutex>::formatter_->format(buffer, formatted);\n\t\tm_log_msgs.push_back({msg.level, fmt::to_string(formatted)});\n\t\tstd::cout << fmt::to_string(formatted);\n\t}\n\n\tvirtual void flush_() override\n\t{\n\t\tstd::cout << std::flush;\n\t}\n\n  private:\n\tstd::deque<LogMsg> m_log_msgs;\n};\n\nLogSystem::LogSystem()\n{\n\tm_logger = spdlog::synchronous_factory::create<Sink>(\"Ilum\");\n\n\tm_logger->set_level(spdlog::level::trace);\n}\n\nLogSystem::~LogSystem()\n{\n\tm_logger->flush();\n\tspdlog::drop_all();\n}\n\nLogSystem &LogSystem::GetInstance()\n{\n\tstatic LogSystem log_system;\n\treturn log_system;\n}\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Private/Path.cpp",
    "content": "#include \"Path.hpp\"\n#include \"Core.hpp\"\n\nnamespace Ilum\n{\nPath &Path::GetInstance()\n{\n\tstatic Path path;\n\treturn path;\n}\n\nbool Path::IsExist(const std::string &path)\n{\n\ttry\n\t{\n\t\tif (std::filesystem::exists(path))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tcatch (std::filesystem::filesystem_error &e)\n\t{\n\t\tLOG_WARN(\"%s. %s\", e.what(), path.c_str());\n\t}\n\treturn false;\n}\n\nbool Path::IsFile(const std::string &path)\n{\n\ttry\n\t{\n\t\tif (std::filesystem::exists(path) && std::filesystem::is_regular_file(path))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tcatch (std::filesystem::filesystem_error &e)\n\t{\n\t\tLOG_WARN(\"%s. %s\", e.what(), path.c_str());\n\t}\n\treturn false;\n}\n\nbool Path::IsDirectory(const std::string &path)\n{\n\ttry\n\t{\n\t\tif (std::filesystem::exists(path) && std::filesystem::is_directory(path))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tcatch (std::filesystem::filesystem_error &e)\n\t{\n\t\tLOG_WARN(\"%s. %s\", e.what(), path.c_str());\n\t}\n\treturn false;\n}\n\nbool Path::CreatePath(const std::string &path)\n{\n\ttry\n\t{\n\t\tif (std::filesystem::exists(path) || std::filesystem::create_directories(path))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tcatch (std::filesystem::filesystem_error &e)\n\t{\n\t\tLOG_WARN(\"{}. {}\", e.what(), path.c_str());\n\t}\n\treturn false;\n}\n\nbool Path::DeletePath(const std::string &path)\n{\n\ttry\n\t{\n\t\tif (std::filesystem::exists(path) && std::filesystem::remove_all(path))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\tcatch (std::filesystem::filesystem_error &e)\n\t{\n\t\tLOG_WARN(\"%s. %s\", e.what(), path.c_str());\n\t}\n\treturn false;\n}\n\nbool Path::Copy(const std::string &src, const std::string &dst)\n{\n\tif (src == dst)\n\t{\n\t\treturn true;\n\t}\n\tif (!IsExist(GetFileDirectory(dst)))\n\t{\n\t\tCreatePath(GetFileDirectory(dst));\n\t}\n\ttry\n\t{\n\t\treturn std::filesystem::copy_file(src, dst, std::filesystem::copy_options::overwrite_existing);\n\t}\n\tcatch (std::filesystem::filesystem_error &e)\n\t{\n\t\tLOG_WARN(\"%s\", e.what());\n\t}\n\treturn false;\n}\n\nvoid Path::SetCurrent(const std::string &path)\n{\n\tstd::filesystem::current_path(path);\n}\n\nconst std::string Path::GetCurrent(bool convert)\n{\n\tstd::string current = std::filesystem::current_path().string();\n\tif (convert)\n\t{\n\t\tstd::replace(current.begin(), current.end(), '\\\\', '/');\n\t}\n\treturn current;\n}\n\nconst std::string Path::GetFileName(const std::string &path, bool has_extension)\n{\n\tauto filename = std::filesystem::u8path(path).filename().generic_string();\n\n\tif (has_extension)\n\t{\n\t\treturn filename;\n\t}\n\telse\n\t{\n\t\tsize_t last_index = filename.find_last_of('.');\n\n\t\tif (last_index != std::string::npos)\n\t\t{\n\t\t\treturn filename.substr(0, last_index);\n\t\t}\n\n\t\treturn filename;\n\t}\n}\n\nconst std::string Path::GetFileDirectory(const std::string &path)\n{\n\tif (IsDirectory(path))\n\t{\n\t\treturn path;\n\t}\n\n\tsize_t last_index = path.find_last_of(\"\\\\/\");\n\n\tif (last_index != std::string::npos)\n\t{\n\t\treturn path.substr(0, last_index + 1);\n\t}\n\n\treturn \"\";\n}\n\nconst std::string Path::GetFileExtension(const std::string &path)\n{\n\ttry\n\t{\n\t\treturn std::filesystem::u8path(path).extension().generic_string();\n\t}\n\tcatch (std::system_error &e)\n\t{\n\t\tLOG_WARN(\"Failed: %s\", e.what());\n\t}\n\treturn \"\";\n}\n\nconst std::string Path::GetRelativePath(const std::string &path)\n{\n\tif (!IsExist(path))\n\t{\n\t\treturn \"\";\n\t}\n\n\treturn std::filesystem::relative(path, std::filesystem::current_path()).u8string();\n}\n\nbool Path::Save(const std::string &path, const std::vector<uint8_t> &data, bool binary)\n{\n\tstd::string dir = GetFileDirectory(path);\n\tif (!IsExist(dir))\n\t{\n\t\tCreatePath(dir);\n\t}\n\tstd::ofstream output(path, binary ? std::ofstream::binary : 2);\n\toutput.write(reinterpret_cast<const char *>(data.data()), data.size() * sizeof(uint8_t));\n\toutput.flush();\n\toutput.close();\n\treturn true;\n}\n\nbool Path::Read(const std::string &path, std::vector<uint8_t> &data, bool binary, uint32_t begin, uint32_t end)\n{\n\tif (!IsFile(path))\n\t{\n\t\tLOG_ERROR(\"Failed to read file {}\", path);\n\t\treturn false;\n\t}\n\n\tdata.clear();\n\n\tstd::ifstream file;\n\n\tfile.open(path, std::ios::in | (binary ? std::ios::binary : 0));\n\n\tif (!file.is_open())\n\t{\n\t\tLOG_ERROR(\"Failed to read file {}\", path);\n\t\treturn false;\n\t}\n\n\tuint64_t read_count = end - begin;\n\n\tif ((end == begin && begin == 0) || end < begin)\n\t{\n\t\tfile.seekg(0, std::ios::end);\n\t\tread_count = static_cast<uint64_t>(file.tellg());\n\t\tfile.seekg(0, std::ios::beg);\n\t}\n\n\tdata.resize(static_cast<size_t>(read_count));\n\tfile.read(reinterpret_cast<char *>(data.data()), read_count);\n\tfile.close();\n\n\treturn true;\n}\n\nstd::string Path::Toupper(const std::string &str)\n{\n\tstd::locale loc;\n\tstd::string upper;\n\tfor (const auto &word : str)\n\t{\n\t\tupper += std::toupper(word, loc);\n\t}\n\n\treturn upper;\n}\n\nstd::string Path::Replace(const std::string &str, char from, char to)\n{\n\tstd::string result = str;\n\tstd::replace(result.begin(), result.end(), from, to);\n\treturn result;\n}\n\nstd::string Path::ValidFileName(const std::string &str)\n{\n\tstd::string result = str;\n\n\tstd::unordered_set<char> invalid_char = {'\\\\', '/', ':', '*', '?', '\"', '<', '>', '|'};\n\t\n\tfor (auto& c : result)\n\t{\n\t\tif (invalid_char.find(c) != invalid_char.end())\n\t\t{\n\t\t\tc = '_';\n\t\t}\n\t}\n\n\treturn result;\n}\n\nstd::vector<std::string> Path::Split(const std::string &str, char delim)\n{\n\tstd::vector<std::string> tokens;\n\n\tstd::stringstream sstream(str);\n\tstd::string       token;\n\twhile (std::getline(sstream, token, delim))\n\t{\n\t\ttokens.push_back(token);\n\t}\n\n\treturn tokens;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Private/Plugin.cpp",
    "content": "#include \"Plugin.hpp\"\n\nnamespace Ilum\n{\nstruct PluginManager::Impl\n{\n\tstd::unordered_map<std::string, HMODULE> modules;\n};\n\nPluginManager::PluginManager()\n{\n\tm_impl = new Impl;\n}\n\nPluginManager::~PluginManager()\n{\n\tfor (auto& [name, h_module] : m_impl->modules)\n\t{\n\t\tFreeLibrary(h_module);\n\t}\n\tdelete m_impl;\n}\n\nPluginManager &PluginManager::GetInstance()\n{\n\tstatic PluginManager plugin_manager;\n\treturn plugin_manager;\n}\n\nHMODULE PluginManager::GetLibrary(const std::string &lib_path)\n{\n\tif (m_impl->modules.find(lib_path) == m_impl->modules.end())\n\t{\n\t\tm_impl->modules.emplace(lib_path, LoadLibraryA(lib_path.c_str()));\n\t}\n\treturn m_impl->modules.at(lib_path);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Private/Time.cpp",
    "content": "#include \"Time.hpp\"\n\nnamespace Ilum\n{\nstruct Timer::Impl\n{\n\tTimer::Impl(std::chrono::high_resolution_clock::time_point start, std::chrono::high_resolution_clock::time_point end):\n\t    start(start), tick_end(end)\n\t{\n\t}\n\n\tstd::chrono::high_resolution_clock::time_point start;\n\tstd::chrono::high_resolution_clock::time_point tick_start;\n\tstd::chrono::high_resolution_clock::time_point tick_end;\n\n\tfloat    time                = 0.f;\n\tfloat    delta_time          = 0.f;\n\tfloat    delta_time_smoothed = 0.f;\n\tfloat    accumlate_time      = 0.f;\n\tfloat    frame_rate          = 0.f;\n\tuint32_t frame_count         = 0u;\n\n\tconst uint32_t accumulate = 5u;\n\tconst float    duration   = 500.f;\n};\n\nTimer::Timer()\n{\n\tp_impl = new Impl(std::chrono::high_resolution_clock::now(), std::chrono::high_resolution_clock::now());\n}\n\nTimer::~Timer()\n{\n\tdelete p_impl;\n\tp_impl = nullptr;\n}\n\nTimer &Timer::GetInstance()\n{\n\tstatic Timer timer;\n\treturn timer;\n}\n\nfloat Timer::TotalTime()\n{\n\treturn p_impl->time;\n}\n\nfloat Timer::DeltaTime()\n{\n\treturn p_impl->delta_time;\n}\n\nfloat Timer::DeltaTimeSmoothed()\n{\n\treturn p_impl->delta_time_smoothed;\n}\n\nfloat Timer::FrameRate()\n{\n\treturn p_impl->frame_rate;\n}\n\nvoid Timer::Tick()\n{\n\tp_impl->tick_start                                    = std::chrono::high_resolution_clock::now();\n\tstd::chrono::duration<float, std::milli> delta = p_impl->tick_start - p_impl->tick_end;\n\n\tp_impl->delta_time = delta.count();\n\tp_impl->time       = std::chrono::duration<float, std::milli>(p_impl->tick_start - p_impl->start).count();\n\tp_impl->tick_end   = std::chrono::high_resolution_clock::now();\n\n\tp_impl->delta_time_smoothed = p_impl->delta_time_smoothed * (1.f - 1.f / p_impl->accumulate) + p_impl->delta_time / p_impl->accumulate;\n\n\tif (p_impl->accumlate_time < p_impl->duration)\n\t{\n\t\tp_impl->accumlate_time += p_impl->delta_time;\n\t\tp_impl->frame_count++;\n\t}\n\telse\n\t{\n\t\tp_impl->frame_rate            = static_cast<float>(p_impl->frame_count) / (p_impl->accumlate_time / 1000.f);\n\t\tp_impl->accumlate_time = 0.f;\n\t\tp_impl->frame_count    = 0;\n\t}\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Private/Variant.cpp",
    "content": "#include \"Variant.hpp\"\n\n#include <any>\n\nnamespace Ilum\n{\nVariant::~Variant()\n{\n\tif (m_data)\n\t{\n\t\tm_data.reset();\n\t\tm_size = 0;\n\t}\n}\n\nVariant::Variant(Variant &&other) noexcept :\n    m_data(std::move(other.m_data)),\n    m_size(other.m_size)\n{\n\tother.m_data = nullptr;\n}\n\nVariant::Variant(const Variant &other) :\n    m_size(other.m_size), m_data(other.m_data)\n{\n}\n\nVariant &Variant::operator=(Variant &&other) noexcept\n{\n\tm_data = std::move(other.m_data);\n\tm_size = other.m_size;\n\n\tother.m_data = nullptr;\n\n\treturn *this;\n}\n\nVariant &Variant::operator=(const Variant &other)\n{\n\tm_data = other.m_data;\n\tm_size = other.m_size;\n\n\treturn *this;\n}\n\nbool Variant::Empty() const\n{\n\treturn m_data == nullptr;\n}\n\nvoid Variant::Set(const void *data, size_t size)\n{\n\tif (m_size < size)\n\t{\n\t\tm_data = std::shared_ptr<void>(malloc(size));\n\t\tm_size = size;\n\t}\n\n\tif (m_data)\n\t{\n\t\tstd::memcpy(m_data.get(), data, size);\n\t}\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Private/Window.cpp",
    "content": "#include \"Window.hpp\"\n#include \"Path.hpp\"\n\n#include <GLFW/glfw3.h>\n\n#ifdef _WIN32\n#\tdefine GLFW_EXPOSE_NATIVE_WIN32\n#endif        // WIN32\n#include <GLFW/glfw3native.h>\n\n#define STB_IMAGE_IMPLEMENTATION\n#include <stb_image.h>\n\nnamespace Ilum\n{\nWindow::Window(const std::string &title, const std::string &icon, uint32_t width, uint32_t height) :\n    m_width(width), m_height(height), m_title(title)\n{\n\tif (!glfwInit())\n\t{\n\t\treturn;\n\t}\n\n\tif (width == 0 || height == 0)\n\t{\n\t\tauto *video_mode = glfwGetVideoMode(glfwGetPrimaryMonitor());\n\n\t\tm_width  = static_cast<uint32_t>(video_mode->width * 3 / 4);\n\t\tm_height = static_cast<uint32_t>(video_mode->height * 3 / 4);\n\t}\n\n\tglfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);\n\tm_handle = glfwCreateWindow(m_width, m_height, title.c_str(), NULL, NULL);\n\tif (!m_handle)\n\t{\n\t\tglfwTerminate();\n\t\treturn;\n\t}\n\n\tif (Path::GetInstance().IsFile(icon))\n\t{\n\t\tGLFWimage window_icon = {};\n\t\twindow_icon.pixels    = stbi_load(icon.data(), &window_icon.width, &window_icon.height, 0, 4);\n\t\tglfwSetWindowIcon(m_handle, 1, &window_icon);\n\t\tstbi_image_free(window_icon.pixels);\n\t}\n\n\tglfwSetWindowUserPointer(m_handle, this);\n\n\tglfwSetKeyCallback(m_handle, [](GLFWwindow *window, int32_t key, int32_t scancode, int32_t action, int32_t mods) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnKeyFunc.Invoke(key, scancode, action, mods);\n\t});\n\n\tglfwSetCharCallback(m_handle, [](GLFWwindow *window, uint32_t codepoint) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnCharFunc.Invoke(codepoint);\n\t});\n\n\tglfwSetCharModsCallback(m_handle, [](GLFWwindow *window, uint32_t codepoint, int32_t mods) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnCharModsFunc.Invoke(codepoint, mods);\n\t});\n\n\tglfwSetMouseButtonCallback(m_handle, [](GLFWwindow *window, int32_t button, int32_t action, int32_t mods) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnMouseButtonFunc.Invoke(button, action, mods);\n\t});\n\n\tglfwSetCursorPosCallback(m_handle, [](GLFWwindow *window, double xpos, double ypos) {\n\t\tWindow *handle        = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->m_pos_delta_x = static_cast<float>(xpos) - handle->m_pos_last_x;\n\t\thandle->m_pos_delta_y = static_cast<float>(ypos) - handle->m_pos_last_y;\n\t\thandle->OnCursorPosFunc.Invoke(xpos, ypos);\n\t\thandle->m_pos_last_x = static_cast<float>(xpos);\n\t\thandle->m_pos_last_y = static_cast<float>(ypos);\n\t});\n\n\tglfwSetCursorEnterCallback(m_handle, [](GLFWwindow *window, int32_t entered) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnCursorEnterFunc.Invoke(entered);\n\t});\n\n\tglfwSetScrollCallback(m_handle, [](GLFWwindow *window, double xoffset, double yoffset) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnScrollFunc.Invoke(xoffset, yoffset);\n\t});\n\n\tglfwSetDropCallback(m_handle, [](GLFWwindow *window, int32_t count, const char **paths) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnDropFunc.Invoke(count, paths);\n\t});\n\n\tglfwSetWindowSizeCallback(m_handle, [](GLFWwindow *window, int32_t width, int32_t height) {\n\t\tWindow *handle = (Window *) glfwGetWindowUserPointer(window);\n\t\thandle->OnWindowSizeFunc.Invoke(width, height);\n\t\thandle->m_width  = static_cast<uint32_t>(width);\n\t\thandle->m_height = static_cast<uint32_t>(height);\n\t});\n\n\tglfwSetWindowCloseCallback(m_handle, [](GLFWwindow *window) {\n\t\tglfwSetWindowShouldClose(window, true);\n\t});\n\n\tglfwSetInputMode(m_handle, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);\n}\n\nWindow::~Window()\n{\n\tglfwDestroyWindow(m_handle);\n\tglfwTerminate();\n}\n\nbool Window::Tick()\n{\n\tif (!glfwWindowShouldClose(m_handle))\n\t{\n\t\tm_pos_delta_x = 0.f;\n\t\tm_pos_delta_y = 0.f;\n\t\tglfwPollEvents();\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool Window::IsKeyDown(int32_t key) const\n{\n\tif (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)\n\t{\n\t\treturn false;\n\t}\n\treturn glfwGetKey(m_handle, key) == GLFW_PRESS;\n}\n\nbool Window::IsMouseButtonDown(int32_t button) const\n{\n\tif (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)\n\t{\n\t\treturn false;\n\t}\n\n\treturn glfwGetMouseButton(m_handle, button) == GLFW_PRESS;\n}\n\nvoid Window::SetTitle(const std::string &title)\n{\n\tglfwSetWindowTitle(m_handle, title.c_str());\n\tm_title = title;\n}\n\nGLFWwindow *Window::GetHandle() const\n{\n\treturn m_handle;\n}\n\nvoid *Window::GetNativeHandle() const\n{\n\treturn glfwGetWin32Window(m_handle);\n}\n\nuint32_t Window::GetWidth() const\n{\n\treturn m_width;\n}\n\nuint32_t Window::GetHeight() const\n{\n\treturn m_height;\n}\n\nbool Window::IsKeyPressed(KeyCode keycode)\n{\n\tauto state = glfwGetKey(m_handle, static_cast<int32_t>(keycode));\n\treturn state == GLFW_PRESS || state == GLFW_REPEAT;\n}\n\nbool Window::IsMouseButtonPressed(MouseCode button)\n{\n\tauto state = glfwGetMouseButton(m_handle, static_cast<int32_t>(button));\n\treturn state == GLFW_PRESS;\n}\n\nglm::vec2 Window::GetMousePosition()\n{\n\tdouble xpos, ypos;\n\tglfwGetCursorPos(m_handle, &xpos, &ypos);\n\treturn glm::vec2{float(xpos), float(ypos)};\n}\n\nvoid Window::SetCursorPosition(const glm::vec2 &pos)\n{\n\tglfwSetCursorPos(m_handle, static_cast<double>(pos.x), static_cast<double>(pos.y));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/API.hpp",
    "content": "#pragma once\n\n#define EXPORT_API __declspec(dllexport)\n#define IMPORT_API __declspec(dllimport)\n"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Container.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\ntemplate <typename _Ty>\nclass RandomSet\n{\n  public:\n\tRandomSet()  = default;\n\t~RandomSet() = default;\n\n\tvoid insert(_Ty data)\n\t{\n\t\tassert(!has(data));\n\t\tm_lookup.emplace(data, m_data.size());\n\t\tm_data.push_back(data);\n\t}\n\n\tvoid erase(_Ty data)\n\t{\n\t\tauto target = m_lookup.find(data);\n\t\tassert(target != m_lookup.end());\n\t\tauto idx = target->second;\n\t\tif (idx != m_data.size() - 1)\n\t\t{\n\t\t\tm_lookup[m_data.back()] = idx;\n\t\t\tm_data[idx]             = m_data.back();\n\t\t}\n\t\tm_data.pop_back();\n\t\tm_lookup.erase(target);\n\t}\n\n\tauto begin() noexcept\n\t{\n\t\treturn m_data.begin();\n\t}\n\n\tauto begin() const noexcept\n\t{\n\t\treturn m_data.begin();\n\t}\n\n\tauto end() noexcept\n\t{\n\t\treturn m_data.end();\n\t}\n\n\tauto end() const noexcept\n\t{\n\t\treturn m_data.end();\n\t}\n\n\t_Ty operator[](size_t idx) const\n\t{\n\t\treturn m_data[idx];\n\t}\n\n\t_Ty &operator[](size_t idx)\n\t{\n\t\treturn m_data[idx];\n\t}\n\n\t_Ty at(size_t idx)\n\t{\n\t\treturn m_data.at(idx);\n\t}\n\n\tsize_t size() const noexcept\n\t{\n\t\treturn m_data.size();\n\t}\n\n\tvoid reserve(size_t n)\n\t{\n\t\tm_data.reserve(n);\n\t\tm_lookup.reserve(n);\n\t}\n\n\tvoid clear() noexcept\n\t{\n\t\tm_data.clear();\n\t\tm_lookup.clear();\n\t}\n\n\tconst std::vector<_Ty> &vec() const noexcept\n\t{\n\t\treturn m_data;\n\t}\n\n\tstd::vector<_Ty> &vec() noexcept\n\t{\n\t\treturn m_data;\n\t}\n\n\tsize_t idx(_Ty data) const\n\t{\n\t\treturn m_lookup.at(data);\n\t}\n\n\tbool has(_Ty data) const\n\t{\n\t\treturn m_lookup.find(data) != m_lookup.end();\n\t}\n\n\tbool empty() const noexcept\n\t{\n\t\treturn m_data.empty();\n\t}\n\n  private:\n\tstd::unordered_map<_Ty, std::size_t> m_lookup;\n\tstd::vector<_Ty>                     m_data;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Core.hpp",
    "content": "#pragma once\n\n#include \"Container.hpp\"\n#include \"Hash.hpp\"\n#include \"Log.hpp\"\n#include \"Path.hpp\"\n#include \"Plugin.hpp\"\n#include \"Precompile.hpp\"\n#include \"Variant.hpp\"\n\n#include <cereal/types/array.hpp>\n#include <cereal/types/map.hpp>\n#include <cereal/types/set.hpp>\n#include <cereal/types/string.hpp>\n#include <cereal/types/unordered_map.hpp>\n#include <cereal/types/unordered_set.hpp>\n#include <cereal/types/vector.hpp>\n\n#include <glm/glm.hpp>\n#include <glm/gtc/matrix_transform.hpp>\n#include <glm/gtc/type_ptr.hpp>\n#include <glm/gtx/matrix_decompose.hpp>\n#include <glm/gtx/quaternion.hpp>\n\n#define SERIALIZER_TYPE_JSON 0\n#define SERIALIZER_TYPE_BINARY 1\n#define SERIALIZER_TYPE_XML 2\n#define SERIALIZER_TYPE SERIALIZER_TYPE_BINARY\n\n#define LOG_HELPER(LOG_LEVEL, ...) \\\n\tIlum::LogSystem::GetInstance().Log(LOG_LEVEL, \"[\" + std::string(__FUNCTION__) + \"] \" + __VA_ARGS__);\n\n// Logging\n#define LOG_DEBUG(...) LOG_HELPER(Ilum::LogSystem::LogLevel::Debug, __VA_ARGS__);\n#define LOG_INFO(...) LOG_HELPER(Ilum::LogSystem::LogLevel::Info, __VA_ARGS__);\n#define LOG_WARN(...) LOG_HELPER(Ilum::LogSystem::LogLevel::Warn, __VA_ARGS__);\n#define LOG_ERROR(...) LOG_HELPER(Ilum::LogSystem::LogLevel::Error, __VA_ARGS__);\n#define LOG_FATAL(...) LOG_HELPER(Ilum::LogSystem::LogLevel::Fatal, __VA_ARGS__);\n\n#if SERIALIZER_TYPE == SERIALIZER_TYPE_JSON\n#\tinclude <cereal/archives/json.hpp>\nusing InputArchive  = cereal::JSONInputArchive;\nusing OutputArchive = cereal::JSONOutputArchive;\n#elif SERIALIZER_TYPE == SERIALIZER_TYPE_BINARY\n#\tinclude <cereal/archives/binary.hpp>\nusing InputArchive  = cereal::BinaryInputArchive;\nusing OutputArchive = cereal::BinaryOutputArchive;\n#elif SERIALIZER_TYPE == SERIALIZER_TYPE_XML\n#\tinclude <cereal/archives/xml.hpp>\nusing InputArchive  = cereal::XMLInputArchive;\nusing OutputArchive = cereal::XMLOutputArchive;\n#else\n#\terror Must specify a type of serializer!\n#endif\n\n#define SERIALIZE(FILE, DATA, ...)                \\\n\t{                                             \\\n\t\tstd::ofstream os(FILE, std::ios::binary); \\\n\t\tOutputArchive archive(os);                \\\n\t\tarchive(DATA, __VA_ARGS__);               \\\n\t}\n\n#define DESERIALIZE(FILE, DATA, ...)              \\\n\t{                                             \\\n\t\tstd::ifstream is(FILE, std::ios::binary); \\\n\t\tInputArchive  archive(is);                \\\n\t\tarchive(DATA, __VA_ARGS__);               \\\n\t}\n\n#if defined(__REFLECTION_PARSER__)\n#\tdefine META(...) __attribute__((annotate(#__VA_ARGS__)))\n#\tdefine CLASS(class_name, ...) class __attribute__((annotate(#__VA_ARGS__))) class_name\n#\tdefine STRUCT(struct_name, ...) struct __attribute__((annotate(#__VA_ARGS__))) struct_name\n#\tdefine ENUM(enum_name, ...) enum class __attribute__((annotate(#__VA_ARGS__))) enum_name\n#else\n#\tdefine META(...)\n#\tdefine CLASS(class_name, ...) class class_name\n#\tdefine STRUCT(struct_name, ...) struct struct_name\n#\tdefine ENUM(enum_name, ...) enum class enum_name\n#endif        // __REFLECTION_PARSER__\n\n#define DEFINE_ENUMCLASS_OPERATION(EnumClass)                   \\\n\tinline EnumClass operator|(EnumClass lhs, EnumClass rhs)    \\\n\t{                                                           \\\n\t\treturn (EnumClass) ((uint64_t) lhs | (uint64_t) rhs);   \\\n\t}                                                           \\\n\tinline bool operator&(EnumClass lhs, EnumClass rhs)         \\\n\t{                                                           \\\n\t\treturn (bool) ((uint64_t) lhs & (uint64_t) rhs);        \\\n\t}                                                           \\\n\tinline EnumClass &operator|=(EnumClass &lhs, EnumClass rhs) \\\n\t{                                                           \\\n\t\treturn lhs = lhs | rhs;                                 \\\n\t}\n\nnamespace glm\n{\ntemplate <class Archive>\nvoid serialize(Archive &archive, glm::vec2 &m)\n{\n\tarchive(m.x, m.y);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive &archive, glm::vec3 &m)\n{\n\tarchive(m.x, m.y, m.z);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive &archive, glm::vec4 &m)\n{\n\tarchive(m.x, m.y, m.z, m.w);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive &archive, glm::mat4 &m)\n{\n\tarchive(\n\t    m[0][0], m[0][1], m[0][2], m[0][3],\n\t    m[1][0], m[1][1], m[1][2], m[1][3],\n\t    m[2][0], m[2][1], m[2][2], m[2][3],\n\t    m[3][0], m[3][1], m[3][2], m[3][3]);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive &archive, glm::quat &m)\n{\n\tarchive(m.x, m.y, m.z, m.w);\n}\n}        // namespace glm\n"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Delegates.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nusing DelegateHandle = uint32_t;\n\ntemplate <typename... Args>\nclass  MulticastDelegate\n{\n  public:\n\tusing Delegate = std::function<void(Args...)>;\n\n\tDelegateHandle Subscribe(Delegate &&delegate)\n\t{\n\t\twhile (IsLock())\n\t\t{\n\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds(16));\n\t\t}\n\n\t\tDelegateHandle id = m_avaliable_id++;\n\t\tm_subscribers.emplace(id, std::move(delegate));\n\t\treturn id;\n\t}\n\n\tDelegateHandle operator+=(Delegate &&delegate)\n\t{\n\t\treturn Subscribe(std::move(delegate));\n\t}\n\n\tbool UnSubscribe(const DelegateHandle &handle)\n\t{\n\t\twhile (IsLock())\n\t\t{\n\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds(16));\n\t\t}\n\n\t\tif (m_subscribers.find(handle) != m_subscribers.end())\n\t\t{\n\t\t\tm_subscribers.erase(handle);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tbool operator-=(const DelegateHandle &handle)\n\t{\n\t\treturn UnSubscribe(handle);\n\t}\n\n\tvoid Clear()\n\t{\n\t\twhile (IsLock())\n\t\t{\n\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds(16));\n\t\t}\n\n\t\tm_subscribers.clear();\n\t}\n\n\tvoid Invoke(Args... args)\n\t{\n\t\tLock();\n\t\tfor (auto const &[key, val] : m_subscribers)\n\t\t{\n\t\t\tval(args...);\n\t\t}\n\t\tUnlock();\n\t}\n\n  private:\n\tvoid Lock()\n\t{\n\t\tm_lock++;\n\t}\n\n\tvoid Unlock()\n\t{\n\t\tassert(m_lock > 0);\n\t\tm_lock--;\n\t}\n\n\tbool IsLock()\n\t{\n\t\treturn m_lock > 0;\n\t}\n\n  private:\n\tstd::unordered_map<DelegateHandle, Delegate> m_subscribers;\n\n\tDelegateHandle m_avaliable_id = 0;\n\n\tint32_t m_lock = 0;\n};\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Hash.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\ntemplate <class T>\ninline void HashCombine(size_t &seed, const T &v)\n{\n\tstd::hash<T> hasher;\n\tseed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n}\n\ntemplate <typename T>\ninline void HashCombine(size_t &seed, const std::vector<T> &v)\n{\n\tfor (auto &data : v)\n\t{\n\t\tHashCombine(seed, data);\n\t}\n}\n\ntemplate <class T1, class... T2>\ninline void HashCombine(size_t &seed, const T1 &v1, const T2 &...v2)\n{\n\tHashCombine(seed, v1);\n\tHashCombine(seed, v2...);\n}\n\ntemplate <typename T>\ninline size_t Hash(const T &v)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, v);\n\treturn hash;\n}\n\ntemplate <typename T1, typename... T2>\ninline size_t Hash(const T1 &v1, const T2 &...v2)\n{\n\tsize_t hash = 0;\n\tHashCombine(hash, v1, v2...);\n\treturn hash;\n}\n\nstruct PairHash\n{\n\ttemplate <class T1, class T2>\n\tstd::size_t operator()(const std::pair<T1, T2> &p) const\n\t{\n\t\treturn Hash(p.first, p.second);\n\t}\n};\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Input.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\n/*KeyCode*/\ntypedef enum class KeyCode : uint16_t\n{\n\t// From glfw3.h\n\tSpace      = 32,\n\tApostrophe = 39, /* ' */\n\tComma      = 44, /* , */\n\tMinus      = 45, /* - */\n\tPeriod     = 46, /* . */\n\tSlash      = 47, /* / */\n\n\tD0 = 48, /* 0 */\n\tD1 = 49, /* 1 */\n\tD2 = 50, /* 2 */\n\tD3 = 51, /* 3 */\n\tD4 = 52, /* 4 */\n\tD5 = 53, /* 5 */\n\tD6 = 54, /* 6 */\n\tD7 = 55, /* 7 */\n\tD8 = 56, /* 8 */\n\tD9 = 57, /* 9 */\n\n\tSemicolon = 59, /* ; */\n\tEqual     = 61, /* = */\n\n\tA = 65,\n\tB = 66,\n\tC = 67,\n\tD = 68,\n\tE = 69,\n\tF = 70,\n\tG = 71,\n\tH = 72,\n\tI = 73,\n\tJ = 74,\n\tK = 75,\n\tL = 76,\n\tM = 77,\n\tN = 78,\n\tO = 79,\n\tP = 80,\n\tQ = 81,\n\tR = 82,\n\tS = 83,\n\tT = 84,\n\tU = 85,\n\tV = 86,\n\tW = 87,\n\tX = 88,\n\tY = 89,\n\tZ = 90,\n\n\tLeftBracket  = 91, /* [ */\n\tBackslash    = 92, /* \\ */\n\tRightBracket = 93, /* ] */\n\tGraveAccent  = 96, /* ` */\n\n\tWorld1 = 161, /* non-US #1 */\n\tWorld2 = 162, /* non-US #2 */\n\n\t/* Function keys */\n\tEscape      = 256,\n\tEnter       = 257,\n\tTab         = 258,\n\tBackspace   = 259,\n\tInsert      = 260,\n\tDelete      = 261,\n\tRight       = 262,\n\tLeft        = 263,\n\tDown        = 264,\n\tUp          = 265,\n\tPageUp      = 266,\n\tPageDown    = 267,\n\tHome        = 268,\n\tEnd         = 269,\n\tCapsLock    = 280,\n\tScrollLock  = 281,\n\tNumLock     = 282,\n\tPrintScreen = 283,\n\tPause       = 284,\n\tF1          = 290,\n\tF2          = 291,\n\tF3          = 292,\n\tF4          = 293,\n\tF5          = 294,\n\tF6          = 295,\n\tF7          = 296,\n\tF8          = 297,\n\tF9          = 298,\n\tF10         = 299,\n\tF11         = 300,\n\tF12         = 301,\n\tF13         = 302,\n\tF14         = 303,\n\tF15         = 304,\n\tF16         = 305,\n\tF17         = 306,\n\tF18         = 307,\n\tF19         = 308,\n\tF20         = 309,\n\tF21         = 310,\n\tF22         = 311,\n\tF23         = 312,\n\tF24         = 313,\n\tF25         = 314,\n\n\t/* Keypad */\n\tKP0        = 320,\n\tKP1        = 321,\n\tKP2        = 322,\n\tKP3        = 323,\n\tKP4        = 324,\n\tKP5        = 325,\n\tKP6        = 326,\n\tKP7        = 327,\n\tKP8        = 328,\n\tKP9        = 329,\n\tKPDecimal  = 330,\n\tKPDivide   = 331,\n\tKPMultiply = 332,\n\tKPSubtract = 333,\n\tKPAdd      = 334,\n\tKPEnter    = 335,\n\tKPEqual    = 336,\n\n\tLeftShift    = 340,\n\tLeftControl  = 341,\n\tLeftAlt      = 342,\n\tLeftSuper    = 343,\n\tRightShift   = 344,\n\tRightControl = 345,\n\tRightAlt     = 346,\n\tRightSuper   = 347,\n\tMenu         = 348\n} Key;\n\ninline std::ostream &operator<<(std::ostream &os, KeyCode keyCode)\n{\n\tos << static_cast<int32_t>(keyCode);\n\treturn os;\n}\n\n// From glfw3.h\n#define KEY_SPACE ::Key::Space\n#define KEY_APOSTROPHE ::Key::Apostrophe /* ' */\n#define KEY_COMMA ::Key::Comma           /* , */\n#define KEY_MINUS ::Key::Minus           /* - */\n#define KEY_PERIOD ::Key::Period         /* . */\n#define KEY_SLASH ::Key::Slash           /* / */\n#define KEY_0 ::Key::D0\n#define KEY_1 ::Key::D1\n#define KEY_2 ::Key::D2\n#define KEY_3 ::Key::D3\n#define KEY_4 ::Key::D4\n#define KEY_5 ::Key::D5\n#define KEY_6 ::Key::D6\n#define KEY_7 ::Key::D7\n#define KEY_8 ::Key::D8\n#define KEY_9 ::Key::D9\n#define KEY_SEMICOLON ::Key::Semicolon /* ; */\n#define KEY_EQUAL ::Key::Equal         /* = */\n#define KEY_A ::Key::A\n#define KEY_B ::Key::B\n#define KEY_C ::Key::C\n#define KEY_D ::Key::D\n#define KEY_E ::Key::E\n#define KEY_F ::Key::F\n#define KEY_G ::Key::G\n#define KEY_H ::Key::H\n#define KEY_I ::Key::I\n#define KEY_J ::Key::J\n#define KEY_K ::Key::K\n#define KEY_L ::Key::L\n#define KEY_M ::Key::M\n#define KEY_N ::Key::N\n#define KEY_O ::Key::O\n#define KEY_P ::Key::P\n#define KEY_Q ::Key::Q\n#define KEY_R ::Key::R\n#define KEY_S ::Key::S\n#define KEY_T ::Key::T\n#define KEY_U ::Key::U\n#define KEY_V ::Key::V\n#define KEY_W ::Key::W\n#define KEY_X ::Key::X\n#define KEY_Y ::Key::Y\n#define KEY_Z ::Key::Z\n#define KEY_LEFT_BRACKET ::Key::LeftBracket   /* [ */\n#define KEY_BACKSLASH ::Key::Backslash        /* \\ */\n#define KEY_RIGHT_BRACKET ::Key::RightBracket /* ] */\n#define KEY_GRAVE_ACCENT ::Key::GraveAccent   /* ` */\n#define KEY_WORLD_1 ::Key::World1             /* non-US #1 */\n#define KEY_WORLD_2 ::Key::World2             /* non-US #2 */\n\n/* Function keys */\n#define KEY_ESCAPE ::Key::Escape\n#define KEY_ENTER ::Key::Enter\n#define KEY_TAB ::Key::Tab\n#define KEY_BACKSPACE ::Key::Backspace\n#define KEY_INSERT ::Key::Insert\n#define KEY_DELETE ::Key::Delete\n#define KEY_RIGHT ::Key::Right\n#define KEY_LEFT ::Key::Left\n#define KEY_DOWN ::Key::Down\n#define KEY_UP ::Key::Up\n#define KEY_PAGE_UP ::Key::PageUp\n#define KEY_PAGE_DOWN ::Key::PageDown\n#define KEY_HOME ::Key::Home\n#define KEY_END ::Key::End\n#define KEY_CAPS_LOCK ::Key::CapsLock\n#define KEY_SCROLL_LOCK ::Key::ScrollLock\n#define KEY_NUM_LOCK ::Key::NumLock\n#define KEY_PRINT_SCREEN ::Key::PrintScreen\n#define KEY_PAUSE ::Key::Pause\n#define KEY_F1 ::Key::F1\n#define KEY_F2 ::Key::F2\n#define KEY_F3 ::Key::F3\n#define KEY_F4 ::Key::F4\n#define KEY_F5 ::Key::F5\n#define KEY_F6 ::Key::F6\n#define KEY_F7 ::Key::F7\n#define KEY_F8 ::Key::F8\n#define KEY_F9 ::Key::F9\n#define KEY_F10 ::Key::F10\n#define KEY_F11 ::Key::F11\n#define KEY_F12 ::Key::F12\n#define KEY_F13 ::Key::F13\n#define KEY_F14 ::Key::F14\n#define KEY_F15 ::Key::F15\n#define KEY_F16 ::Key::F16\n#define KEY_F17 ::Key::F17\n#define KEY_F18 ::Key::F18\n#define KEY_F19 ::Key::F19\n#define KEY_F20 ::Key::F20\n#define KEY_F21 ::Key::F21\n#define KEY_F22 ::Key::F22\n#define KEY_F23 ::Key::F23\n#define KEY_F24 ::Key::F24\n#define KEY_F25 ::Key::F25\n\n/* Keypad */\n#define KEY_KP_0 ::Key::KP0\n#define KEY_KP_1 ::Key::KP1\n#define KEY_KP_2 ::Key::KP2\n#define KEY_KP_3 ::Key::KP3\n#define KEY_KP_4 ::Key::KP4\n#define KEY_KP_5 ::Key::KP5\n#define KEY_KP_6 ::Key::KP6\n#define KEY_KP_7 ::Key::KP7\n#define KEY_KP_8 ::Key::KP8\n#define KEY_KP_9 ::Key::KP9\n#define KEY_KP_DECIMAL ::Key::KPDecimal\n#define KEY_KP_DIVIDE ::Key::KPDivide\n#define KEY_KP_MULTIPLY ::Key::KPMultiply\n#define KEY_KP_SUBTRACT ::Key::KPSubtract\n#define KEY_KP_ADD ::Key::KPAdd\n#define KEY_KP_ENTER ::Key::KPEnter\n#define KEY_KP_EQUAL ::Key::KPEqual\n\n#define KEY_LEFT_SHIFT ::Key::LeftShift\n#define KEY_LEFT_CONTROL ::Key::LeftControl\n#define KEY_LEFT_ALT ::Key::LeftAlt\n#define KEY_LEFT_SUPER ::Key::LeftSuper\n#define KEY_RIGHT_SHIFT ::Key::RightShift\n#define KEY_RIGHT_CONTROL ::Key::RightControl\n#define KEY_RIGHT_ALT ::Key::RightAlt\n#define KEY_RIGHT_SUPER ::Key::RightSuper\n#define KEY_MENU ::Key::Menu\n\n////////////////////////////////////////////////////////////////////////////\n\n/*Mouse Code*/\ntypedef enum class MouseCode : uint16_t\n{\n\t// From glfw3.h\n\tButton0 = 0,\n\tButton1 = 1,\n\tButton2 = 2,\n\tButton3 = 3,\n\tButton4 = 4,\n\tButton5 = 5,\n\tButton6 = 6,\n\tButton7 = 7,\n\n\tButtonLast   = Button7,\n\tButtonLeft   = Button0,\n\tButtonRight  = Button1,\n\tButtonMiddle = Button2\n} Mouse;\n\ninline std::ostream &operator<<(std::ostream &os, MouseCode mouseCode)\n{\n\tos << static_cast<int32_t>(mouseCode);\n\treturn os;\n}\n\n#define MOUSE_BUTTON_0 ::Mouse::Button0\n#define MOUSE_BUTTON_1 ::Mouse::Button1\n#define MOUSE_BUTTON_2 ::Mouse::Button2\n#define MOUSE_BUTTON_3 ::Mouse::Button3\n#define MOUSE_BUTTON_4 ::Mouse::Button4\n#define MOUSE_BUTTON_5 ::Mouse::Button5\n#define MOUSE_BUTTON_6 ::Mouse::Button6\n#define MOUSE_BUTTON_7 ::Mouse::Button7\n#define MOUSE_BUTTON_LAST ::Mouse::ButtonLast\n#define MOUSE_BUTTON_LEFT ::Mouse::ButtonLeft\n#define MOUSE_BUTTON_RIGHT ::Mouse::ButtonRight\n#define MOUSE_BUTTON_MIDDLE ::Mouse::ButtonMiddle\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/JobSystem.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nclass SpinLock\n{\n  public:\n\tSpinLock();\n\t~SpinLock() = default;\n\n\tvoid Lock();\n\tvoid Unlock();\n\n  private:\n\tstd::atomic_flag m_flag;\n};\n\ntemplate <typename T, size_t capacity>\nclass RingBuffer\n{\n  public:\n\tRingBuffer()  = default;\n\t~RingBuffer() = default;\n\n\tRingBuffer(const RingBuffer &)            = delete;\n\tRingBuffer &operator=(const RingBuffer &) = delete;\n\tRingBuffer(RingBuffer &&)                 = delete;\n\tRingBuffer &operator=(RingBuffer &&)      = delete;\n\n\tvoid Push(const T &data)\n\t{\n\t\tsize_t current_tail             = m_run_tail.fetch_add(1, std::memory_order_relaxed);\n\t\tm_data[current_tail % capacity] = data;\n\t\tm_tail.fetch_add(1, std::memory_order_relaxed);\n\t}\n\n\tbool TryPop(T &data)\n\t{\n\t\tsize_t current_head = 0;\n\n\t\t{\n\t\t\tm_lock.Lock();\n\t\t\tif (m_tail <= m_head)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcurrent_head = m_head++;\n\t\t\tm_lock.Unlock();\n\t\t}\n\n\t\tdata = m_data[current_head % capacity];\n\t\treturn true;\n\t}\n\n\tbool Empty() const\n\t{\n\t\treturn m_tail <= m_head;\n\t}\n\n  private:\n\tT                   m_data[capacity] = {};\n\tsize_t              m_head           = 0;\n\tstd::atomic<size_t> m_tail           = 0;\n\tstd::atomic<size_t> m_run_tail       = 0;\n\tSpinLock            m_lock;\n};\n\nclass ThreadPool\n{\n  public:\n\tThreadPool(uint32_t max_threads_num);\n\t~ThreadPool();\n\n\tThreadPool(const ThreadPool &)            = delete;\n\tThreadPool &operator=(const ThreadPool &) = delete;\n\tThreadPool(ThreadPool &&)                 = delete;\n\tThreadPool &operator=(ThreadPool &&)      = delete;\n\n\tsize_t GetThreadCount() const;\n\n\ttemplate <typename Task, typename... Args>\n\tinline auto AddTask(Task &&task, Args &&...args)\n\t    -> std::future<decltype(task(args...))>\n\t{\n\t\tusing return_type = decltype(task(args...));\n\n\t\tauto pack = std::make_shared<std::packaged_task<return_type()>>(\n\t\t    std::bind(std::forward<Task>(task), std::forward<Args>(args)...));\n\t\tm_task_queue.Push([pack]() { (*pack)(); });\n\n\t\t{\n\t\t\tstd::unique_lock<std::mutex> lock(m_mutex);\n\t\t\tm_condition.notify_one();\n\t\t}\n\n\t\treturn pack->get_future();\n\t}\n\n\tvoid WaitAll();\n\n  private:\n\tRingBuffer<std::function<void()>, 1024>           m_task_queue;\n\tstd::unordered_map<std::thread::id, const char *> m_thread_names;\n\n\tstd::vector<std::thread> m_workers;\n\tstd::mutex               m_mutex;\n\tstd::atomic<bool>        m_stop = false;\n\tstd::condition_variable  m_condition;\n};\n\nclass JobNode\n{\n\tfriend class JobSystem;\n\tfriend class JobGraph;\n\n  public:\n\t// Job Graph won't provide return value\n\texplicit JobNode(std::function<void()> &&task);\n\n\tJobNode() = default;\n\n\t~JobNode() = default;\n\n\tvirtual std::type_index GetType();\n\n\t// A.percede(B) => B depend on A\n\tvoid Percede(JobNode *node);\n\n\t// A.succeed(B) => A depend on B\n\tvoid Succeed(JobNode *node);\n\n\tvirtual bool Compile();\n\n\tvirtual void Run();\n\n  protected:\n\tstd::vector<JobNode *> m_successors;\n\tstd::vector<JobNode *> m_dependents;\n\tstd::atomic<uint32_t>  m_unfinish_dependents = 0;\n\n  private:\n\tstd::function<void()> m_task;\n};\n\nclass JobGraph : public JobNode\n{\n\tfriend class JobSystem;\n\n  public:\n\texplicit JobGraph() = default;\n\n\t~JobGraph() = default;\n\n\tvirtual std::type_index GetType() override;\n\n\tJobGraph &AddNode(JobNode *node);\n\n\t// Validation and topology sorting\n\tvirtual bool Compile() override;\n\n\t// Single thread job graph execute\n\t// You must compile job graph before it runs\n\tvirtual void Run() override;\n\n  private:\n\tstd::vector<JobNode *> m_nodes;\n};\n\nclass JobSystem;\n\nclass JobHandle\n{\n\tfriend class JobSystem;\n\t// The number of subjob current job is dealing\n\tstd::atomic<uint32_t> m_counter = 0;\n};\n\nclass JobSystem\n{\n  public:\n\tJobSystem();\n\n\t~JobSystem();\n\n\tstatic JobSystem &GetInstance();\n\n\tsize_t GetThreadCount();\n\n\t// You must compile job graph before it executed\n\tvoid Execute(JobHandle &handle, JobGraph &graph);\n\tvoid Execute(JobHandle &handle, JobNode &node);\n\n\t// Async execute, can be used in resource loading\n\ttemplate <typename Task, typename... Args>\n\tinline auto ExecuteAsync(Task &&task, Args &&...args)\n\t    -> std::future<decltype(task(args...))>\n\t{\n\t\treturn m_thread_pool->AddTask([task, args...]() {\n\t\t\treturn task(std::forward<Args>(args)...);\n\t\t});\n\t}\n\n\ttemplate <typename Task>\n\tinline auto ExecuteAsync(Task &&task)\n\t    -> std::future<decltype(task())>\n\t{\n\t\treturn m_thread_pool->AddTask([task]() {\n\t\t\treturn task();\n\t\t});\n\t}\n\n\t// Using dispatch method, task need group id as parameter\n\tvoid Dispatch(JobHandle &handle, uint32_t job_count, uint32_t group_size, const std::function<void(uint32_t)> &task);\n\tbool IsBusy(const JobHandle &handle);\n\tvoid Wait(const JobHandle &handle);\n\tvoid WaitAll();\n\n  private:\n\tstd::unique_ptr<ThreadPool> m_thread_pool = nullptr;\n};\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Log.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <spdlog/spdlog.h>\n\nnamespace Ilum\n{\nclass  LogSystem final\n{\n  public:\n\tenum class LogLevel : uint8_t\n\t{\n\t\tDebug,\n\t\tInfo,\n\t\tWarn,\n\t\tError,\n\t\tFatal\n\t};\n\n  public:\n\tLogSystem();\n\n\t~LogSystem();\n\n\tstatic LogSystem &GetInstance();\n\n\ttemplate <typename... Args>\n\tvoid Log(LogLevel level, Args &&...args)\n\t{\n\t\tswitch (level)\n\t\t{\n\t\t\tcase Ilum::LogSystem::LogLevel::Debug:\n\t\t\t\tm_logger->debug(std::forward<Args>(args)...);\n\t\t\t\tbreak;\n\t\t\tcase Ilum::LogSystem::LogLevel::Info:\n\t\t\t\tm_logger->info(std::forward<Args>(args)...);\n\t\t\t\tbreak;\n\t\t\tcase Ilum::LogSystem::LogLevel::Warn:\n\t\t\t\tm_logger->warn(std::forward<Args>(args)...);\n\t\t\t\tbreak;\n\t\t\tcase Ilum::LogSystem::LogLevel::Error:\n\t\t\t\tm_logger->error(std::forward<Args>(args)...);\n\t\t\t\tbreak;\n\t\t\tcase Ilum::LogSystem::LogLevel::Fatal:\n\t\t\t\tm_logger->critical(std::forward<Args>(args)...);\n\t\t\t\tthrow std::runtime_error(fmt::format(std::forward<Args>(args)...));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n  private:\n\tstd::shared_ptr<spdlog::logger> m_logger;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/PRECOMPILE.HPP",
    "content": "#pragma once\n\n#include <algorithm>\n#include <array>\n#include <atomic>\n#include <cassert>\n#include <chrono>\n#include <filesystem>\n#include <fstream>\n#include <functional>\n#include <future>\n#include <iostream>\n#include <limits>\n#include <map>\n#include <memory>\n#include <memory_resource>\n#include <optional>\n#include <queue>\n#include <regex>\n#include <set>\n#include <sstream>\n#include <string>\n#include <thread>\n#include <typeindex>\n#include <unordered_map>\n#include <unordered_set>\n#include <variant>\n#include <vector>\n\n#include \"API.hpp\"\n"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Path.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nclass  Path\n{\n  public:\n\tstatic Path &GetInstance();\n\n\tbool IsExist(const std::string &path);\n\tbool IsFile(const std::string &path);\n\tbool IsDirectory(const std::string &path);\n\tbool CreatePath(const std::string &path);\n\tbool DeletePath(const std::string &path);\n\tbool Copy(const std::string &src, const std::string &dst);\n\tvoid SetCurrent(const std::string &path);\n\n\tconst std::string GetCurrent(bool convert = true);\n\tconst std::string GetFileName(const std::string &path, bool has_extension = true);\n\tconst std::string GetFileDirectory(const std::string &path);\n\tconst std::string GetFileExtension(const std::string &path);\n\tconst std::string GetRelativePath(const std::string &path);\n\n\tbool Save(const std::string &path, const std::vector<uint8_t> &data, bool binary = false);\n\tbool Read(const std::string &path, std::vector<uint8_t> &data, bool binary = false, uint32_t begin = 0, uint32_t end = 0);\n\n\tstd::string Toupper(const std::string &str);\n\tstd::string Replace(const std::string &str, char from, char to);\n\tstd::string ValidFileName(const std::string &str);\n\n\tstd::vector<std::string> Split(const std::string &str, char delim);\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Plugin.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <string>\n\n#ifdef _WIN64\n#\tinclude <Windows.h>\n#\tinclude <libloaderapi.h>\n#else\n#\terror(\"Windows only for now\")\n#endif\n\nnamespace Ilum\n{\nclass  PluginManager\n{\n  public:\n\tPluginManager();\n\n\t~PluginManager();\n\n\tstatic PluginManager &GetInstance();\n\n\ttemplate <typename _Ty = void, typename... Args>\n\t_Ty Call(const std::string &lib_path, const std::string &func_name, Args... args)\n\t{\n\t\ttypedef _Ty(CALLBACK * FUNC)(Args...);\n\n\t\tauto lib_handle = GetLibrary(lib_path);\n\n\t\tauto func = (FUNC) GetProcAddress(lib_handle, func_name.c_str());\n\n\t\tif (!func)\n\t\t{\n\t\t\tif constexpr (std::is_same_v<_Ty, void>)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn _Ty();\n\t\t\t}\n\t\t}\n\n\t\tif constexpr (std::is_same_v<_Ty, void>)\n\t\t{\n\t\t\tfunc(args...);\n\t\t\treturn;\n\t\t}\n\t\telse if constexpr (sizeof...(Args) == 0)\n\t\t{\n\t\t\treturn func();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn func(args...);\n\t\t}\n\t}\n\n  private:\n\tHMODULE GetLibrary(const std::string &lib_path);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Time.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nclass  Timer\n{\n  public:\n\tTimer();\n\n\t~Timer();\n\n\tstatic Timer &GetInstance();\n\n\tfloat TotalTime();\n\n\tfloat DeltaTime();\n\n\tfloat DeltaTimeSmoothed();\n\n\tfloat FrameRate();\n\n\tvoid  Tick();\n\n  private:\n\tstruct Impl;\n\tImpl *p_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Variant.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nclass  Variant\n{\n  public:\n\tVariant() = default;\n\n\t~Variant();\n\n\tVariant(Variant &&other) noexcept;\n\n\tVariant(const Variant &other);\n\n\ttemplate <typename _Ty>\n\tVariant(const _Ty& var)\n\t{\n\t\tSet(&var, sizeof(_Ty));\n\t}\n\n\tVariant &operator=(Variant &&other) noexcept;\n\n\tVariant &operator=(const Variant &other);\n\n\tbool Empty() const;\n\n\ttemplate <typename _Ty>\n\tvoid operator=(const _Ty &var)\n\t{\n\t\tSet(&var, sizeof(_Ty));\n\t}\n\n\ttemplate <typename _Ty>\n\t_Ty *Convert() const\n\t{\n\t\treturn std::static_pointer_cast<_Ty>(m_data).get();\n\t}\n\n\ttemplate <class Archive>\n\tvoid save(Archive &archive) const\n\t{\n\t\tstd::vector<uint8_t> data(m_size);\n\t\tstd::memcpy(data.data(), m_data.get(), m_size);\n\t\tarchive(data);\n\t}\n\n\ttemplate <class Archive>\n\tvoid load(Archive &archive)\n\t{\n\t\tstd::vector<uint8_t> data;\n\t\tarchive(data);\n\t\tSet(data.data(), data.size());\n\t}\n\n  private:\n\tvoid Set(const void *data, size_t size);\n\n  private:\n\tstd::shared_ptr<void> m_data = nullptr;\n\n\tsize_t m_size = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/Public/Core/Window.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n#include \"Delegates.hpp\"\n#include \"Input.hpp\"\n\nstruct GLFWwindow;\n\nnamespace Ilum\n{\nclass  Window\n{\n  public:\n\tWindow(const std::string &title, const std::string &icon, uint32_t width = 0, uint32_t height = 0);\n\n\t~Window();\n\n\tbool Tick();\n\n\tbool IsKeyDown(int32_t key) const;\n\n\tbool IsMouseButtonDown(int32_t button) const;\n\n\tvoid SetTitle(const std::string &title);\n\n\tGLFWwindow *GetHandle() const;\n\n\tvoid *GetNativeHandle() const;\n\n\tuint32_t GetWidth() const;\n\n\tuint32_t GetHeight() const;\n\n\tbool IsKeyPressed(KeyCode keycode);\n\n\tbool IsMouseButtonPressed(MouseCode button);\n\n\tglm::vec2 GetMousePosition();\n\n\tvoid SetCursorPosition(const glm::vec2 &pos);\n\n  public:\n\tMulticastDelegate<>                                   OnResetFunc;\n\tMulticastDelegate<int32_t, int32_t, int32_t, int32_t> OnKeyFunc;\n\tMulticastDelegate<uint32_t>                           OnCharFunc;\n\tMulticastDelegate<int32_t, uint32_t>                  OnCharModsFunc;\n\tMulticastDelegate<int32_t, int32_t, int32_t>          OnMouseButtonFunc;\n\tMulticastDelegate<double, double>                     OnCursorPosFunc;\n\tMulticastDelegate<int32_t>                            OnCursorEnterFunc;\n\tMulticastDelegate<double, double>                     OnScrollFunc;\n\tMulticastDelegate<int32_t, const char **>             OnDropFunc;\n\tMulticastDelegate<int32_t, int32_t>                   OnWindowSizeFunc;\n\tMulticastDelegate<>                                   OnWindowCloseFunc;\n\n  private:\n\tGLFWwindow *m_handle = nullptr;\n\n\tuint32_t    m_width;\n\tuint32_t    m_height;\n\tstd::string m_title;\n\tfloat       m_mouse_wheel_h = 0.0f;\n\tfloat       m_mouse_wheel   = 0.0f;\n\tfloat       m_pos_delta_x   = 0.f;\n\tfloat       m_pos_delta_y   = 0.f;\n\tfloat       m_pos_last_x    = 0.f;\n\tfloat       m_pos_last_y    = 0.f;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Core/xmake.lua",
    "content": ""
  },
  {
    "path": "Source/Runtime/Geometry/Private/AABB.cpp",
    "content": "#include \"AABB.hpp\"\n\nnamespace Ilum\n{\nAABB::AABB(const glm::vec3 &min, const glm::vec3 &max) :\n    min(min), max(max)\n{\n}\n\nvoid AABB::Merge(const glm::vec3 &point)\n{\n\tmin = glm::min(min, point);\n\tmax = glm::max(max, point);\n}\n\nvoid AABB::Merge(const std::vector<glm::vec3> &points)\n{\n\tfor (auto &point : points)\n\t{\n\t\tMerge(point);\n\t}\n}\n\nvoid AABB::Merge(const AABB &aabb)\n{\n\tmin = glm::min(min, aabb.min);\n\tmax = glm::max(max, aabb.max);\n}\n\nAABB AABB::Transform(const glm::mat4 &transform) const\n{\n\tglm::vec3 v[2] = {}, xa, xb, ya, yb, za, zb;\n\n\txa = transform[0] * min[0];\n\txb = transform[0] * max[0];\n\n\tya = transform[1] * min[1];\n\tyb = transform[1] * max[1];\n\n\tza = transform[2] * min[2];\n\tzb = transform[2] * max[2];\n\n\tv[0] = transform[3];\n\tv[0] += glm::min(xa, xb);\n\tv[0] += glm::min(ya, yb);\n\tv[0] += glm::min(za, zb);\n\n\tv[1] = transform[3];\n\tv[1] += glm::max(xa, xb);\n\tv[1] += glm::max(ya, yb);\n\tv[1] += glm::max(za, zb);\n\n\treturn AABB(v[0], v[1]);\n}\n\nconst glm::vec3 AABB::Center() const\n{\n\treturn 0.5f * (min + max);\n}\n\nconst glm::vec3 AABB::Scale() const\n{\n\treturn max - min;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Private/Mesh/EMesh.cpp",
    "content": "#include \"Mesh/EMesh.hpp\"\n\nnamespace Ilum\n{\nEMesh::EMesh(const std::vector<VertexData> &vertices, const std::vector<uint32_t> &indices, uint32_t stride) :\n    m_stride(stride)\n{\n\t// Create new vertices\n\tfor (auto &v : vertices)\n\t{\n\t\tVertex *nv = (Vertex *) m_pool.allocate(sizeof(Vertex), alignof(Vertex));\n\t\tnew (nv) Vertex(v, nullptr);\n\n\t\tm_vertices.insert(nv);\n\t}\n\n\tstd::unordered_map<std::pair<Vertex *, Vertex *>, Edge *, PairHash> vertex_edge_map;\n\n\t// Create new edge\n\tfor (size_t i = 0; i < indices.size(); i += stride)\n\t{\n\t\tFace *nf = (Face *) m_pool.allocate(sizeof(Face), alignof(Face));\n\t\tnew (nf) Face(nullptr);\n\n\t\tstd::vector<Edge *> fe;\n\n\t\tfor (size_t j = 0; j < stride; j++)\n\t\t{\n\t\t\tVertex *v1 = m_vertices[indices[i + j]];\n\t\t\tVertex *v2 = m_vertices[indices[i + (j + 1) % stride]];\n\n\t\t\tif (vertex_edge_map.find(std::make_pair(v1, v2)) == vertex_edge_map.end() &&\n\t\t\t    vertex_edge_map.find(std::make_pair(v2, v1)) == vertex_edge_map.end())\n\t\t\t{\n\t\t\t\tEdge *ne = (Edge *) m_pool.allocate(sizeof(Edge), alignof(Edge));\n\t\t\t\tnew (ne) Edge(v1, v2, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);\n\n\t\t\t\tvertex_edge_map[std::make_pair(v1, v2)] = ne;\n\t\t\t\tvertex_edge_map[std::make_pair(v2, v1)] = ne;\n\n\t\t\t\tm_edges.insert(ne);\n\t\t\t\tfe.push_back(ne);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto *ne = vertex_edge_map[std::make_pair(v1, v2)];\n\t\t\t\tfe.push_back(ne);\n\t\t\t}\n\t\t}\n\n\t\tnf->edge = fe[0];\n\n\t\tfor (size_t j = 0; j < fe.size(); j++)\n\t\t{\n\t\t\tfe[j]->face[0] == nullptr ? fe[j]->face[0] = nf : fe[j]->face[1] = nf;\n\n\t\t\tEdge *e1 = fe[j];\n\t\t\tEdge *e2 = fe[(j + 1) % fe.size()];\n\n\t\t\tif (e1 && e2)\n\t\t\t{\n\t\t\t\te2->prev[0] == nullptr ? e2->prev[0] = e1 : e2->prev[1] = e1;\n\t\t\t\te1->next[0] == nullptr ? e1->next[0] = e2 : e1->next[1] = e2;\n\t\t\t}\n\t\t}\n\n\t\tm_faces.insert(nf);\n\t}\n}\n\nEMesh::~EMesh()\n{\n\tm_pool.release();\n\tm_vertices.clear();\n\tm_faces.clear();\n\tm_edges.clear();\n}\n\nTriMesh EMesh::ToTriMesh() const\n{\n\tstd::vector<VertexData> vertices;\n\tstd::vector<uint32_t>  indices;\n\n\tvertices.reserve(m_vertices.size());\n\tfor (auto &v : m_vertices)\n\t{\n\t\tvertices.push_back(v->data);\n\t}\n\n\t// Convert to triangle mesh\n\tindices.reserve(m_faces.size() * (m_stride - 2) * 3);\n\tfor (auto &f : m_faces)\n\t{\n\t\tEdge    *e        = f->edge;\n\t\tuint32_t face_idx = e->face[0] == f ? 0 : 1;\n\t\tVertex  *start_v  = e->vertex[face_idx];\n\n\t\te = f->edge->next[face_idx];\n\n\t\twhile (e->vertex[0] != start_v && e->vertex[1] != start_v)\n\t\t{\n\t\t\tindices.push_back(static_cast<uint32_t>(m_vertices.idx(start_v)));\n\t\t\tindices.push_back(static_cast<uint32_t>(m_vertices.idx(e->vertex[face_idx])));\n\t\t\tindices.push_back(static_cast<uint32_t>(m_vertices.idx(e->vertex[(face_idx + 1) % 2])));\n\n\t\t\tface_idx = e->face[0] == f ? 0 : 1;\n\n\t\t\te = e->next[face_idx];\n\t\t}\n\t}\n\n\tTriMesh mesh;\n\tmesh.vertices = std::move(vertices);\n\tmesh.indices  = std::move(indices);\n\n\treturn mesh;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Private/Mesh/FMesh.cpp",
    "content": "#include \"Mesh/FMesh.hpp\"\n\nnamespace Ilum\n{\nFMesh::FMesh(const std::vector<VertexData> &vertices, const std::vector<uint32_t> &indices)\n{\n\t// Create new vertices\n\tfor (auto &v : vertices)\n\t{\n\t\tVertex *nv = (Vertex *) m_pool.allocate(sizeof(Vertex), alignof(Vertex));\n\t\tnew (nv) Vertex(v, nullptr);\n\n\t\tm_vertices.insert(nv);\n\t}\n\n\tstd::unordered_map<std::pair<Vertex *, Vertex *>, Face *, PairHash> edge_face_map;\n\tstd::unordered_map<Face *, uint32_t>                                 face_count;\n\n\tfor (size_t idx = 0; idx < indices.size(); idx += 3)\n\t{\n\t\tFace *nf = (Face *) m_pool.allocate(sizeof(Face), alignof(Face));\n\t\tnew (nf) Face(m_vertices[indices[idx]], m_vertices[indices[idx + 1]], m_vertices[indices[idx + 2]], nullptr, nullptr, nullptr);\n\n\t\tm_faces.insert(nf);\n\n\t\tface_count[nf] = 0;\n\n\t\tfor (size_t i = 0; i < 3; i++)\n\t\t{\n\t\t\tif (!m_vertices[indices[idx + i]]->face)\n\t\t\t{\n\t\t\t\tm_vertices[indices[idx + i]]->face = nf;\n\t\t\t}\n\n\t\t\tauto e1 = std::make_pair(nf->vertex[i], nf->vertex[(i + 1) % 3]);\n\t\t\tauto e2 = std::make_pair(nf->vertex[(i + 1) % 3], nf->vertex[i]);\n\n\t\t\tif (edge_face_map.find(e1) != edge_face_map.end())\n\t\t\t{\n\t\t\t\tnf->face[face_count[nf]++]                               = edge_face_map[e1];\n\t\t\t\tedge_face_map[e1]->face[face_count[edge_face_map[e1]]++] = nf;\n\t\t\t}\n\n\t\t\tedge_face_map[e1] = nf;\n\t\t\tedge_face_map[e2] = nf;\n\t\t}\n\t}\n}\n\nFMesh::~FMesh()\n{\n\tm_pool.release();\n\tm_vertices.clear();\n\tm_faces.clear();\n}\n\nTriMesh FMesh::ToTriMesh() const\n{\n\tstd::vector<VertexData> vertices;\n\tstd::vector<uint32_t>  indices;\n\n\tvertices.reserve(m_vertices.size());\n\tfor (auto &v : m_vertices)\n\t{\n\t\tvertices.push_back(v->data);\n\t}\n\n\tindices.reserve(m_faces.size() * 3);\n\tfor (auto &f : m_faces)\n\t{\n\t\tfor (uint32_t i = 0; i < 3; i++)\n\t\t{\n\t\t\tindices.push_back(static_cast<uint32_t>(m_vertices.idx(f->vertex[i])));\n\t\t}\n\t}\n\n\tTriMesh mesh;\n\tmesh.vertices = std::move(vertices);\n\tmesh.indices  = std::move(indices);\n\n\treturn mesh;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Private/Mesh/HEMesh.cpp",
    "content": "#include \"Mesh/HEMesh.hpp\"\n\nnamespace Ilum\n{\nHEMesh::HEMesh(const std::vector<VertexData> &vertices, const std::vector<uint32_t> &indices, uint32_t stride)\n{\n\t// Create new vertices\n\tfor (auto &v : vertices)\n\t{\n\t\tVertex *nv = (Vertex *) m_pool.allocate(sizeof(Vertex), alignof(Vertex));\n\t\tnew (nv) Vertex(v, nullptr);\n\n\t\tm_vertices.insert(nv);\n\t}\n\n\tstd::unordered_map<std::pair<Vertex *, Vertex *>, HalfEdge *, PairHash> vertex_edge_map;\n\n\t// Create new edge\n\tfor (size_t i = 0; i < indices.size(); i += stride)\n\t{\n\t\tFace *nf = (Face *) m_pool.allocate(sizeof(Face), alignof(Face));\n\t\tnew (nf) Face(nullptr);\n\n\t\tm_faces.insert(nf);\n\n\t\tstd::vector<HalfEdge *> fe;\n\n\t\tfor (size_t j = 0; j < stride; j++)\n\t\t{\n\t\t\tVertex *v1 = m_vertices[indices[i + j]];\n\t\t\tVertex *v2 = m_vertices[indices[i + (j + 1) % stride]];\n\n\t\t\t// Not find v1 -> v2, create new one\n\t\t\tif (vertex_edge_map.find(std::make_pair(v1, v2)) == vertex_edge_map.end())\n\t\t\t{\n\t\t\t\tHalfEdge *ne = (HalfEdge *) m_pool.allocate(sizeof(HalfEdge), alignof(HalfEdge));\n\t\t\t\tnew (ne) HalfEdge(v2, nf, nullptr, nullptr, nullptr);\n\n\t\t\t\tv1->half_edge = ne;\n\n\t\t\t\tvertex_edge_map[std::make_pair(v1, v2)] = ne;\n\t\t\t\tm_halfedges.insert(ne);\n\t\t\t\tfe.push_back(ne);\n\n\t\t\t\tif (vertex_edge_map.find(std::make_pair(v2, v1)) != vertex_edge_map.end())\n\t\t\t\t{\n\t\t\t\t\tauto *opposite     = vertex_edge_map[std::make_pair(v2, v1)];\n\t\t\t\t\tne->opposite       = opposite;\n\t\t\t\t\topposite->opposite = ne;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tHalfEdge *opposite = (HalfEdge *) m_pool.allocate(sizeof(HalfEdge), alignof(HalfEdge));\n\t\t\t\t\tnew (opposite) HalfEdge(v1, nullptr, nullptr, nullptr, nullptr);\n\t\t\t\t\tne->opposite       = opposite;\n\t\t\t\t\topposite->opposite = ne;\n\n\t\t\t\t\tvertex_edge_map[std::make_pair(v2, v1)] = opposite;\n\t\t\t\t\tm_halfedges.insert(opposite);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto *ne = vertex_edge_map[std::make_pair(v1, v2)];\n\t\t\t\tne->face = nf;\n\t\t\t\tfe.push_back(ne);\n\t\t\t}\n\t\t}\n\n\t\tnf->half_edge = fe[0];\n\n\t\tfor (size_t i = 0; i < fe.size(); i++)\n\t\t{\n\t\t\tfe[i]->next = fe[(i + 1) % fe.size()];\n\t\t\tfe[i]->prev = fe[(i + fe.size() - 1) % fe.size()];\n\t\t}\n\t}\n\n\tfor (auto *he : m_halfedges)\n\t{\n\t\tif (!he->face)\n\t\t{\n\t\t\the->next = he->opposite->prev->opposite;\n\t\t\twhile (he->next->face)\n\t\t\t{\n\t\t\t\the->next = he->next->prev->opposite;\n\t\t\t}\n\n\t\t\the->prev = he->opposite->next->opposite;\n\t\t\twhile (he->prev->face)\n\t\t\t{\n\t\t\t\the->prev = he->prev->next->opposite;\n\t\t\t}\n\t\t}\n\t}\n}\n\nHEMesh::~HEMesh()\n{\n\tm_pool.release();\n\tm_vertices.clear();\n\tm_faces.clear();\n\tm_halfedges.clear();\n}\n\nconst std::vector<HEMesh::Vertex *> &HEMesh::Vertices() const\n{\n\treturn m_vertices.vec();\n}\n\nconst std::vector<HEMesh::Face *> &HEMesh::Faces() const\n{\n\treturn m_faces.vec();\n}\n\nconst std::vector<HEMesh::HalfEdge *> &HEMesh::HalfEdges() const\n{\n\treturn m_halfedges.vec();\n}\n\nstd::vector<HEMesh::Vertex *> &HEMesh::Vertices()\n{\n\treturn m_vertices.vec();\n}\n\nstd::vector<HEMesh::Face *> &HEMesh::Faces()\n{\n\treturn m_faces.vec();\n}\n\nstd::vector<HEMesh::HalfEdge *> &HEMesh::HalfEdges()\n{\n\treturn m_halfedges.vec();\n}\n\nbool HEMesh::HasBoundary() const\n{\n\tfor (auto &he : m_halfedges)\n\t{\n\t\tif (!he->face)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool HEMesh::IsOnBoundary(HalfEdge *he) const\n{\n\treturn !he->face || !he->opposite->face;\n}\n\nbool HEMesh::IsOnBoundary(Vertex *v) const\n{\n\tauto *he = v->half_edge;\n\tauto *h  = he;\n\tdo\n\t{\n\t\tif (h->opposite->face)\n\t\t{\n\t\t\th = h->opposite->next;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t} while (he != h);\n\n\treturn false;\n}\n\nuint32_t HEMesh::Degree(Vertex *v) const\n{\n\tauto *he = v->half_edge;\n\tauto *h  = he;\n\n\tuint32_t deg = 0;\n\n\tdo\n\t{\n\t\tdeg++;\n\t\th = h->opposite->next;\n\t} while (h != he);\n\n\treturn deg;\n}\n\nstd::vector<std::vector<HEMesh::Vertex *>> HEMesh::Boundary() const\n{\n\tstd::unordered_set<HEMesh::HalfEdge *>     boundary_halfedges;\n\tstd::vector<std::vector<HEMesh::Vertex *>> boundaries;\n\n\tfor (auto *he : m_halfedges)\n\t{\n\t\tif (!he->face && boundary_halfedges.find(he) == boundary_halfedges.end())\n\t\t{\n\t\t\tstd::vector<HEMesh::Vertex *> boundary;\n\n\t\t\tauto *h = he;\n\n\t\t\tdo\n\t\t\t{\n\t\t\t\tboundary_halfedges.insert(h);\n\t\t\t\tboundary.push_back(h->vertex);\n\t\t\t\th = h->next;\n\t\t\t} while (h != he);\n\n\t\t\tboundaries.push_back(boundary);\n\t\t}\n\t}\n\n\treturn boundaries;\n}\n\nstd::vector<HEMesh::Vertex *> HEMesh::AdjVertices(Vertex *v) const\n{\n\tauto *he = v->half_edge;\n\tauto *h  = he;\n\n\tstd::vector<HEMesh::Vertex *> adj_vertices;\n\n\tdo\n\t{\n\t\tadj_vertices.push_back(h->vertex);\n\t\th = h->opposite->next;\n\t} while (h != he);\n\n\treturn adj_vertices;\n}\n\nsize_t HEMesh::VertexIndex(Vertex *v) const\n{\n\treturn m_vertices.idx(v);\n}\n\nTriMesh HEMesh::ToTriMesh() const\n{\n\tstd::vector<VertexData> vertices;\n\tstd::vector<uint32_t>  indices;\n\n\tvertices.reserve(m_vertices.size());\n\tfor (auto &v : m_vertices)\n\t{\n\t\tvertices.push_back(v->data);\n\t}\n\n\t// Convert to triangle mesh\n\tindices.reserve(m_faces.size() * (m_stride - 2) * 3);\n\tfor (auto &f : m_faces)\n\t{\n\t\tauto *he = f->half_edge;\n\t\tauto *h  = he;\n\n\t\tdo\n\t\t{\n\t\t\tindices.push_back(static_cast<uint32_t>(m_vertices.idx(he->vertex)));\n\t\t\the = he->next;\n\t\t} while (h != he);\n\t}\n\n\tTriMesh mesh;\n\tmesh.vertices = std::move(vertices);\n\tmesh.indices  = std::move(indices);\n\n\treturn mesh;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Private/Mesh/Mesh.cpp",
    "content": "#include \"Mesh/Mesh.hpp\"\n\n#include <glm/gtc/constants.hpp>\n\nnamespace Ilum\n{\nvoid TriMesh::GenerateNormal()\n{\n\tfor (size_t i = 0; i < vertices.size(); i++)\n\t{\n\t\tvertices[i].normal = glm::vec3(0.f);\n\t}\n\n\tfor (size_t i = 0; i < indices.size(); i += 3)\n\t{\n\t\tglm::vec3 e2 = vertices[indices[i + 1]].position - vertices[indices[i]].position;\n\t\tglm::vec3 e1 = vertices[indices[i]].position - vertices[indices[i + 2]].position;\n\n\t\tglm::vec3 normal = glm::normalize(glm::cross(e1, e2));\n\t\tvertices[indices[i]].normal += normal;\n\t\tvertices[indices[i + 1]].normal += normal;\n\t\tvertices[indices[i + 2]].normal += normal;\n\t}\n\n\tfor (size_t i = 0; i < vertices.size(); i++)\n\t{\n\t\tvertices[i].normal = glm::normalize(vertices[i].normal);\n\t}\n}\n\nfloat Mesh::Area(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) const\n{\n\tglm::vec3 e1 = v2 - v1;\n\tglm::vec3 e2 = v3 - v1;\n\n\treturn glm::length(glm::cross(e1, e2));\n}\n\nfloat Mesh::LocalAverageLegion(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, LocalAverageLegionOption option) const\n{\n\tif (option == LocalAverageLegionOption::BarycentricCell)\n\t{\n\t\tfloat local_average_legion = 0.f;\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tlocal_average_legion += Area(center, neighbors[i], neighbors[i + 1]) / 3.f;\n\t\t}\n\t\treturn local_average_legion;\n\t}\n\telse if (option == LocalAverageLegionOption::VoronoiCell)\n\t{\n\t\tfloat local_average_legion = 0.f;\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tglm::vec3 e1 = neighbors[i] - center;\n\t\t\tglm::vec3 e2 = neighbors[i + 1] - center;\n\t\t\tglm::vec3 n  = Normal(center, neighbors[i], neighbors[i + 1]);\n\n\t\t\tglm::vec3 vb1 = glm::normalize(glm::cross(n, e1));\n\t\t\tglm::vec3 vb2 = glm::normalize(glm::cross(e2, n));\n\n\t\t\tglm::vec3 mp1 = (neighbors[i] + center) * 0.5f;\n\t\t\tglm::vec3 mp2 = (neighbors[i + 1] + center) * 0.5f;\n\n\t\t\tfloat     t = ((vb1.y * mp1.x - vb1.x * mp1.y) - (vb1.y * mp2.x - vb1.x * mp2.y)) / (vb1.y * vb2.x - vb1.x * vb2.y);\n\t\t\tglm::vec3 p = mp2 + vb2 * t;\n\n\t\t\tlocal_average_legion += Area(p, mp1, center) + Area(p, mp2, center);\n\t\t}\n\t\treturn local_average_legion;\n\t}\n\telse if (option == LocalAverageLegionOption::MixVoronoiCell)\n\t{\n\t\tfloat local_average_legion = 0.f;\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tglm::vec3 e1 = neighbors[i] - center;\n\t\t\tglm::vec3 e2 = neighbors[i + 1] - center;\n\n\t\t\tif (glm::dot(e1, e2) < 0.f)\n\t\t\t{\n\t\t\t\tglm::vec3 mp  = (neighbors[i] + neighbors[i + 1]) * 0.5f;\n\t\t\t\tglm::vec3 mp1 = (neighbors[i] + center) * 0.5f;\n\t\t\t\tglm::vec3 mp2 = (neighbors[i + 1] + center) * 0.5f;\n\n\t\t\t\tlocal_average_legion += Area(mp, mp1, center) + Area(mp, mp2, center);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tglm::vec3 n = Normal(center, neighbors[i], neighbors[i + 1]);\n\n\t\t\t\tglm::vec3 vb1 = glm::normalize(glm::cross(n, e1));\n\t\t\t\tglm::vec3 vb2 = glm::normalize(glm::cross(e2, n));\n\n\t\t\t\tglm::vec3 mp1 = (neighbors[i] + center) * 0.5f;\n\t\t\t\tglm::vec3 mp2 = (neighbors[i + 1] + center) * 0.5f;\n\n\t\t\t\tfloat     t = ((vb1.y * mp1.x - vb1.x * mp1.y) - (vb1.y * mp2.x - vb1.x * mp2.y)) / (vb1.y * vb2.x - vb1.x * vb2.y);\n\t\t\t\tglm::vec3 p = mp2 + vb2 * t;\n\n\t\t\t\tlocal_average_legion += Area(p, mp1, center) + Area(p, mp2, center);\n\t\t\t}\n\t\t}\n\t\treturn local_average_legion;\n\t}\n\n\treturn 0.0f;\n}\n\nglm::vec3 Mesh::Laplace(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, LaplaceOption option) const\n{\n\tif (option == LaplaceOption::Uniform)\n\t{\n\t\tglm::vec3 result = glm::vec3(0.f);\n\t\tfor (auto &neighbor : neighbors)\n\t\t{\n\t\t\tresult += (neighbor - center);\n\t\t}\n\t\treturn result / static_cast<float>(neighbors.size());\n\t}\n\telse if (option == LaplaceOption::CotangentFormula)\n\t{\n\t\tglm::vec3 result = glm::vec3(0.f);\n\t\tfor (size_t i = 0; i < neighbors.size(); i++)\n\t\t{\n\t\t\tglm::vec3 current = neighbors[i];\n\t\t\tglm::vec3 next    = neighbors[(i + 1) % neighbors.size()];\n\t\t\tglm::vec3 prev    = neighbors[(i + neighbors.size() - 1) % neighbors.size()];\n\n\t\t\tfloat cos_alpha = glm::dot(center - next, current - next) / (glm::length(center - next), glm::length(current - next));\n\t\t\tfloat cos_beta  = glm::dot(center - prev, current - prev) / (glm::length(center - prev), glm::length(current - prev));\n\n\t\t\tfloat cot_alpha = cos_alpha / glm::sqrt(1 - cos_alpha * cos_alpha);\n\t\t\tfloat cot_beta  = cos_beta / glm::sqrt(1 - cos_beta * cos_beta);\n\n\t\t\tresult += (cot_alpha + cot_beta) * (current - center);\n\t\t}\n\t\treturn result / (2.f * LocalAverageLegion(center, neighbors));\n\t}\n\n\treturn glm::vec3(0.f);\n}\n\nglm::vec3 Mesh::Normal(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) const\n{\n\tglm::vec3 e1 = v2 - v1;\n\tglm::vec3 e2 = v3 - v1;\n\n\treturn glm::normalize(glm::cross(e1, e2));\n}\n\nglm::vec3 Mesh::Normal(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, VertexNormalOption option) const\n{\n\tif (option == VertexNormalOption::Uniform)\n\t{\n\t\tglm::vec3 norm = glm::vec3(0.f);\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tnorm += Normal(center, neighbors[i], neighbors[i + 1]);\n\t\t}\n\t\treturn glm::normalize(norm);\n\t}\n\telse if (option == VertexNormalOption::Area)\n\t{\n\t\tglm::vec3 norm = glm::vec3(0.f);\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tnorm += Area(center, neighbors[i], neighbors[i + 1]) * Normal(center, neighbors[i], neighbors[i + 1]);\n\t\t}\n\t\treturn glm::normalize(norm);\n\t}\n\telse if (option == VertexNormalOption::Angle)\n\t{\n\t\tglm::vec3 norm = glm::vec3(0.f);\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tglm::vec3 e1    = neighbors[i] - center;\n\t\t\tglm::vec3 e2    = neighbors[i + 1] - center;\n\t\t\tfloat     angle = glm::acos(glm::dot(e1, e2) / (glm::length(e1) * glm::length(e2)));\n\t\t\tnorm += angle * Normal(center, neighbors[i], neighbors[i + 1]);\n\t\t}\n\t\treturn glm::normalize(norm);\n\t}\n\n\treturn glm::vec3(0.f);\n}\n\nfloat Mesh::Curvature(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, CurvatureOption option)\n{\n\tif (option == CurvatureOption::Mean)\n\t{\n\t\tglm::vec3 laplacian = Laplace(center, neighbors);\n\t\tglm::vec3 norm      = Normal(center, neighbors);\n\t\treturn -0.5f * glm::dot(laplacian, norm);\n\t}\n\telse if (option == CurvatureOption::AbsoluteMean)\n\t{\n\t\tglm::vec3 laplacian = Laplace(center, neighbors);\n\t\tglm::vec3 norm      = Normal(center, neighbors);\n\t\treturn glm::abs(-0.5f * glm::dot(laplacian, norm));\n\t}\n\telse if (option == CurvatureOption::Gaussian)\n\t{\n\t\tfloat result = 2.f * glm::pi<float>();\n\t\tfor (size_t i = 0; i < neighbors.size() - 1; i++)\n\t\t{\n\t\t\tglm::vec3 e1    = neighbors[i] - center;\n\t\t\tglm::vec3 e2    = neighbors[i + 1] - center;\n\t\t\tfloat     angle = glm::acos(glm::dot(e1, e2) / (glm::length(e1) * glm::length(e2)));\n\t\t\tresult -= angle;\n\t\t}\n\t\treturn result / LocalAverageLegion(center, neighbors);\n\t}\n\n\treturn 0.0f;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Private/MeshProcess.cpp",
    "content": "#include \"MeshProcess.hpp\"\n\nnamespace Ilum\n{\ntemplate <typename _Ty>\nstd::unique_ptr<_Ty> &MeshProcess<_Ty>::GetInstance(const std::string &plugin)\n{\n\tstatic std::unique_ptr<_Ty> ptr = std::unique_ptr<_Ty>(PluginManager::GetInstance().Call<_Ty *>(plugin, \"Create\"));\n\treturn ptr;\n}\n\ntemplate  class MeshProcess<Subdivision>;\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/AABB.hpp",
    "content": "#pragma once\n\n#include <glm/glm.hpp>\n#include <glm/vec3.hpp>\n\n#include <vector>\n\nnamespace Ilum\n{\nstruct AABB\n{\n  public:\n\tglm::vec3 min = glm::vec3(std::numeric_limits<float>::max());\n\tglm::vec3 max = glm::vec3(-std::numeric_limits<float>::min());\n\n  public:\n\tAABB() = default;\n\n\tAABB(const glm::vec3 &min, const glm::vec3 &max);\n\n\t~AABB() = default;\n\n\tvoid Merge(const glm::vec3 &point);\n\n\tvoid Merge(const std::vector<glm::vec3> &points);\n\n\tvoid Merge(const AABB &aabb);\n\n\tAABB Transform(const glm::mat4 &transform) const;\n\n\tconst glm::vec3 Center() const;\n\n\tconst glm::vec3 Scale() const;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/Mesh/EMesh.hpp",
    "content": "#pragma once\n\n#include \"Mesh/Mesh.hpp\"\n\nnamespace Ilum\n{\n// Edge based data structure\nclass  EMesh : public Mesh\n{\n  public:\n\tstruct Vertex;\n\tstruct Edge;\n\tstruct Face;\n\n\tstruct Vertex\n\t{\n\t\tVertexData data;\n\t\tEdge      *edge = nullptr;\n\n\t\tVertex(const VertexData &data, Edge *edge) :\n\t\t    data(data), edge(edge)\n\t\t{}\n\t};\n\n\tstruct Face\n\t{\n\t\tEdge *edge = nullptr;\n\n\t\tFace(Edge *edge) :\n\t\t    edge(edge)\n\t\t{}\n\t};\n\n\tstruct Edge\n\t{\n\t\tVertex *vertex[2];\n\t\tFace   *face[2];\n\t\tEdge   *next[2];\n\t\tEdge   *prev[2];\n\n\t\tEdge(Vertex *v1, Vertex *v2, Face *f1, Face *f2, Edge *next_e1, Edge *next_e2, Edge *prev_e1, Edge *prev_e2) :\n\t\t    vertex{v1, v2}, face{f1, f2}, next{next_e1, next_e2}, prev{prev_e1, prev_e2}\n\t\t{}\n\t};\n\n  public:\n\tEMesh(const std::vector<VertexData> &vertices, const std::vector<uint32_t> &indices, uint32_t stride = 3);\n\n\t~EMesh();\n\n\tvirtual TriMesh ToTriMesh() const override;\n\n  private:\n\tuint32_t m_stride;\n\n\tRandomSet<Vertex *> m_vertices;\n\tRandomSet<Face *>   m_faces;\n\tRandomSet<Edge *>   m_edges;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/Mesh/FMesh.hpp",
    "content": "#pragma once\n\n#include \"Mesh.hpp\"\n\nnamespace Ilum\n{\n// Face based data structure only support triangle mesh\nclass  FMesh : public Mesh\n{\n  public:\n\tstruct Face;\n\tstruct Vertex;\n\n\tstruct Vertex\n\t{\n\t\tVertexData data;\n\t\tFace      *face;\n\n\t\tVertex(const VertexData &data, Face *face) :\n\t\t    data(data), face(face)\n\t\t{}\n\t};\n\n\tstruct Face\n\t{\n\t\tVertex *vertex[3];\n\t\tFace   *face[3];\n\n\t\tFace(Vertex *v1, Vertex *v2, Vertex *v3, Face *f1, Face *f2, Face *f3) :\n\t\t    vertex{v1, v2, v3}, face{f1, f2, f3}\n\t\t{}\n\t};\n\n  public:\n\tFMesh(const std::vector<VertexData> &vertices, const std::vector<uint32_t> &indices);\n\n\t~FMesh();\n\n\tvirtual TriMesh ToTriMesh() const override;\n\n  private:\n\tRandomSet<Vertex *> m_vertices;\n\tRandomSet<Face *>   m_faces;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/Mesh/HEMesh.hpp",
    "content": "#pragma once\n\n#include \"Mesh.hpp\"\n\nnamespace Ilum\n{\nclass  HEMesh : public Mesh\n{\n  public:\n\tstruct Vertex;\n\tstruct Face;\n\tstruct HalfEdge;\n\n\tstruct Vertex\n\t{\n\t\tVertexData data;\n\t\tHalfEdge  *half_edge;\n\n\t\tVertex(const VertexData &data, HalfEdge *half_edge) :\n\t\t    data(data), half_edge(half_edge)\n\t\t{}\n\t};\n\n\tstruct Face\n\t{\n\t\tHalfEdge *half_edge;\n\n\t\tFace(HalfEdge *half_edge) :\n\t\t    half_edge(half_edge)\n\t\t{}\n\t};\n\n\tstruct HalfEdge\n\t{\n\t\tVertex   *vertex;\n\t\tFace     *face;\n\t\tHalfEdge *next;\n\t\tHalfEdge *prev;\n\t\tHalfEdge *opposite;\n\n\t\tHalfEdge(Vertex *vertex, Face *face, HalfEdge *next, HalfEdge *prev, HalfEdge *opposite) :\n\t\t    vertex(vertex), face(face), next(next), prev(prev), opposite(opposite)\n\t\t{}\n\t};\n\n\tHEMesh(const std::vector<VertexData> &vertices, const std::vector<uint32_t> &indices, uint32_t stride = 3);\n\n\t~HEMesh();\n\n\tconst std::vector<Vertex *> &Vertices() const;\n\n\tconst std::vector<Face *> &Faces() const;\n\n\tconst std::vector<HalfEdge *> &HalfEdges() const;\n\n\tstd::vector<Vertex *> &Vertices();\n\n\tstd::vector<Face *> &Faces();\n\n\tstd::vector<HalfEdge *> &HalfEdges();\n\n\tbool HasBoundary() const;\n\n\tbool IsOnBoundary(HalfEdge *he) const;\n\n\tbool IsOnBoundary(Vertex *v) const;\n\n\tuint32_t Degree(Vertex *v) const;\n\n\tstd::vector<std::vector<Vertex *>> Boundary() const;\n\n\tstd::vector<Vertex *> AdjVertices(Vertex *v) const;\n\n\tsize_t VertexIndex(Vertex *v) const;\n\n\tvirtual TriMesh ToTriMesh() const override;\n\n  private:\n\tuint32_t m_stride;\n\n\tRandomSet<Vertex *>   m_vertices;\n\tRandomSet<HalfEdge *> m_halfedges;\n\tRandomSet<Face *>     m_faces;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/Mesh/Mesh.hpp",
    "content": "#pragma once\n\n#include \"../Precompile.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nstruct VertexData\n{\n\tglm::vec3 position = glm::vec3(0.f);\n\tglm::vec3 normal   = glm::vec3(0.f);\n\tglm::vec2 uv       = glm::vec2(0.f);\n};\n\nstruct  TriMesh\n{\n\tstd::vector<VertexData> vertices;\n\tstd::vector<uint32_t>   indices;\n\n\tvoid GenerateNormal();\n};\n\nclass  Mesh\n{\n  public:\n\tenum class VertexNormalOption\n\t{\n\t\tUniform,\n\t\tArea,\n\t\tAngle\n\t};\n\n\tenum class LaplaceOption\n\t{\n\t\tUniform,\n\t\tCotangentFormula\n\t};\n\n\tenum class CurvatureOption\n\t{\n\t\tMean,\n\t\tAbsoluteMean,\n\t\tGaussian\n\t};\n\n\tenum class LocalAverageLegionOption\n\t{\n\t\tBarycentricCell,\n\t\tVoronoiCell,\n\t\tMixVoronoiCell\n\t};\n\n  public:\n\tMesh() = default;\n\n\t~Mesh() = default;\n\n\tvirtual TriMesh ToTriMesh() const = 0;\n\n  protected:\n\tfloat Area(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) const;\n\n\tfloat LocalAverageLegion(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, LocalAverageLegionOption option = LocalAverageLegionOption::MixVoronoiCell) const;\n\n\t// neighbor points must in order\n\tglm::vec3 Laplace(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, LaplaceOption option = LaplaceOption::CotangentFormula) const;\n\n\tglm::vec3 Normal(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) const;\n\n\tglm::vec3 Normal(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, VertexNormalOption option = VertexNormalOption::Angle) const;\n\n\tfloat Curvature(const glm::vec3 &center, const std::vector<glm::vec3> &neighbors, CurvatureOption option = CurvatureOption::Gaussian);\n\n  protected:\n\tstd::pmr::unsynchronized_pool_resource m_pool;\n};\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/MeshProcess.hpp",
    "content": "#pragma once\n\n#include \"Mesh/Mesh.hpp\"\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\ntemplate <typename _Ty>\nclass  MeshProcess\n{\n  public:\n\tstatic std::unique_ptr<_Ty> &GetInstance(const std::string &plugin);\n};\n\nclass  Subdivision : public MeshProcess<Subdivision>\n{\n  public:\n\tvirtual TriMesh Execute(const TriMesh &mesh) = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/Meshlet.hpp",
    "content": "#pragma once\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nstruct Meshlet\n{\n\tglm::vec3 center;\n\tfloat     radius;\n\n\tuint32_t data_offset;\n\tuint32_t vertex_offset;\n\tuint32_t vertex_count;\n\tuint32_t triangle_count;\n\n\tglm::vec3 cone_axis;\n\tfloat     cone_cutoff;\n\n\tglm::vec3 cone_apex;\n\tuint32_t  visible = false;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(center, radius, cone_axis, cone_cutoff, cone_apex, data_offset, vertex_offset, vertex_count, triangle_count);\n\t}\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Geometry/Public/Geometry/Precompile.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n"
  },
  {
    "path": "Source/Runtime/Geometry/xmake.lua",
    "content": "target(\"Geometry\")\n    set_kind(\"$(kind)\")\n    add_files(\"Private/**.cpp\")\n    set_pcxxheader(\"Public/Geometry/Precompile.hpp\")\n\n    add_includedirs(\"Public/Geometry\")\n    add_includedirs(\"Public\", {public  = true})\n\n    add_deps(\"Core\")\n    add_packages(\"spdlog\", \"glm\", \"cereal\")\ntarget_end()\n"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIAccelerationStructure.cpp",
    "content": "#include \"RHIAccelerationStructure.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIAccelerationStructure::RHIAccelerationStructure(RHIDevice *device):\n    p_device(device)\n{\n}\n\nstd::unique_ptr<RHIAccelerationStructure> RHIAccelerationStructure::Create(RHIDevice *rhi_device)\n{\n\treturn std::unique_ptr<RHIAccelerationStructure>(std::move(PluginManager::GetInstance().Call<RHIAccelerationStructure *>(fmt::format(\"RHI.{}.dll\", rhi_device->GetBackend()), \"CreateAccelerationStructure\", rhi_device)));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIBuffer.cpp",
    "content": "#include \"RHIBuffer.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIBuffer::RHIBuffer(RHIDevice *device, const BufferDesc &desc) :\n    p_device(device), m_desc(desc)\n{\n}\n\nconst std::string RHIBuffer::GetBackend() const\n{\n\treturn p_device->GetBackend();\n}\n\nstd::unique_ptr<RHIBuffer> RHIBuffer::Create(RHIDevice *device, const BufferDesc &desc)\n{\n\treturn std::unique_ptr<RHIBuffer>(std::move(PluginManager::GetInstance().Call<RHIBuffer *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateBuffer\", device, desc)));\n}\n\nconst BufferDesc &RHIBuffer::GetDesc() const\n{\n\treturn m_desc;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHICommand.cpp",
    "content": "#include \"RHICommand.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHICommand::RHICommand(RHIDevice *device, RHIQueueFamily family) :\n    p_device(device), m_family(family)\n{\n}\n\nRHIQueueFamily RHICommand::GetQueueFamily() const\n{\n\treturn m_family;\n}\n\nconst std::string RHICommand::GetBackend() const\n{\n\treturn p_device->GetBackend();\n}\n\nCommandState RHICommand::GetState() const\n{\n\treturn m_state;\n}\n\nvoid RHICommand::Init()\n{\n\tassert(m_state == CommandState::Available);\n\tm_state = CommandState::Initial;\n}\n\nstd::unique_ptr<RHICommand> RHICommand::Create(RHIDevice *device, RHIQueueFamily family)\n{\n\treturn std::unique_ptr<RHICommand>(std::move(PluginManager::GetInstance().Call<RHICommand *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateCommand\", device, family)));\n}\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIContext.cpp",
    "content": "#include \"RHIContext.hpp\"\n\n#include <Core/Path.hpp>\n#include <Core/Plugin.hpp>\n#include <Core/Time.hpp>\n\n#undef CreateSemaphore\n\nnamespace Ilum\n{\nRHIContext::RHIContext(Window *window, const std::string &backend, bool vsync) :\n    p_window(window), m_vsync(vsync)\n{\n\tif (Path::GetInstance().IsExist(\"shared/RHI/RHI.CUDA.dll\"))\n\t{\n\t\tm_cuda_device = RHIDevice::Create(\"CUDA\");\n\t}\n\n\tm_device = RHIDevice::Create(backend);\n\n\tm_swapchain = RHISwapchain::Create(m_device.get(), p_window->GetNativeHandle(), p_window->GetWidth(), p_window->GetHeight(), m_vsync);\n\n\tm_queue = RHIQueue::Create(m_device.get());\n\n\tif (m_cuda_device)\n\t{\n\t\tm_cuda_queue = RHIQueue::Create(m_cuda_device.get());\n\t}\n\n\tfor (uint32_t i = 0; i < m_swapchain->GetTextureCount(); i++)\n\t{\n\t\tm_frames.emplace_back(RHIFrame::Create(m_device.get()));\n\n\t\tif (m_cuda_device)\n\t\t{\n\t\t\tm_cuda_frames.emplace_back(RHIFrame::Create(m_cuda_device.get()));\n\t\t}\n\n\t\tm_present_complete.emplace_back(RHISemaphore::Create(m_device.get()));\n\t\tm_render_complete.emplace_back(RHISemaphore::Create(m_device.get()));\n\t}\n}\n\nRHIContext::~RHIContext()\n{\n\tm_device->WaitIdle();\n\n\tfor (auto &frame : m_frames)\n\t{\n\t\tframe->Reset();\n\t}\n\n\tm_frames.clear();\n\tm_cuda_frames.clear();\n\n\tm_present_complete.clear();\n\tm_render_complete.clear();\n\n\tm_swapchain.reset();\n\n\tm_samplers.clear();\n\n\tm_queue.reset();\n\n\tm_cuda_device.reset();\n\n\tm_device.reset();\n}\n\nconst std::string &RHIContext::GetDeviceName() const\n{\n\treturn m_device->GetName();\n}\n\nconst std::string RHIContext::GetBackend() const\n{\n\treturn m_device->GetBackend();\n}\n\nbool RHIContext::HasCUDA() const\n{\n\treturn m_cuda_device != nullptr;\n}\n\nbool RHIContext::IsVsync() const\n{\n\treturn m_vsync;\n}\n\nvoid RHIContext::SetVsync(bool vsync)\n{\n\tm_vsync = vsync;\n}\n\nbool RHIContext::IsFeatureSupport(RHIFeature feature) const\n{\n\treturn m_device->IsFeatureSupport(feature);\n}\n\nvoid RHIContext::WaitIdle() const\n{\n\tm_device->WaitIdle();\n}\n\nRHISwapchain *RHIContext::GetSwapchain() const\n{\n\treturn m_swapchain.get();\n}\n\nstd::unique_ptr<RHISwapchain> RHIContext::CreateSwapchain(void *window_handle, uint32_t width, uint32_t height, bool sync)\n{\n\treturn RHISwapchain::Create(m_device.get(), window_handle, width, height, sync);\n}\n\nstd::unique_ptr<RHITexture> RHIContext::CreateTexture(const TextureDesc &desc)\n{\n\treturn RHITexture::Create(m_device.get(), desc);\n}\n\nstd::unique_ptr<RHITexture> RHIContext::CreateTexture2D(uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples)\n{\n\treturn RHITexture::Create2D(m_device.get(), width, height, format, usage, mipmap, samples);\n}\n\nstd::unique_ptr<RHITexture> RHIContext::CreateTexture3D(uint32_t width, uint32_t height, uint32_t depth, RHIFormat format, RHITextureUsage usage)\n{\n\treturn RHITexture::Create3D(m_device.get(), width, height, depth, format, usage);\n}\n\nstd::unique_ptr<RHITexture> RHIContext::CreateTextureCube(uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap)\n{\n\treturn RHITexture::CreateCube(m_device.get(), width, height, format, usage, mipmap);\n}\n\nstd::unique_ptr<RHITexture> RHIContext::CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples)\n{\n\treturn RHITexture::Create2DArray(m_device.get(), width, height, layers, format, usage, mipmap, samples);\n}\n\nstd::unique_ptr<RHITexture> RHIContext::MapToCUDATexture(RHITexture *texture)\n{\n\tif (m_cuda_device)\n\t{\n\t\tHANDLE mem_handle = PluginManager::GetInstance().Call<HANDLE>(fmt::format(\"RHI.{}.dll\", m_device->GetBackend()), \"GetTextureMemHandle\", m_device.get(), texture);\n\t\treturn std::unique_ptr<RHITexture>(std::move(PluginManager::GetInstance().Call<RHITexture *>(\"RHI.CUDA.dll\", fmt::format(\"MapTexture{}ToCUDA\", m_device->GetBackend()), m_device.get(), texture->GetDesc(), mem_handle, texture->GetMemorySize())));\n\t}\n\treturn nullptr;\n}\n\nstd::unique_ptr<RHIBuffer> RHIContext::CreateBuffer(const BufferDesc &desc)\n{\n\treturn RHIBuffer::Create(m_device.get(), desc);\n}\n\nstd::unique_ptr<RHIBuffer> RHIContext::CreateBuffer(size_t size, RHIBufferUsage usage, RHIMemoryUsage memory)\n{\n\tBufferDesc desc = {};\n\tdesc.size       = size;\n\tdesc.usage      = usage;\n\tdesc.memory     = memory;\n\n\treturn RHIBuffer::Create(m_device.get(), desc);\n}\n\nstd::unique_ptr<RHIBuffer> RHIContext::MapToCUDABuffer(RHIBuffer *buffer)\n{\n\tif (m_cuda_device)\n\t{\n\t\tHANDLE mem_handle = PluginManager::GetInstance().Call<HANDLE>(fmt::format(\"RHI.{}.dll\", m_device->GetBackend()), \"GetBufferMemHandle\", m_device.get(), buffer);\n\t\treturn std::unique_ptr<RHIBuffer>(std::move(PluginManager::GetInstance().Call<RHIBuffer *>(\"RHI.CUDA.dll\", fmt::format(\"MapBuffer{}ToCUDA\", m_device->GetBackend()), m_device.get(), buffer->GetDesc(), mem_handle)));\n\t}\n\treturn nullptr;\n}\n\nRHISampler *RHIContext::CreateSampler(const SamplerDesc &desc)\n{\n\tsize_t hash = Hash(desc.address_mode_u, desc.address_mode_v, desc.address_mode_w, desc.anisotropic, desc.border_color, desc.mag_filter, desc.max_lod, desc.min_filter, desc.min_lod, desc.mipmap_mode, desc.mip_lod_bias);\n\n\tif (m_sampler_lookup.find(hash) == m_sampler_lookup.end())\n\t{\n\t\tm_sampler_lookup.emplace(hash, m_samplers.size());\n\t\tm_samplers.emplace_back(RHISampler::Create(m_device.get(), desc));\n\t}\n\n\treturn m_samplers.at(m_sampler_lookup.at(hash)).get();\n}\n\nuint32_t RHIContext::GetSamplerIndex(const SamplerDesc &desc)\n{\n\tsize_t hash = Hash(desc.address_mode_u, desc.address_mode_v, desc.address_mode_w, desc.anisotropic, desc.border_color, desc.mag_filter, desc.max_lod, desc.min_filter, desc.min_lod, desc.mipmap_mode, desc.mip_lod_bias);\n\tif (m_sampler_lookup.find(hash) == m_sampler_lookup.end())\n\t{\n\t\tCreateSampler(desc);\n\t}\n\treturn static_cast<uint32_t>(m_sampler_lookup.at(hash));\n}\n\nstd::vector<RHISampler *> RHIContext::GetSamplers() const\n{\n\tstd::vector<RHISampler *>samplers(m_samplers.size());\n\tstd::transform(m_samplers.begin(), m_samplers.end(), samplers.begin(), [](const std::unique_ptr<RHISampler> &sampler) { return sampler.get(); });\n\treturn samplers;\n}\n\nsize_t RHIContext::GetSamplerCount() const\n{\n\treturn m_samplers.size();\n}\n\nRHICommand *RHIContext::CreateCommand(RHIQueueFamily family, bool cuda)\n{\n\treturn cuda ? m_cuda_frames[m_current_frame]->AllocateCommand(family) : m_frames[m_current_frame]->AllocateCommand(family);\n}\n\nRHIDescriptor *RHIContext::CreateDescriptor(const ShaderMeta &meta, bool cuda)\n{\n\treturn cuda ? m_cuda_frames[m_current_frame]->AllocateDescriptor(meta) : m_frames[m_current_frame]->AllocateDescriptor(meta);\n}\n\nstd::unique_ptr<RHIPipelineState> RHIContext::CreatePipelineState(bool cuda)\n{\n\treturn RHIPipelineState::Create(cuda ? m_cuda_device.get() : m_device.get());\n}\n\nstd::unique_ptr<RHIShader> RHIContext::CreateShader(const std::string &entry_point, const std::vector<uint8_t> &source, bool cuda)\n{\n\treturn RHIShader::Create(cuda ? m_cuda_device.get() : m_device.get(), entry_point, source);\n}\n\nstd::unique_ptr<RHIRenderTarget> RHIContext::CreateRenderTarget(bool cuda)\n{\n\treturn RHIRenderTarget::Create(m_device.get());\n}\n\nstd::unique_ptr<RHIProfiler> RHIContext::CreateProfiler(bool cuda)\n{\n\treturn RHIProfiler::Create(cuda ? m_cuda_device.get() : m_device.get(), m_swapchain->GetTextureCount());\n}\n\nstd::unique_ptr<RHIFence> RHIContext::CreateFence()\n{\n\treturn RHIFence::Create(m_device.get());\n}\n\nRHIFence *RHIContext::CreateFrameFence()\n{\n\treturn m_frames[m_current_frame]->AllocateFence();\n}\n\nstd::unique_ptr<RHISemaphore> RHIContext::CreateSemaphore(bool cuda)\n{\n\treturn RHISemaphore::Create(m_device.get());\n}\n\nRHISemaphore *RHIContext::CreateFrameSemaphore()\n{\n\treturn m_frames[m_current_frame]->AllocateSemaphore();\n}\n\nstd::unique_ptr<RHISemaphore> RHIContext::MapToCUDASemaphore(RHISemaphore *semaphore)\n{\n\tif (m_cuda_device)\n\t{\n\t\tHANDLE mem_handle = PluginManager::GetInstance().Call<HANDLE>(fmt::format(\"RHI.{}.dll\", m_device->GetBackend()), \"GetSemaphoreHandle\", m_device.get(), semaphore);\n\t\treturn std::unique_ptr<RHISemaphore>(std::move(PluginManager::GetInstance().Call<RHISemaphore *>(\"RHI.CUDA.dll\", fmt::format(\"MapSemaphore{}ToCUDA\", m_device->GetBackend()), m_device.get(), mem_handle)));\n\t}\n\treturn nullptr;\n}\n\nstd::unique_ptr<RHIAccelerationStructure> RHIContext::CreateAcccelerationStructure()\n{\n\treturn RHIAccelerationStructure::Create(m_device.get());\n}\n\nvoid RHIContext::Submit(std::vector<RHICommand *> &&cmd_buffers, std::vector<RHISemaphore *> &&wait_semaphores, std::vector<RHISemaphore *> &&signal_semaphores)\n{\n\tSubmitInfo submit_info        = {};\n\tsubmit_info.is_cuda           = cmd_buffers.empty() ? false : cmd_buffers[0]->GetBackend() == \"CUDA\";\n\tsubmit_info.queue_family      = cmd_buffers.empty() ? RHIQueueFamily::Graphics : cmd_buffers[0]->GetQueueFamily();\n\tsubmit_info.cmd_buffers       = std::move(cmd_buffers);\n\tsubmit_info.wait_semaphores   = std::move(wait_semaphores);\n\tsubmit_info.signal_semaphores = std::move(signal_semaphores);\n\tm_submit_infos.emplace_back(std::move(submit_info));\n}\n\nvoid RHIContext::Execute(RHICommand *cmd_buffer)\n{\n\tif (cmd_buffer->GetBackend() == \"CUDA\")\n\t{\n\t\tm_cuda_queue->Execute(cmd_buffer);\n\t}\n\telse\n\t{\n\t\tm_queue->Execute(cmd_buffer);\n\t}\n}\n\nvoid RHIContext::Execute(std::vector<RHICommand *> &&cmd_buffers, std::vector<RHISemaphore *> &&wait_semaphores, std::vector<RHISemaphore *> &&signal_semaphores, RHIFence *fence)\n{\n\tSubmitInfo submit_info        = {};\n\tsubmit_info.is_cuda           = cmd_buffers.empty() ? false : cmd_buffers[0]->GetBackend() == \"CUDA\";\n\tsubmit_info.queue_family      = cmd_buffers.empty() ? RHIQueueFamily::Graphics : cmd_buffers[0]->GetQueueFamily();\n\tsubmit_info.cmd_buffers       = std::move(cmd_buffers);\n\tsubmit_info.wait_semaphores   = std::move(wait_semaphores);\n\tsubmit_info.signal_semaphores = std::move(signal_semaphores);\n\n\tif (submit_info.is_cuda)\n\t{\n\t\tm_cuda_queue->Execute(submit_info.queue_family, {submit_info}, fence);\n\t}\n\telse\n\t{\n\t\tm_queue->Execute(submit_info.queue_family, {submit_info}, fence);\n\t}\n}\n\nvoid RHIContext::Reset()\n{\n\tm_submit_infos.clear();\n}\n\nRHITexture *RHIContext::GetBackBuffer()\n{\n\treturn m_swapchain->GetCurrentTexture();\n}\n\nvoid RHIContext::BeginFrame()\n{\n\tm_swapchain->AcquireNextTexture(m_present_complete[m_current_frame].get(), nullptr);\n\tm_frames[m_current_frame]->Reset();\n}\n\nvoid RHIContext::EndFrame()\n{\n\tif (!m_submit_infos.empty())\n\t{\n\t\tfor (int32_t i = static_cast<int32_t>(m_submit_infos.size()) - 1; i >= 0; i--)\n\t\t{\n\t\t\tif (!m_submit_infos[i].is_cuda)\n\t\t\t{\n\t\t\t\tm_submit_infos[i].signal_semaphores.push_back(m_render_complete[m_current_frame].get());\n\t\t\t\tm_submit_infos[i].wait_semaphores.push_back(m_present_complete[m_current_frame].get());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tstd::vector<SubmitInfo> pack_submit_infos;\n\t\tpack_submit_infos.reserve(m_submit_infos.size());\n\t\tRHIQueueFamily last_queue_family = m_submit_infos[0].queue_family;\n\t\tbool           last_is_cuda      = m_submit_infos[0].is_cuda;\n\n\t\tfor (auto &submit_info : m_submit_infos)\n\t\t{\n\t\t\tif (last_queue_family != submit_info.queue_family || last_is_cuda != submit_info.is_cuda)\n\t\t\t{\n\t\t\t\tif (last_is_cuda)\n\t\t\t\t{\n\t\t\t\t\tm_cuda_queue->Execute(last_queue_family, pack_submit_infos);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_queue->Execute(last_queue_family, pack_submit_infos, m_frames[m_current_frame]->AllocateFence());\n\t\t\t\t}\n\t\t\t\tpack_submit_infos.clear();\n\t\t\t\tlast_queue_family = submit_info.queue_family;\n\t\t\t\tlast_is_cuda      = submit_info.is_cuda;\n\t\t\t}\n\t\t\tpack_submit_infos.push_back(submit_info);\n\t\t}\n\t\tif (!pack_submit_infos.empty())\n\t\t{\n\t\t\tm_queue->Execute(last_queue_family, pack_submit_infos, m_frames[m_current_frame]->AllocateFence());\n\t\t}\n\t\tm_submit_infos.clear();\n\t}\n\n\tif (!m_swapchain->Present(m_render_complete[m_current_frame].get()) ||\n\t    p_window->GetWidth() != m_swapchain->GetWidth() ||\n\t    p_window->GetHeight() != m_swapchain->GetHeight() ||\n\t    m_vsync != m_swapchain->GetVsync())\n\t{\n\t\tm_swapchain->Resize(p_window->GetWidth(), p_window->GetHeight(), m_vsync);\n\t\tLOG_INFO(\"Swapchain resize to {} x {}\", p_window->GetWidth(), p_window->GetHeight());\n\t}\n\n\tm_current_frame = (m_current_frame + 1) % m_swapchain->GetTextureCount();\n}\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIDescriptor.cpp",
    "content": "#include \"RHI/RHIDescriptor.hpp\"\n#include \"RHI/RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIDescriptor::RHIDescriptor(RHIDevice *device, const ShaderMeta &meta) :\n    p_device(device), m_meta(meta)\n{\n}\n\nconst ShaderMeta &RHIDescriptor::GetShaderMeta() const\n{\n\treturn m_meta;\n}\n\nstd::unique_ptr<RHIDescriptor> RHIDescriptor::Create(RHIDevice *device, const ShaderMeta &meta)\n{\n\treturn std::unique_ptr<RHIDescriptor>(std::move(PluginManager::GetInstance().Call<RHIDescriptor *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateDescriptor\", device, meta)));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIDevice.cpp",
    "content": "#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIDevice::RHIDevice(const std::string &backend) :\n    m_backend(backend)\n{\n}\n\nstd::unique_ptr<RHIDevice> RHIDevice::Create(const std::string &backend)\n{\n\treturn std::unique_ptr<RHIDevice>(std::move(PluginManager::GetInstance().Call<RHIDevice *>(fmt::format(\"shared/RHI/RHI.{}.dll\", backend), \"CreateDevice\")));\n}\n\nconst std::string &RHIDevice::GetName() const\n{\n\treturn m_name;\n}\n\nconst std::string RHIDevice::GetBackend() const\n{\n\treturn m_backend;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIFrame.cpp",
    "content": "#include \"RHIFrame.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIFrame::RHIFrame(RHIDevice *device) :\n    p_device(device)\n{\n}\n\nstd::unique_ptr<RHIFrame> RHIFrame::Create(RHIDevice *device)\n{\n\treturn std::unique_ptr<RHIFrame>(std::move(PluginManager::GetInstance().Call<RHIFrame *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateFrame\", device)));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIPipelineState.cpp",
    "content": "#include \"RHIPipelineState.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Hash.hpp>\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIPipelineState::RHIPipelineState(RHIDevice *device) :\n    p_device(device)\n{\n}\n\nstd::unique_ptr<RHIPipelineState> RHIPipelineState::Create(RHIDevice *device)\n{\n\treturn std::unique_ptr<RHIPipelineState>(std::move(PluginManager::GetInstance().Call<RHIPipelineState *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreatePipelineState\", device)));\n}\n\nRHIPipelineState &RHIPipelineState::SetShader(RHIShaderStage stage, RHIShader *shader)\n{\n\tm_shaders.emplace_back(std::make_pair(stage, shader));\n\tm_dirty = true;\n\treturn *this;\n}\n\nRHIPipelineState &RHIPipelineState::SetDepthStencilState(const DepthStencilState &state)\n{\n\tif (m_depth_stencil_state != state)\n\t{\n\t\tm_depth_stencil_state = state;\n\t\tm_dirty               = true;\n\t}\n\treturn *this;\n}\n\nRHIPipelineState &RHIPipelineState::SetBlendState(const BlendState &state)\n{\n\tif (m_blend_state != state)\n\t{\n\t\tm_blend_state = state;\n\t\tm_dirty       = true;\n\t}\n\treturn *this;\n}\n\nRHIPipelineState &RHIPipelineState::SetRasterizationState(const RasterizationState &state)\n{\n\tif (m_rasterization_state != state)\n\t{\n\t\tm_rasterization_state = state;\n\t\tm_dirty               = true;\n\t}\n\treturn *this;\n}\n\nRHIPipelineState &RHIPipelineState::SetMultisampleState(const MultisampleState &state)\n{\n\tif (m_multisample_state != state)\n\t{\n\t\tm_multisample_state = state;\n\t\tm_dirty             = true;\n\t}\n\treturn *this;\n}\n\nRHIPipelineState &RHIPipelineState::SetVertexInputState(const VertexInputState &state)\n{\n\tif (m_vertex_input_state != state)\n\t{\n\t\tm_vertex_input_state = state;\n\t\tm_dirty              = true;\n\t}\n\treturn *this;\n}\n\nRHIPipelineState &RHIPipelineState::SetInputAssemblyState(const InputAssemblyState &state)\n{\n\tif (m_input_assembly_state != state)\n\t{\n\t\tm_input_assembly_state = state;\n\t\tm_dirty                = true;\n\t}\n\treturn *this;\n}\n\nRHIPipelineState& RHIPipelineState::ClearShader()\n{\n\tm_shaders.clear();\n\treturn *this;\n}\n\nconst std::vector<std::pair<RHIShaderStage, RHIShader *>> &RHIPipelineState::GetShaders() const\n{\n\treturn m_shaders;\n}\n\nconst DepthStencilState &RHIPipelineState::GetDepthStencilState() const\n{\n\treturn m_depth_stencil_state;\n}\n\nconst BlendState &RHIPipelineState::GetBlendState() const\n{\n\treturn m_blend_state;\n}\n\nconst RasterizationState &RHIPipelineState::GetRasterizationState() const\n{\n\treturn m_rasterization_state;\n}\n\nconst MultisampleState &RHIPipelineState::GetMultisampleState() const\n{\n\treturn m_multisample_state;\n}\n\nconst VertexInputState &RHIPipelineState::GetVertexInputState() const\n{\n\treturn m_vertex_input_state;\n}\n\nconst InputAssemblyState &RHIPipelineState::GetInputAssemblyState() const\n{\n\treturn m_input_assembly_state;\n}\n\nsize_t RHIPipelineState::GetHash()\n{\n\tif (m_dirty)\n\t{\n\t\tm_hash = 0;\n\n\t\t// Hash Shader\n\t\tfor (auto &[stage, shader] : m_shaders)\n\t\t{\n\t\t\tHashCombine(m_hash, stage, shader);\n\t\t}\n\n\t\t// Hash Depth Stencil State\n\t\tHashCombine(m_hash,\n\t\t            m_depth_stencil_state.compare,\n\t\t            m_depth_stencil_state.depth_test_enable,\n\t\t            m_depth_stencil_state.depth_write_enable);\n\n\t\t// Hash Blend State\n\t\tHashCombine(m_hash, m_blend_state.enable, m_blend_state.logic_op);\n\t\tfor (auto &attachment_state : m_blend_state.attachment_states)\n\t\t{\n\t\t\tHashCombine(m_hash,\n\t\t\t            attachment_state.blend_enable,\n\t\t\t            attachment_state.src_color_blend,\n\t\t\t            attachment_state.dst_color_blend,\n\t\t\t            attachment_state.color_blend_op,\n\t\t\t            attachment_state.color_write_mask,\n\t\t\t            attachment_state.src_alpha_blend,\n\t\t\t            attachment_state.dst_alpha_blend,\n\t\t\t            attachment_state.alpha_blend_op);\n\t\t}\n\n\t\t// Hash Rasterization State\n\t\tHashCombine(m_hash,\n\t\t            m_rasterization_state.cull_mode,\n\t\t            m_rasterization_state.front_face,\n\t\t            m_rasterization_state.polygon_mode,\n\t\t            m_rasterization_state.depth_bias_enable,\n\t\t            m_rasterization_state.depth_clamp_enable,\n\t\t            m_rasterization_state.depth_bias,\n\t\t            m_rasterization_state.depth_bias_clamp,\n\t\t            m_rasterization_state.depth_bias_slope);\n\n\t\t// Hash Multisample State\n\t\tHashCombine(m_hash,\n\t\t            m_multisample_state.enable,\n\t\t            m_multisample_state.samples,\n\t\t            m_multisample_state.sample_mask);\n\n\t\t// Hash Vertex Input State\n\t\tfor (auto &input_attribute : m_vertex_input_state.input_attributes)\n\t\t{\n\t\t\tHashCombine(m_hash,\n\t\t\t            input_attribute.location,\n\t\t\t            input_attribute.binding,\n\t\t\t            input_attribute.format,\n\t\t\t            input_attribute.offset);\n\t\t}\n\n\t\t// Hash Input Assembly State\n\t\tHashCombine(m_hash, m_input_assembly_state.topology);\n\n\t\tm_dirty = false;\n\t}\n\treturn m_hash;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIProfiler.cpp",
    "content": "#include \"RHIProfiler.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIProfiler::RHIProfiler(RHIDevice *device, uint32_t frame_count) :\n    p_device(device), m_frame_count(frame_count)\n{\n}\n\nstd::unique_ptr<RHIProfiler> RHIProfiler::Create(RHIDevice *device, uint32_t frame_count)\n{\n\treturn std::unique_ptr<RHIProfiler>(std::move(PluginManager::GetInstance().Call<RHIProfiler *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateProfiler\", device, frame_count)));\n}\n\nconst ProfileState &RHIProfiler::GetProfileState() const\n{\n\treturn m_state;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIQueue.cpp",
    "content": "#include \"RHIQueue.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIQueue::RHIQueue(RHIDevice *device)\n{\n}\n\nstd::unique_ptr<RHIQueue> RHIQueue::Create(RHIDevice *device)\n{\n\treturn std::unique_ptr<RHIQueue>(std::move(PluginManager::GetInstance().Call<RHIQueue *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateQueue\", device)));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIRenderTarget.cpp",
    "content": "#include \"RHIRenderTarget.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIRenderTarget::RHIRenderTarget(RHIDevice *device) :\n    p_device(device)\n{\n}\n\nstd::unique_ptr<RHIRenderTarget> RHIRenderTarget::Create(RHIDevice *device)\n{\n\treturn std::unique_ptr<RHIRenderTarget>(std::move(PluginManager::GetInstance().Call<RHIRenderTarget *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateRenderTarget\", device)));\n}\n\nuint32_t RHIRenderTarget::GetWidth() const\n{\n\treturn m_width;\n}\n\nuint32_t RHIRenderTarget::GetHeight() const\n{\n\treturn m_height;\n}\n\nuint32_t RHIRenderTarget::GetLayers() const\n{\n\treturn m_layers;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHISampler.cpp",
    "content": "#include \"RHISampler.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nSamplerDesc SamplerDesc::LinearClamp()\n{\n\treturn SamplerDesc{\n\t    RHIFilter::Linear,\n\t    RHIFilter::Linear,\n\t    RHIAddressMode::Clamp_To_Edge,\n\t    RHIAddressMode::Clamp_To_Edge,\n\t    RHIAddressMode::Clamp_To_Edge,\n\t    RHIMipmapMode::Linear};\n}\n\nSamplerDesc SamplerDesc::LinearWarp()\n{\n\treturn SamplerDesc{\n\t    RHIFilter::Linear,\n\t    RHIFilter::Linear,\n\t    RHIAddressMode::Repeat,\n\t    RHIAddressMode::Repeat,\n\t    RHIAddressMode::Repeat,\n\t    RHIMipmapMode::Linear};\n}\n\nSamplerDesc SamplerDesc::NearestClamp()\n{\n\treturn SamplerDesc{\n\t    RHIFilter::Nearest,\n\t    RHIFilter::Nearest,\n\t    RHIAddressMode::Clamp_To_Edge,\n\t    RHIAddressMode::Clamp_To_Edge,\n\t    RHIAddressMode::Clamp_To_Edge,\n\t    RHIMipmapMode::Nearest};\n}\n\nSamplerDesc SamplerDesc::NearestWarp()\n{\n\treturn SamplerDesc{\n\t    RHIFilter::Nearest,\n\t    RHIFilter::Nearest,\n\t    RHIAddressMode::Repeat,\n\t    RHIAddressMode::Repeat,\n\t    RHIAddressMode::Repeat,\n\t    RHIMipmapMode::Nearest};\n}\n\nRHISampler::RHISampler(RHIDevice *device, const SamplerDesc &desc) :\n    p_device(device), m_desc(desc)\n{\n}\n\nstd::unique_ptr<RHISampler> RHISampler::Create(RHIDevice *device, const SamplerDesc &desc)\n{\n\treturn std::unique_ptr<RHISampler>(std::move(PluginManager::GetInstance().Call<RHISampler *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateSampler\", device, desc)));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHIShader.cpp",
    "content": "#include \"RHIShader.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIShader::RHIShader(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source) :\n    p_device(device), m_entry_point(entry_point)\n{\n}\n\nstd::unique_ptr<RHIShader> RHIShader::Create(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source)\n{\n\treturn std::unique_ptr<RHIShader>(std::move(PluginManager::GetInstance().Call<RHIShader *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateShader\", device, entry_point, source)));\n}\n\nconst std::string &RHIShader::GetEntryPoint() const\n{\n\treturn m_entry_point;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHISwapchain.cpp",
    "content": "#include \"RHISwapchain.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHISwapchain::RHISwapchain(RHIDevice *device, uint32_t width, uint32_t height, bool vsync) :\n    p_device(device), m_width(width), m_height(height), m_vsync(vsync)\n{\n}\n\nbool RHISwapchain::GetVsync() const\n{\n\treturn m_vsync;\n}\n\nuint32_t RHISwapchain::GetWidth() const\n{\n\treturn m_width;\n}\n\nuint32_t RHISwapchain::GetHeight() const\n{\n\treturn m_height;\n}\n\nstd::unique_ptr<RHISwapchain> RHISwapchain::Create(RHIDevice *device, void *window_handle, uint32_t width, uint32_t height, bool vsync)\n{\n\treturn std::unique_ptr<RHISwapchain>(std::move(PluginManager::GetInstance().Call<RHISwapchain *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateSwapchain\", device, window_handle, width, height, vsync)));\n}\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHISynchronization.cpp",
    "content": "#include \"RHISynchronization.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHIFence::RHIFence(RHIDevice *device) :\n    p_device(device)\n{\n}\n\nstd::unique_ptr<RHIFence> RHIFence::Create(RHIDevice *device)\n{\n\treturn std::unique_ptr<RHIFence>(std::move(PluginManager::GetInstance().Call<RHIFence *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateFence\", device)));\n}\n\nRHISemaphore::RHISemaphore(RHIDevice *device) :\n    p_device(device)\n{\n}\n\nstd::unique_ptr<RHISemaphore> RHISemaphore::Create(RHIDevice *device)\n{\n\treturn std::unique_ptr<RHISemaphore>(std::move(PluginManager::GetInstance().Call<RHISemaphore *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateSemaphore\", device)));\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Private/RHITexture.cpp",
    "content": "#include \"RHITexture.hpp\"\n#include \"RHIDevice.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nRHITexture::RHITexture(RHIDevice *device, const TextureDesc &desc) :\n    p_device(device), m_desc(desc)\n{\n}\n\nconst TextureDesc &RHITexture::GetDesc() const\n{\n\treturn m_desc;\n}\n\nconst std::string RHITexture::GetBackend() const\n{\n\treturn p_device->GetBackend();\n}\n\nstd::unique_ptr<RHITexture> RHITexture::Alias(const TextureDesc &desc)\n{\n\treturn nullptr;\n}\n\nstd::unique_ptr<RHITexture> RHITexture::Create(RHIDevice *device, const TextureDesc &desc)\n{\n\treturn std::unique_ptr<RHITexture>(std::move(PluginManager::GetInstance().Call<RHITexture *>(fmt::format(\"shared/RHI/RHI.{}.dll\", device->GetBackend()), \"CreateTexture\", device, desc)));\n}\n\nstd::unique_ptr<RHITexture> RHITexture::Create2D(RHIDevice *device, uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples)\n{\n\tTextureDesc desc = {};\n\tdesc.width       = width;\n\tdesc.height      = height;\n\tdesc.depth       = 1;\n\tdesc.layers      = 1;\n\tdesc.mips        = mipmap ? static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1 : 1;\n\tdesc.samples     = samples;\n\tdesc.format      = format;\n\tdesc.usage       = usage;\n\n\treturn Create(device, desc);\n}\n\nstd::unique_ptr<RHITexture> RHITexture::Create3D(RHIDevice *device, uint32_t width, uint32_t height, uint32_t depth, RHIFormat format, RHITextureUsage usage)\n{\n\tTextureDesc desc = {};\n\tdesc.width       = width;\n\tdesc.height      = height;\n\tdesc.depth       = depth;\n\tdesc.layers      = 1;\n\tdesc.mips        = 1;\n\tdesc.samples     = 1;\n\tdesc.format      = format;\n\tdesc.usage       = usage;\n\n\treturn Create(device, desc);\n}\n\nstd::unique_ptr<RHITexture> RHITexture::CreateCube(RHIDevice *device, uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap)\n{\n\tTextureDesc desc = {};\n\tdesc.width       = width;\n\tdesc.height      = height;\n\tdesc.depth       = 1;\n\tdesc.layers      = 6;\n\tdesc.mips        = mipmap ? static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1 : 1;\n\tdesc.samples     = 1;\n\tdesc.format      = format;\n\tdesc.usage       = usage;\n\n\treturn Create(device, desc);\n}\n\nstd::unique_ptr<RHITexture> RHITexture::Create2DArray(RHIDevice *device, uint32_t width, uint32_t height, uint32_t layers, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples)\n{\n\tTextureDesc desc = {};\n\tdesc.width       = width;\n\tdesc.height      = height;\n\tdesc.depth       = 1;\n\tdesc.layers      = layers;\n\tdesc.mips        = mipmap ? static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1 : 1;\n\tdesc.samples     = samples;\n\tdesc.format      = format;\n\tdesc.usage       = usage;\n\n\treturn Create(device, desc);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/Fwd.hpp",
    "content": "#pragma once\n\n#include \"RHIDefinitions.hpp\"\n\n#include <Core/Core.hpp>\n#include <Core/Hash.hpp>\n#include <Core/Window.hpp>\n\n#include <array>\n#include <chrono>\n#include <map>\n#include <memory>\n#include <optional>\n#include <string>\n#include <thread>\n#include <unordered_map>\n#include <vector>\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nclass RHIAccelerationStructure;\nclass RHIBuffer;\nclass RHICommand;\nclass RHIDescriptor;\nclass RHIDevice;\nclass RHIFrame;\nclass RHIPipelineState;\nclass RHIProfiler;\nclass RHIQueue;\nclass RHIRenderTarget;\nclass RHISampler;\nclass RHIShader;\nclass RHISwapchain;\nclass RHIFence;\nclass RHISemaphore;\nclass RHITexture;\nstruct ShaderMeta;\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIAccelerationStructure.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nstruct TLASDesc\n{\n\tstruct InstanceInfo\n\t{\n\t\tglm::mat4 transform;\n\t\tuint32_t  material_id;\n\n\t\tRHIAccelerationStructure *blas = nullptr;\n\t};\n\n\tstd::string name;\n\n\tstd::vector<InstanceInfo> instances;\n};\n\nstruct BLASDesc\n{\n\tstd::string name;\n\n\tRHIBuffer *vertex_buffer = nullptr;\n\tRHIBuffer *index_buffer  = nullptr;\n\n\tuint32_t vertices_count  = 0;\n\tuint32_t indices_count   = 0;\n\tuint32_t vertices_offset = 0;\n\tuint32_t indices_offset  = 0;\n};\n\nclass RHIAccelerationStructure\n{\n  public:\n\tRHIAccelerationStructure(RHIDevice *device);\n\n\tvirtual ~RHIAccelerationStructure() = default;\n\n\tstatic std::unique_ptr<RHIAccelerationStructure> Create(RHIDevice *rhi_device);\n\n\tvirtual void Update(RHICommand *cmd_buffer, const TLASDesc &desc) = 0;\n\n\tvirtual void Update(RHICommand *cmd_buffer, const BLASDesc &desc) = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIBuffer.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nSTRUCT(BufferDesc, Enable)\n{\n\tstd::string    name;\n\tRHIBufferUsage usage;\n\tRHIMemoryUsage memory;\n\n\tMETA(Min(1))\n\tsize_t size;\n\n\tMETA(Min(0))\n\tsize_t stride;\n\n\tMETA(Min(0))\n\tsize_t count;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive & archive)\n\t{\n\t\tarchive(name, usage, memory, size, stride, count);\n\t}\n};\n\nclass RHIBuffer\n{\n  public:\n\tRHIBuffer(RHIDevice *device, const BufferDesc &desc);\n\n\tvirtual ~RHIBuffer() = default;\n\n\tconst std::string GetBackend() const;\n\n\tstatic std::unique_ptr<RHIBuffer> Create(RHIDevice *device, const BufferDesc &desc);\n\n\tconst BufferDesc &GetDesc() const;\n\n\tvirtual void CopyToDevice(const void *data, size_t size, size_t offset = 0) = 0;\n\n\tvirtual void CopyToHost(void *data, size_t size, size_t offset = 0) = 0;\n\n\tvirtual void *Map()   = 0;\n\tvirtual void  Unmap() = 0;\n\n\tvirtual void Flush(size_t offset, size_t size) = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n\tBufferDesc m_desc;\n};\n\nstruct BufferStateTransition\n{\n\tRHIBuffer       *buffer;\n\tRHIResourceState src;\n\tRHIResourceState dst;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHICommand.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n#include \"RHIBuffer.hpp\"\n#include \"RHITexture.hpp\"\n\nnamespace Ilum\n{\nenum class CommandState\n{\n\tAvailable,\n\tInitial,\n\tRecording,\n\tExecutable,\n\tPending\n};\n\nstruct RHIDrawIndirectCommand\n{\n\tuint32_t vertex_count;\n\tuint32_t instance_count;\n\tuint32_t vertex_offset;\n\tuint32_t instance_offset;\n};\n\nstruct RHIDrawIndexedIndirectCommand\n{\n\tuint32_t index_count;\n\tuint32_t instance_count;\n\tuint32_t index_offset;\n\tint32_t  vertex_offset;\n\tuint32_t instance_offset;\n};\n\nstruct RHIDispatchIndirectCommand\n{\n\tuint32_t x;\n\tuint32_t y;\n\tuint32_t z;\n};\n\nstruct RHIDrawMeshTasksIndirectCommand\n{\n\tuint32_t group_count_x;\n\tuint32_t group_count_y;\n\tuint32_t group_count_z;\n};\n\nclass RHICommand\n{\n  public:\n\tRHICommand(RHIDevice *device, RHIQueueFamily family);\n\n\tvirtual ~RHICommand() = default;\n\n\tRHIQueueFamily GetQueueFamily() const;\n\n\tconst std::string GetBackend() const;\n\n\tCommandState GetState() const;\n\n\tvoid Init();\n\n\tstatic std::unique_ptr<RHICommand> Create(RHIDevice *device, RHIQueueFamily family);\n\n\tvirtual void SetName(const std::string &name) = 0;\n\n\tvirtual void Begin() = 0;\n\tvirtual void End()   = 0;\n\n\tvirtual void BeginMarker(const std::string &name, float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) = 0;\n\tvirtual void EndMarker()                                                                                      = 0;\n\n\tvirtual void BeginRenderPass(RHIRenderTarget *render_target) = 0;\n\tvirtual void EndRenderPass()                                 = 0;\n\n\tvirtual void BindVertexBuffer(uint32_t binding, RHIBuffer *vertex_buffer)    = 0;\n\tvirtual void BindIndexBuffer(RHIBuffer *index_buffer, bool is_short = false) = 0;\n\n\tvirtual void BindDescriptor(RHIDescriptor *descriptor)           = 0;\n\tvirtual void BindPipelineState(RHIPipelineState *pipeline_state) = 0;\n\n\tvirtual void SetViewport(float width, float height, float x = 0.f, float y = 0.f)                    = 0;\n\tvirtual void SetScissor(uint32_t width, uint32_t height, int32_t offset_x = 0, int32_t offset_y = 0) = 0;\n\n\t// Drawcall\n\tvirtual void Dispatch(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z) = 0;\n\tvirtual void DispatchIndirect(RHIBuffer *buffer, size_t offset)                                                                      = 0;\n\n\tvirtual void Draw(uint32_t vertex_count, uint32_t instance_count = 1, uint32_t first_vertex = 0, uint32_t first_instance = 0)                                   = 0;\n\tvirtual void DrawIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)                                                               = 0;\n\tvirtual void DrawIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) = 0;\n\n\tvirtual void DrawIndexed(uint32_t index_count, uint32_t instance_count = 1, uint32_t first_index = 0, uint32_t vertex_offset = 0, uint32_t first_instance = 0)         = 0;\n\tvirtual void DrawIndexedIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)                                                               = 0;\n\tvirtual void DrawIndexedIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) = 0;\n\n\tvirtual void DrawMeshTask(uint32_t thread_x, uint32_t thread_y, uint32_t thread_z, uint32_t block_x, uint32_t block_y, uint32_t block_z)                                 = 0;\n\tvirtual void DrawMeshTasksIndirect(RHIBuffer *buffer, size_t offset, uint32_t draw_count, uint32_t stride)                                                               = 0;\n\tvirtual void DrawMeshTasksIndirectCount(RHIBuffer *buffer, size_t offset, RHIBuffer *count_buffer, size_t count_buffer_offset, uint32_t max_draw_count, uint32_t stride) = 0;\n\n\t// RayTracing\n\tvirtual void TraceRay(uint32_t width, uint32_t height, uint32_t depth) = 0;\n\n\t// Resource Copy\n\tvirtual void CopyBufferToTexture(RHIBuffer *src_buffer, RHITexture *dst_texture, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count) = 0;\n\tvirtual void CopyTextureToBuffer(RHITexture *src_texture, RHIBuffer *dst_buffer, uint32_t mip_level, uint32_t base_layer, uint32_t layer_count) = 0;\n\tvirtual void CopyBufferToBuffer(RHIBuffer *src_buffer, RHIBuffer *dst_buffer, size_t size, size_t src_offset = 0, size_t dst_offset = 0)        = 0;\n\n\tvirtual void GenerateMipmaps(RHITexture *texture, RHIResourceState initial_state, RHIFilter filter)                                                                                                                                                  = 0;\n\tvirtual void BlitTexture(RHITexture *src_texture, const TextureRange &src_range, const RHIResourceState &src_state, RHITexture *dst_texture, const TextureRange &dst_range, const RHIResourceState &dst_state, RHIFilter filter = RHIFilter::Linear) = 0;\n\n\t// Resource Reset\n\tvirtual void FillBuffer(RHIBuffer *buffer, RHIResourceState state, size_t size, size_t offset = 0, uint32_t data = 0)    = 0;\n\tvirtual void FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, const glm::vec4 &color) = 0;\n\tvirtual void FillTexture(RHITexture *texture, RHIResourceState state, const TextureRange &range, float depth) = 0;\n\n\t// Resource Barrier\n\tvirtual void ResourceStateTransition(const std::vector<TextureStateTransition> &texture_transitions, const std::vector<BufferStateTransition> &buffer_transitions) = 0;\n\n  protected:\n\tRHIDevice     *p_device = nullptr;\n\tRHIQueueFamily m_family;\n\tCommandState   m_state = CommandState::Available;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIContext.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\n#include \"RHIAccelerationStructure.hpp\"\n#include \"RHIBuffer.hpp\"\n#include \"RHICommand.hpp\"\n#include \"RHIDescriptor.hpp\"\n#include \"RHIDevice.hpp\"\n#include \"RHIFrame.hpp\"\n#include \"RHIPipelineState.hpp\"\n#include \"RHIProfiler.hpp\"\n#include \"RHIQueue.hpp\"\n#include \"RHIRenderTarget.hpp\"\n#include \"RHISampler.hpp\"\n#include \"RHIShader.hpp\"\n#include \"RHISwapchain.hpp\"\n#include \"RHISynchronization.hpp\"\n#include \"RHITexture.hpp\"\n\nnamespace Ilum\n{\n#undef CreateSemaphore\n\nclass RHIContext\n{\n  public:\n\tRHIContext(Window *window, const std::string &backend = \"Vulkan\", bool vsync = false);\n\n\t~RHIContext();\n\n\tconst std::string &GetDeviceName() const;\n\n\tconst std::string GetBackend() const;\n\n\tbool HasCUDA() const;\n\n\tbool IsVsync() const;\n\n\tvoid SetVsync(bool vsync);\n\n\tbool IsFeatureSupport(RHIFeature feature) const;\n\n\tvoid WaitIdle() const;\n\n\tRHISwapchain *GetSwapchain() const;\n\n\tstd::unique_ptr<RHISwapchain> CreateSwapchain(void *window_handle, uint32_t width, uint32_t height, bool sync);\n\n\t// Create Texture\n\tstd::unique_ptr<RHITexture> CreateTexture(const TextureDesc &desc);\n\tstd::unique_ptr<RHITexture> CreateTexture2D(uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples = 1);\n\tstd::unique_ptr<RHITexture> CreateTexture3D(uint32_t width, uint32_t height, uint32_t depth, RHIFormat format, RHITextureUsage usage);\n\tstd::unique_ptr<RHITexture> CreateTextureCube(uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap);\n\tstd::unique_ptr<RHITexture> CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples = 1);\n\n\t// Texture Conversion\n\tstd::unique_ptr<RHITexture> MapToCUDATexture(RHITexture *texture);\n\n\t// Create Buffer\n\tstd::unique_ptr<RHIBuffer> CreateBuffer(const BufferDesc &desc);\n\tstd::unique_ptr<RHIBuffer> CreateBuffer(size_t size, RHIBufferUsage usage, RHIMemoryUsage memory);\n\n\ttemplate <typename T>\n\tstd::unique_ptr<RHIBuffer> CreateBuffer(size_t count, RHIBufferUsage usage, RHIMemoryUsage memory)\n\t{\n\t\tBufferDesc desc = {};\n\t\tdesc.count      = count;\n\t\tdesc.stride     = sizeof(T);\n\t\tdesc.usage      = usage;\n\t\tdesc.memory     = memory;\n\t\tdesc.size       = desc.count * desc.stride;\n\n\t\treturn CreateBuffer(desc);\n\t}\n\n\t// Buffer Conversion\n\tstd::unique_ptr<RHIBuffer> MapToCUDABuffer(RHIBuffer *buffer);\n\n\t// Create Sampler\n\tRHISampler *CreateSampler(const SamplerDesc &desc);\n\n\tuint32_t GetSamplerIndex(const SamplerDesc &desc);\n\n\tstd::vector<RHISampler *> GetSamplers() const;\n\n\tsize_t GetSamplerCount() const;\n\n\t// Create Command\n\tRHICommand *CreateCommand(RHIQueueFamily family, bool cuda = false);\n\n\t// Create Descriptor\n\tRHIDescriptor *CreateDescriptor(const ShaderMeta &meta, bool cuda = false);\n\n\t// Create PipelineState\n\tstd::unique_ptr<RHIPipelineState> CreatePipelineState(bool cuda = false);\n\n\t// Create Shader\n\tstd::unique_ptr<RHIShader> CreateShader(const std::string &entry_point, const std::vector<uint8_t> &source, bool cuda = false);\n\n\t// Create Render Target\n\tstd::unique_ptr<RHIRenderTarget> CreateRenderTarget(bool cuda = false);\n\n\t// Create Profiler\n\tstd::unique_ptr<RHIProfiler> CreateProfiler(bool cuda = false);\n\n\t// Create Fence\n\tstd::unique_ptr<RHIFence> CreateFence();\n\n\t// Create Fence that will reset every frame\n\tRHIFence *CreateFrameFence();\n\n\t// Create Semaphore\n\tstd::unique_ptr<RHISemaphore> CreateSemaphore(bool cuda = false);\n\n\t// Create Frame Semaphore\n\tRHISemaphore *CreateFrameSemaphore();\n\n\tstd::unique_ptr<RHISemaphore> MapToCUDASemaphore(RHISemaphore *semaphore);\n\n\t// Create Acceleration Structure\n\tstd::unique_ptr<RHIAccelerationStructure> CreateAcccelerationStructure();\n\n\t// Submit command buffer\n\tvoid Submit(std::vector<RHICommand *> &&cmd_buffers, std::vector<RHISemaphore *> &&wait_semaphores = {}, std::vector<RHISemaphore *> &&signal_semaphores = {});\n\n\t// Execute immediate command buffer\n\tvoid Execute(RHICommand *cmd_buffer);\n\n\tvoid Execute(std::vector<RHICommand *> &&cmd_buffers, std::vector<RHISemaphore *> &&wait_semaphores, std::vector<RHISemaphore *> &&signal_semaphores, RHIFence *fence = nullptr);\n\n\tvoid Reset();\n\n\t// Get Back Buffer\n\tRHITexture *GetBackBuffer();\n\n\t// Frame\n\tvoid BeginFrame();\n\n\tvoid EndFrame();\n\n  private:\n\tuint32_t m_current_frame = 0;\n\tbool     m_vsync         = false;\n\n  private:\n\tWindow *p_window = nullptr;\n\n\tstd::unique_ptr<RHIDevice> m_device      = nullptr;\n\tstd::unique_ptr<RHIDevice> m_cuda_device = nullptr;\n\n\tstd::unique_ptr<RHISwapchain> m_swapchain = nullptr;\n\n\tstd::unique_ptr<RHIQueue> m_queue      = nullptr;\n\tstd::unique_ptr<RHIQueue> m_cuda_queue = nullptr;\n\n\tstd::vector<std::unique_ptr<RHISemaphore>> m_present_complete;\n\tstd::vector<std::unique_ptr<RHISemaphore>> m_render_complete;\n\n\tstd::vector<std::unique_ptr<RHIFrame>> m_frames;\n\tstd::vector<std::unique_ptr<RHIFrame>> m_cuda_frames;\n\n\tstd::vector<SubmitInfo> m_submit_infos;\n\n\tstd::vector<std::unique_ptr<RHISampler>> m_samplers;\n\tstd::unordered_map<size_t, size_t>       m_sampler_lookup;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIDefinitions.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\nnamespace Ilum\n{\nENUM(RHIShaderStage, Enable){\n    Vertex                 = 1,\n    TessellationControl    = 1 << 1,\n    TessellationEvaluation = 1 << 2,\n    Geometry               = 1 << 3,\n    Fragment               = 1 << 4,\n    Compute                = 1 << 5,\n    RayGen                 = 1 << 6,\n    AnyHit                 = 1 << 7,\n    ClosestHit             = 1 << 8,\n    Miss                   = 1 << 9,\n    Intersection           = 1 << 10,\n    Callable               = 1 << 11,\n    Mesh                   = 1 << 12,\n    Task                   = 1 << 13};\n\nDEFINE_ENUMCLASS_OPERATION(RHIShaderStage);\n\nENUM(RHIFeature, Enable){\n    RayTracing,\n    MeshShading,\n    BufferDeviceAddress,\n    Bindless};\n\nENUM(RHIQueueFamily, Enable){\n    Graphics,\n    Compute,\n    Transfer};\n\nENUM(RHIFormat, Enable){\n    Undefined          = 0,\n    R16_UINT           = 1,\n    R16_SINT           = 1 << 1,\n    R16_FLOAT          = 1 << 2,\n    R8G8B8A8_UNORM     = 1 << 3,\n    B8G8R8A8_UNORM     = 1 << 4,\n    R32_UINT           = 1 << 5,\n    R32_SINT           = 1 << 6,\n    R32_FLOAT          = 1 << 7,\n    D32_FLOAT          = 1 << 8,\n    D24_UNORM_S8_UINT  = 1 << 9,\n    R16G16_UINT        = 1 << 10,\n    R16G16_SINT        = 1 << 11,\n    R16G16_FLOAT       = 1 << 12,\n    R10G10B10A2_UNORM  = 1 << 13,\n    R10G10B10A2_UINT   = 1 << 14,\n    R11G11B10_FLOAT    = 1 << 15,\n    R16G16B16A16_UINT  = 1 << 16,\n    R16G16B16A16_SINT  = 1 << 17,\n    R16G16B16A16_FLOAT = 1 << 18,\n    R32G32_UINT        = 1 << 19,\n    R32G32_SINT        = 1 << 20,\n    R32G32_FLOAT       = 1 << 21,\n    R32G32B32_UINT     = 1 << 22,\n    R32G32B32_SINT     = 1 << 23,\n    R32G32B32_FLOAT    = 1 << 24,\n    R32G32B32A32_UINT  = 1 << 25,\n    R32G32B32A32_SINT  = 1 << 26,\n    R32G32B32A32_FLOAT = 1 << 27,\n};\n\nDEFINE_ENUMCLASS_OPERATION(RHIFormat);\n\ninline uint32_t GetFormatStride(RHIFormat format)\n{\n\tswitch (format)\n\t{\n\t\tcase RHIFormat::Undefined:\n\t\t\treturn 0;\n\t\tcase RHIFormat::R16_UINT:\n\t\tcase RHIFormat::R16_SINT:\n\t\tcase RHIFormat::R16_FLOAT:\n\t\t\treturn 2;\n\t\tcase RHIFormat::R32_UINT:\n\t\tcase RHIFormat::R32_SINT:\n\t\tcase RHIFormat::R32_FLOAT:\n\t\tcase RHIFormat::D32_FLOAT:\n\t\tcase RHIFormat::R16G16_UINT:\n\t\tcase RHIFormat::R16G16_SINT:\n\t\tcase RHIFormat::R16G16_FLOAT:\n\t\tcase RHIFormat::R8G8B8A8_UNORM:\n\t\tcase RHIFormat::B8G8R8A8_UNORM:\n\t\tcase RHIFormat::D24_UNORM_S8_UINT:\n\t\tcase RHIFormat::R10G10B10A2_UNORM:\n\t\tcase RHIFormat::R10G10B10A2_UINT:\n\t\tcase RHIFormat::R11G11B10_FLOAT:\n\t\t\treturn 4;\n\t\tcase RHIFormat::R16G16B16A16_UINT:\n\t\tcase RHIFormat::R16G16B16A16_SINT:\n\t\tcase RHIFormat::R16G16B16A16_FLOAT:\n\t\tcase RHIFormat::R32G32_UINT:\n\t\tcase RHIFormat::R32G32_SINT:\n\t\tcase RHIFormat::R32G32_FLOAT:\n\t\t\treturn 8;\n\t\tcase RHIFormat::R32G32B32_UINT:\n\t\tcase RHIFormat::R32G32B32_SINT:\n\t\tcase RHIFormat::R32G32B32_FLOAT:\n\t\t\treturn 12;\n\t\tcase RHIFormat::R32G32B32A32_UINT:\n\t\tcase RHIFormat::R32G32B32A32_SINT:\n\t\tcase RHIFormat::R32G32B32A32_FLOAT:\n\t\t\treturn 16;\n\t\tdefault:\n\t\t\treturn 0;\n\t}\n}\n\ninline bool IsDepthFormat(RHIFormat format)\n{\n\treturn format == RHIFormat::D32_FLOAT ||\n\t       format == RHIFormat::D24_UNORM_S8_UINT;\n}\n\ninline bool IsStencilFormat(RHIFormat format)\n{\n\treturn format == RHIFormat::D24_UNORM_S8_UINT;\n}\n\nENUM(RHIVertexSemantics, Enable){\n    Binormal,\n    Blend_Indices,\n    Blend_Weights,\n    Color,\n    Normal,\n    Position,\n    Tangent,\n    Texcoord};\n\nENUM(RHIMemoryUsage, Enable){\n    GPU_Only,\n    CPU_TO_GPU,\n    GPU_TO_CPU};\n\n// Texture\nENUM(RHITextureDimension, Enable) :\n    uint64_t{\n        Texture1D        = 1,\n        Texture2D        = 1 << 1,\n        Texture3D        = 1 << 2,\n        TextureCube      = 1 << 3,\n        Texture1DArray   = 1 << 4,\n        Texture2DArray   = 1 << 5,\n        TextureCubeArray = 1 << 6,\n    };\n\ninline RHITextureDimension GetTextureDimension(uint32_t width, uint32_t height, uint32_t depth, uint32_t layers)\n{\n\tif (layers == 1)\n\t{\n\t\tif (depth == 1)\n\t\t{\n\t\t\tif (height == 1)\n\t\t\t{\n\t\t\t\treturn RHITextureDimension::Texture1D;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn RHITextureDimension::Texture2D;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn RHITextureDimension::Texture3D;\n\t\t}\n\t}\n\n\tif (layers == 6)\n\t{\n\t\treturn RHITextureDimension::TextureCube;\n\t}\n\n\tif (layers % 6 == 0)\n\t{\n\t\treturn RHITextureDimension::TextureCubeArray;\n\t}\n\n\tif (height == 1)\n\t{\n\t\treturn RHITextureDimension::Texture1DArray;\n\t}\n\telse\n\t{\n\t\treturn RHITextureDimension::Texture2DArray;\n\t}\n}\n\n// Buffer\nENUM(RHIBufferUsage, Enable){\n    Undefined             = 0,\n    Vertex                = 1,\n    Index                 = 1 << 1,\n    Indirect              = 1 << 2,\n    Transfer              = 1 << 3,\n    AccelerationStructure = 1 << 4,\n    ShaderResource        = 1 << 5,\n    UnorderedAccess       = 1 << 6,\n    ConstantBuffer        = 1 << 7};\nDEFINE_ENUMCLASS_OPERATION(RHIBufferUsage);\n\nENUM(RHITextureUsage, Enable){\n    Undefined       = 0,\n    Transfer        = 1,\n    ShaderResource  = 1 << 1,\n    UnorderedAccess = 1 << 2,\n    RenderTarget    = 1 << 3};\n\nDEFINE_ENUMCLASS_OPERATION(RHITextureUsage);\n\nENUM(RHIResourceState, Enable){\n    Undefined,\n    VertexBuffer,\n    ConstantBuffer,\n    IndexBuffer,\n    IndirectBuffer,\n    TransferSource,\n    TransferDest,\n    ShaderResource,\n    UnorderedAccess,\n    RenderTarget,\n    DepthWrite,\n    DepthRead,\n    AccelerationStructure,\n    Present};\n\ninline RHITextureUsage ResourceStateToTextureUsage(RHIResourceState state)\n{\n\tswitch (state)\n\t{\n\t\tcase RHIResourceState::TransferSource:\n\t\tcase RHIResourceState::TransferDest:\n\t\t\treturn RHITextureUsage::Transfer;\n\t\tcase RHIResourceState::ShaderResource:\n\t\t\treturn RHITextureUsage::ShaderResource;\n\t\tcase RHIResourceState::UnorderedAccess:\n\t\t\treturn RHITextureUsage::UnorderedAccess;\n\t\tcase RHIResourceState::RenderTarget:\n\t\tcase RHIResourceState::DepthWrite:\n\t\t\treturn RHITextureUsage::RenderTarget;\n\t\tcase RHIResourceState::DepthRead:\n\t\t\treturn RHITextureUsage::ShaderResource;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn RHITextureUsage::Undefined;\n}\n\ninline RHIBufferUsage ResourceStateToBufferUsage(RHIResourceState state)\n{\n\tswitch (state)\n\t{\n\t\tcase RHIResourceState::VertexBuffer:\n\t\t\treturn RHIBufferUsage::Vertex;\n\t\tcase RHIResourceState::ConstantBuffer:\n\t\t\treturn RHIBufferUsage::ConstantBuffer;\n\t\tcase RHIResourceState::IndexBuffer:\n\t\t\treturn RHIBufferUsage::Index;\n\t\tcase RHIResourceState::IndirectBuffer:\n\t\tcase RHIResourceState::TransferSource:\n\t\tcase RHIResourceState::TransferDest:\n\t\t\treturn RHIBufferUsage::Transfer;\n\t\tcase RHIResourceState::ShaderResource:\n\t\t\treturn RHIBufferUsage::ShaderResource;\n\t\tcase RHIResourceState::UnorderedAccess:\n\t\t\treturn RHIBufferUsage::UnorderedAccess;\n\t\tcase RHIResourceState::AccelerationStructure:\n\t\t\treturn RHIBufferUsage::AccelerationStructure;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn RHIBufferUsage::Undefined;\n}\n\n// Sampler\nENUM(RHIFilter, Enable){\n    Nearest,\n    Linear};\n\nENUM(RHIAddressMode, Enable){\n    Repeat,\n    Mirrored_Repeat,\n    Clamp_To_Edge,\n    Clamp_To_Border,\n    Mirror_Clamp_To_Edge};\n\nENUM(RHIMipmapMode, Enable){\n    Nearest,\n    Linear};\n\nENUM(RHISamplerBorderColor, Enable){\n    Float_Transparent_Black,\n    Int_Transparent_Black,\n    Float_Opaque_Black,\n    Int_Opaque_Black,\n    Float_Opaque_White,\n    Int_Opaque_White};\n\n// Pipeline State\nENUM(RHICompareOp, Enable){\n    Never,\n    Less,\n    Equal,\n    Less_Or_Equal,\n    Greater,\n    Not_Equal,\n    Greater_Or_Equal,\n    Always};\n\nENUM(RHILogicOp, Enable){\n    Clear,\n    And,\n    And_Reverse,\n    Copy,\n    And_Inverted,\n    No_Op,\n    XOR,\n    Or,\n    Nor,\n    Equivalent,\n    Invert,\n    Or_Reverse,\n    Copy_Inverted,\n    Or_Inverted,\n    Nand,\n    Set};\n\nENUM(RHIBlendFactor, Enable){\n    Zero,\n    One,\n    Src_Color,\n    One_Minus_Src_Color,\n    Dst_Color,\n    One_Minus_Dst_Color,\n    Src_Alpha,\n    One_Minus_Src_Alpha,\n    Dst_Alpha,\n    One_Minus_Dst_Alpha,\n    Constant_Color,\n    One_Minus_Constant_Color,\n    Constant_Alpha,\n    One_Minus_Constant_Alpha,\n    Src_Alpha_Saturate,\n    Src1_Color,\n    One_Minus_Src1_Color,\n    Src1_Alpha,\n    One_Minus_Src1_Alpha};\n\nENUM(RHIBlendOp, Enable){\n    Add,\n    Subtract,\n    Reverse_Subtract,\n    Min,\n    Max};\n\nENUM(RHICullMode, Enable){\n    None,\n    Front,\n    Back};\n\nENUM(RHIFrontFace, Enable){\n    Counter_Clockwise,\n    Clockwise};\n\nENUM(RHIPolygonMode, Enable){\n    Wireframe,\n    Solid};\n\nENUM(RHIPrimitiveTopology, Enable){\n    Point,\n    Line,\n    Triangle,\n    Patch};\n\nENUM(RHIVertexInputRate, Enable){\n    Vertex,\n    Instance};\n\nENUM(RHILoadAction, Enable){\n    DontCare,\n    Load,\n    Clear};\n\nENUM(RHIStoreAction, Enable){\n    DontCare,\n    Store};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIDescriptor.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n#include \"RHIShader.hpp\"\n#include \"RHITexture.hpp\"\n\nnamespace Ilum\n{\nclass RHIDescriptor\n{\n  public:\n\tRHIDescriptor(RHIDevice *device, const ShaderMeta &meta);\n\n\tvirtual ~RHIDescriptor() = default;\n\n\tconst ShaderMeta &GetShaderMeta() const;\n\n\tstatic std::unique_ptr<RHIDescriptor> Create(RHIDevice *device, const ShaderMeta &meta);\n\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, RHITexture *texture, RHITextureDimension dimension)                       = 0;\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, RHITexture *texture, const TextureRange &range)                           = 0;\n\tvirtual RHIDescriptor &BindTexture(const std::string &name, const std::vector<RHITexture *> &textures, RHITextureDimension dimension) = 0;\n\n\tvirtual RHIDescriptor &BindSampler(const std::string &name, RHISampler *sampler)                       = 0;\n\tvirtual RHIDescriptor &BindSampler(const std::string &name, const std::vector<RHISampler *> &samplers) = 0;\n\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, RHIBuffer *buffer)                              = 0;\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, RHIBuffer *buffer, size_t offset, size_t range) = 0;\n\tvirtual RHIDescriptor &BindBuffer(const std::string &name, const std::vector<RHIBuffer *> &buffers)        = 0;\n\n\tvirtual RHIDescriptor &BindConstant(const std::string &name, const void *constant) = 0;\n\n\ttemplate <typename T>\n\tRHIDescriptor &SetConstant(const std::string &name, const T &constant)\n\t{\n\t\treturn BindConstant(name, &constant);\n\t}\n\n\tvirtual RHIDescriptor &BindAccelerationStructure(const std::string &name, RHIAccelerationStructure *acceleration_structure) = 0;\n\n  protected:\n\tRHIDevice       *p_device = nullptr;\n\tconst ShaderMeta m_meta;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIDevice.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nclass RHIDevice\n{\n  public:\n\tRHIDevice(const std::string &backend = \"Vulkan\");\n\n\tvirtual ~RHIDevice() = default;\n\n\tstatic std::unique_ptr<RHIDevice> Create(const std::string &backend = \"Vulkan\");\n\n\tconst std::string &GetName() const;\n\n\tconst std::string GetBackend() const;\n\n\tvirtual void WaitIdle() = 0;\n\n\tvirtual bool IsFeatureSupport(RHIFeature feature) = 0;\n\n  protected:\n\tconst std::string m_backend;\n\tstd::string m_name;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIFrame.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nstruct ShaderMeta;\n\nclass RHIFrame\n{\n  public:\n\tRHIFrame(RHIDevice *device);\n\n\tvirtual ~RHIFrame() = default;\n\n\tstatic std::unique_ptr<RHIFrame> Create(RHIDevice *device);\n\n\tvirtual RHIFence *AllocateFence() = 0;\n\n\tvirtual RHISemaphore *AllocateSemaphore() = 0;\n\n\tvirtual RHICommand *AllocateCommand(RHIQueueFamily family) = 0;\n\n\tvirtual RHIDescriptor *AllocateDescriptor(const ShaderMeta &meta) = 0;\n\n\tvirtual void Reset() = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIPipelineState.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nstruct DepthStencilState\n{\n\tbool depth_test_enable  = true;\n\tbool depth_write_enable = true;\n\n\tRHICompareOp compare = RHICompareOp::Less_Or_Equal;\n\t// TODO: Stencil Test\n\n\tinline bool operator==(const DepthStencilState &state) const\n\t{\n\t\treturn depth_test_enable == state.depth_test_enable &&\n\t\t       depth_write_enable == state.depth_write_enable &&\n\t\t       compare == state.compare;\n\t}\n\n\tinline bool operator!=(const DepthStencilState &state) const\n\t{\n\t\treturn !(*this == state);\n\t}\n};\n\nstruct BlendState\n{\n\tbool                 enable          = false;\n\tRHILogicOp           logic_op        = RHILogicOp::Or;\n\tstd::array<float, 4> blend_constants = {0.f};\n\n\tstruct AttachmentState\n\t{\n\t\tbool           blend_enable     = false;\n\t\tRHIBlendFactor src_color_blend  = RHIBlendFactor::Src_Alpha;\n\t\tRHIBlendFactor dst_color_blend  = RHIBlendFactor::One_Minus_Src_Alpha;\n\t\tRHIBlendOp     color_blend_op   = RHIBlendOp::Add;\n\t\tRHIBlendFactor src_alpha_blend  = RHIBlendFactor::One;\n\t\tRHIBlendFactor dst_alpha_blend  = RHIBlendFactor::Zero;\n\t\tRHIBlendOp     alpha_blend_op   = RHIBlendOp::Add;\n\t\tuint8_t        color_write_mask = 1 | 2 | 4 | 8;\n\n\t\tinline bool operator==(const AttachmentState &state) const\n\t\t{\n\t\t\treturn blend_enable == state.blend_enable &&\n\t\t\t       src_color_blend == state.src_color_blend &&\n\t\t\t       dst_color_blend == state.dst_color_blend &&\n\t\t\t       color_blend_op == state.color_blend_op &&\n\t\t\t       src_alpha_blend == state.src_alpha_blend &&\n\t\t\t       dst_alpha_blend == state.dst_alpha_blend &&\n\t\t\t       alpha_blend_op == state.alpha_blend_op &&\n\t\t\t       color_write_mask == state.color_write_mask;\n\t\t}\n\t\tinline bool operator!=(const AttachmentState &state) const\n\t\t{\n\t\t\treturn !(*this == state);\n\t\t}\n\t};\n\n\tstd::vector<AttachmentState> attachment_states;\n\n\tinline bool operator==(const BlendState &state) const\n\t{\n\t\tif (enable != state.enable ||\n\t\t    logic_op != state.logic_op ||\n\t\t    blend_constants[0] != state.blend_constants[0] ||\n\t\t    blend_constants[1] != state.blend_constants[1] ||\n\t\t    blend_constants[2] != state.blend_constants[2] ||\n\t\t    blend_constants[3] != state.blend_constants[3])\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tif (attachment_states.size() == state.attachment_states.size())\n\t\t{\n\t\t\tfor (uint32_t i = 0; i < attachment_states.size(); i++)\n\t\t\t{\n\t\t\t\tif (attachment_states[i] != state.attachment_states[i])\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tinline bool operator!=(const BlendState &state) const\n\t{\n\t\treturn !(*this == state);\n\t}\n};\n\nstruct RasterizationState\n{\n\tRHICullMode    cull_mode         = RHICullMode::Back;\n\tRHIFrontFace   front_face        = RHIFrontFace::Counter_Clockwise;\n\tRHIPolygonMode polygon_mode      = RHIPolygonMode::Solid;\n\tbool           depth_bias_enable = false;\n\tbool           depth_clamp_enable  = false;\n\tfloat          line_width        = 1.f;\n\tfloat          depth_bias        = 0.f;\n\tfloat          depth_bias_clamp  = 0.f;\n\tfloat          depth_bias_slope  = 0.f;\n\n\tinline bool operator==(const RasterizationState &state) const\n\t{\n\t\treturn cull_mode == state.cull_mode &&\n\t\t       front_face == state.front_face &&\n\t\t       polygon_mode == state.polygon_mode &&\n\t\t       line_width == state.line_width &&\n\t\t       depth_bias_enable == state.depth_bias_enable &&\n\t\t       depth_clamp_enable == state.depth_clamp_enable &&\n\t\t       depth_bias == state.depth_bias &&\n\t\t       depth_bias_clamp == state.depth_bias_clamp &&\n\t\t       depth_bias_slope == state.depth_bias_slope;\n\t}\n\tinline bool operator!=(const RasterizationState &state) const\n\t{\n\t\treturn !(*this == state);\n\t}\n};\n\nstruct MultisampleState\n{\n\tbool     enable      = false;\n\tuint32_t samples     = 1;\n\tuint32_t sample_mask = 0;\n\n\tinline bool operator==(const MultisampleState &state) const\n\t{\n\t\treturn enable == state.enable &&\n\t\t       samples == state.samples &&\n\t\t       sample_mask == state.sample_mask;\n\t}\n\tinline bool operator!=(const MultisampleState &state) const\n\t{\n\t\treturn !(*this == state);\n\t}\n};\n\nstruct VertexInputState\n{\n\tstruct InputBinding\n\t{\n\t\tuint32_t           binding;\n\t\tuint32_t           stride;\n\t\tRHIVertexInputRate rate;\n\n\t\tinline bool operator==(const InputBinding &desc) const\n\t\t{\n\t\t\treturn binding == desc.binding &&\n\t\t\t       stride == desc.stride &&\n\t\t\t       rate == desc.rate;\n\t\t}\n\t\tinline bool operator!=(const InputBinding &state) const\n\t\t{\n\t\t\treturn !(*this == state);\n\t\t}\n\t};\n\n\tstruct InputAttribute\n\t{\n\t\tRHIVertexSemantics semantics;\n\t\tuint32_t           location;\n\t\tuint32_t           binding;\n\t\tRHIFormat          format;\n\t\tuint32_t           offset;\n\n\t\tinline bool operator==(const InputAttribute &desc) const\n\t\t{\n\t\t\treturn semantics == desc.semantics &&\n\t\t\t       location == desc.location &&\n\t\t\t       binding == desc.binding &&\n\t\t\t       format == desc.format &&\n\t\t\t       offset == desc.offset;\n\t\t}\n\t\tinline bool operator!=(const InputAttribute &state) const\n\t\t{\n\t\t\treturn !(*this == state);\n\t\t}\n\t};\n\n\tstd::vector<InputAttribute> input_attributes;\n\tstd::vector<InputBinding>   input_bindings;\n\n\tinline bool operator==(const VertexInputState &state) const\n\t{\n\t\tbool same_input_attributes = false;\n\t\tbool same_input_bindings   = false;\n\n\t\tif (input_attributes.size() == state.input_attributes.size())\n\t\t{\n\t\t\tfor (uint32_t i = 0; i < input_attributes.size(); i++)\n\t\t\t{\n\t\t\t\tif (input_attributes[i] != state.input_attributes[i])\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsame_input_attributes = true;\n\t\t}\n\n\t\tif (input_bindings.size() == state.input_bindings.size())\n\t\t{\n\t\t\tfor (uint32_t i = 0; i < input_bindings.size(); i++)\n\t\t\t{\n\t\t\t\tif (input_bindings[i] != state.input_bindings[i])\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsame_input_bindings = true;\n\t\t}\n\n\t\treturn same_input_attributes && same_input_bindings;\n\t}\n\n\tinline bool operator!=(const VertexInputState &state) const\n\t{\n\t\treturn !(*this == state);\n\t}\n};\n\nstruct InputAssemblyState\n{\n\tRHIPrimitiveTopology topology = RHIPrimitiveTopology::Triangle;\n\n\tinline bool operator==(const InputAssemblyState &state) const\n\t{\n\t\treturn topology == state.topology;\n\t}\n\n\tinline bool operator!=(const InputAssemblyState &state) const\n\t{\n\t\treturn !(*this == state);\n\t}\n};\n\n// TODO: Tessellation\n\nclass RHIPipelineState\n{\n  public:\n\tRHIPipelineState(RHIDevice *device);\n\n\tvirtual ~RHIPipelineState() = default;\n\n\tstatic std::unique_ptr<RHIPipelineState> Create(RHIDevice *device);\n\n\tRHIPipelineState &SetShader(RHIShaderStage stage, RHIShader *shader);\n\tRHIPipelineState &SetDepthStencilState(const DepthStencilState &state);\n\tRHIPipelineState &SetBlendState(const BlendState &state);\n\tRHIPipelineState &SetRasterizationState(const RasterizationState &state);\n\tRHIPipelineState &SetMultisampleState(const MultisampleState &state);\n\tRHIPipelineState &SetVertexInputState(const VertexInputState &state);\n\tRHIPipelineState &SetInputAssemblyState(const InputAssemblyState &state);\n\n\tRHIPipelineState &ClearShader();\n\n\tconst std::vector<std::pair<RHIShaderStage, RHIShader *>> &GetShaders() const;\n\tconst DepthStencilState                                   &GetDepthStencilState() const;\n\tconst BlendState                                          &GetBlendState() const;\n\tconst RasterizationState                                  &GetRasterizationState() const;\n\tconst MultisampleState                                    &GetMultisampleState() const;\n\tconst VertexInputState                                    &GetVertexInputState() const;\n\tconst InputAssemblyState                                  &GetInputAssemblyState() const;\n\n\tsize_t GetHash();\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n\n\tstd::vector<std::pair<RHIShaderStage, RHIShader *>> m_shaders;\n\n\tDepthStencilState  m_depth_stencil_state;\n\tBlendState         m_blend_state;\n\tRasterizationState m_rasterization_state;\n\tMultisampleState   m_multisample_state;\n\tInputAssemblyState m_input_assembly_state;\n\tVertexInputState   m_vertex_input_state;\n\n\tbool   m_dirty = false;\n\tsize_t m_hash  = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIProfiler.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nstruct ProfileState\n{\n\tstd::chrono::time_point<std::chrono::high_resolution_clock> cpu_start;\n\tstd::chrono::time_point<std::chrono::high_resolution_clock> cpu_end;\n\n\tuint64_t gpu_start = 0;\n\tuint64_t gpu_end   = 0;\n\n\tfloat cpu_time = 0.f;\n\tfloat gpu_time = 0.f;\n\n\tstd::thread::id thread_id;\n};\n\nclass RHIProfiler\n{\n  public:\n\tRHIProfiler(RHIDevice *device, uint32_t frame_count = 3);\n\n\tvirtual ~RHIProfiler() = default;\n\n\tstatic std::unique_ptr<RHIProfiler> Create(RHIDevice *device, uint32_t frame_count = 3);\n\n\tconst ProfileState &GetProfileState() const;\n\n\tvirtual void Begin(RHICommand *cmd_buffer, uint32_t frame_index) = 0;\n\n\tvirtual void End(RHICommand *cmd_buffer) = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n\tuint32_t   m_frame_count;\n\tuint32_t   m_current_index = 0;\n\tProfileState m_state;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIQueue.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nstruct SubmitInfo\n{\n\tRHIQueueFamily queue_family;\n\tbool           is_cuda;\n\n\tstd::vector<RHICommand *>   cmd_buffers;\n\tstd::vector<RHISemaphore *> wait_semaphores;\n\tstd::vector<RHISemaphore *> signal_semaphores;\n};\n\nclass RHIQueue\n{\n  public:\n\tRHIQueue(RHIDevice *device);\n\n\tvirtual ~RHIQueue() = default;\n\n\tstatic std::unique_ptr<RHIQueue> Create(RHIDevice *device);\n\n\tvirtual void Execute(RHIQueueFamily family, const std::vector<SubmitInfo> &submit_infos, RHIFence* fence = nullptr) = 0;\n\n\t// Immediate execution\n\tvirtual void Execute(RHICommand *cmd_buffer) = 0;\n\n\tvirtual void Wait() = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIRenderTarget.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n#include \"RHITexture.hpp\"\n\nnamespace Ilum\n{\nstruct ColorAttachment\n{\n\tRHILoadAction  load  = RHILoadAction::Clear;\n\tRHIStoreAction store = RHIStoreAction::Store;\n\n\tstd::array<float, 4> clear_value = {0.f};\n};\n\nstruct DepthStencilAttachment\n{\n\tRHILoadAction  depth_load    = RHILoadAction::Clear;\n\tRHIStoreAction depth_store   = RHIStoreAction::Store;\n\tRHILoadAction  stencil_load  = RHILoadAction::DontCare;\n\tRHIStoreAction stencil_store = RHIStoreAction::DontCare;\n\n\tfloat    clear_depth   = std::numeric_limits<float>::max();\n\tuint32_t clear_stencil = 0;\n};\n\nclass RHIRenderTarget\n{\n  public:\n\tRHIRenderTarget(RHIDevice *device);\n\n\tvirtual ~RHIRenderTarget() = default;\n\n\tstatic std::unique_ptr<RHIRenderTarget> Create(RHIDevice *device);\n\n\tvirtual RHIRenderTarget &Set(uint32_t slot, RHITexture *texture, RHITextureDimension dimension, const ColorAttachment &attachment) = 0;\n\tvirtual RHIRenderTarget &Set(uint32_t slot, RHITexture *texture, const TextureRange &range, const ColorAttachment &attachment)     = 0;\n\tvirtual RHIRenderTarget &Set(RHITexture *texture, RHITextureDimension dimension, const DepthStencilAttachment &attachment)         = 0;\n\tvirtual RHIRenderTarget &Set(RHITexture *texture, const TextureRange &range, const DepthStencilAttachment &attachment)             = 0;\n\n\tuint32_t GetWidth() const;\n\n\tuint32_t GetHeight() const;\n\n\tuint32_t GetLayers() const;\n\n\tvirtual RHIRenderTarget &Clear() = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n\n\tuint32_t m_width  = 0;\n\tuint32_t m_height = 0;\n\tuint32_t m_layers = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHISampler.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nENUM(SamplerStateType, Enable){\n    LinearClamp,\n    LinearWarp,\n    NearestClamp,\n    NearestWarp,\n};\n\nstruct SamplerDesc\n{\n\tRHIFilter min_filter;\n\tRHIFilter mag_filter;\n\n\tRHIAddressMode address_mode_u;\n\tRHIAddressMode address_mode_v;\n\tRHIAddressMode address_mode_w;\n\tRHIMipmapMode  mipmap_mode;\n\n\tRHISamplerBorderColor border_color = RHISamplerBorderColor::Float_Transparent_Black;\n\n\tbool anisotropic = true;\n\n\tfloat mip_lod_bias = 0.f;\n\tfloat min_lod      = 0.f;\n\tfloat max_lod      = 100.f;\n\n\ttemplate<typename Archive>\n\tvoid serialize(Archive& archive)\n\t{\n\t\tarchive(min_filter, mag_filter, address_mode_u, address_mode_v, address_mode_w, mipmap_mode, border_color, anisotropic, mip_lod_bias, min_lod, max_lod);\n\t}\n\n\tstatic SamplerDesc LinearClamp();\n\tstatic SamplerDesc LinearWarp();\n\tstatic SamplerDesc NearestClamp();\n\tstatic SamplerDesc NearestWarp();\n};\n\nclass RHISampler\n{\n  public:\n\tRHISampler(RHIDevice *device, const SamplerDesc &desc);\n\n\tvirtual ~RHISampler() = default;\n\n\tstatic std::unique_ptr<RHISampler> Create(RHIDevice *device, const SamplerDesc &desc);\n\n  protected:\n\tRHIDevice  *p_device = nullptr;\n\tSamplerDesc m_desc;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHIShader.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nENUM(DescriptorType, Enable){\n    Sampler,\n    TextureSRV,\n    TextureUAV,\n    ConstantBuffer,\n    StructuredBuffer,\n    AccelerationStructure};\n\nSTRUCT(ShaderMeta, Enable)\n{\n\tSTRUCT(Variable, Enable)\n\t{\n\t\tuint32_t  spirv_id;\n\t\tuint32_t  location;\n\t\tRHIFormat format;\n\n\t\tinline bool operator==(const Variable &other) const\n\t\t{\n\t\t\treturn location == other.location &&\n\t\t\t       format == other.format;\n\t\t}\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive & archive)\n\t\t{\n\t\t\tarchive(spirv_id, location, format);\n\t\t}\n\t};\n\n\tSTRUCT(Constant, Enable)\n\t{\n\t\tuint32_t       spirv_id;\n\t\tstd::string    name;\n\t\tuint32_t       size   = 0;\n\t\tuint32_t       offset = 0;\n\t\tRHIShaderStage stage;\n\n\t\tinline bool operator==(const Constant &other) const\n\t\t{\n\t\t\treturn size == other.size &&\n\t\t\t       offset == other.offset &&\n\t\t\t       stage == other.stage;\n\t\t}\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive & archive)\n\t\t{\n\t\t\tarchive(spirv_id, name, size, offset, stage);\n\t\t}\n\t};\n\n\tSTRUCT(Descriptor, Enable)\n\t{\n\t\tuint32_t       spirv_id;\n\t\tstd::string    name;\n\t\tuint32_t       array_size;\n\t\tuint32_t       set;\n\t\tuint32_t       binding;\n\t\tDescriptorType type;\n\t\tRHIShaderStage stage;\n\n\t\tinline bool operator==(const Descriptor &other) const\n\t\t{\n\t\t\treturn array_size == other.array_size &&\n\t\t\t       set == other.set &&\n\t\t\t       binding == other.binding &&\n\t\t\t       type == other.type;\n\t\t}\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive & archive)\n\t\t{\n\t\t\tarchive(spirv_id, name, array_size, set, binding, type, stage);\n\t\t}\n\t};\n\n\tinline ShaderMeta &operator+=(const ShaderMeta &rhs)\n\t{\n\t\tHashCombine(hash, rhs.hash);\n\n\t\tfor (auto &rhs_descriptor : rhs.descriptors)\n\t\t{\n\t\t\tbool should_add = true;\n\t\t\tfor (auto &descriptor : descriptors)\n\t\t\t{\n\t\t\t\tif (descriptor == rhs_descriptor)\n\t\t\t\t{\n\t\t\t\t\tdescriptor.stage = descriptor.stage | rhs_descriptor.stage;\n\t\t\t\t\tshould_add       = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (should_add)\n\t\t\t{\n\t\t\t\tdescriptors.push_back(rhs_descriptor);\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &rhs_constant : rhs.constants)\n\t\t{\n\t\t\tbool should_add = true;\n\t\t\tfor (auto &constant : constants)\n\t\t\t{\n\t\t\t\tif (constant == rhs_constant)\n\t\t\t\t{\n\t\t\t\t\tconstant.stage = constant.stage | rhs_constant.stage;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (should_add)\n\t\t\t{\n\t\t\t\tconstants.push_back(rhs_constant);\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &input : rhs.inputs)\n\t\t{\n\t\t\tinputs.push_back(input);\n\t\t}\n\t\tfor (auto &output : rhs.outputs)\n\t\t{\n\t\t\toutputs.push_back(output);\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\tstd::vector<Descriptor> descriptors;\n\tstd::vector<Constant>   constants;\n\tstd::vector<Variable>   inputs;\n\tstd::vector<Variable>   outputs;\n\n\tsize_t hash = 0;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive & archive)\n\t{\n\t\tarchive(descriptors, constants, inputs, outputs, hash);\n\t}\n};\n\nclass RHIShader\n{\n  public:\n\tRHIShader(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source);\n\n\tvirtual ~RHIShader() = default;\n\n\tstatic std::unique_ptr<RHIShader> Create(RHIDevice *device, const std::string &entry_point, const std::vector<uint8_t> &source);\n\n\tconst std::string &GetEntryPoint() const;\n\n  protected:\n\tRHIDevice  *p_device = nullptr;\n\tstd::string m_entry_point;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHISwapchain.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nclass RHISwapchain\n{\n  public:\n\tRHISwapchain(RHIDevice *device, uint32_t width, uint32_t height, bool vsync = false);\n\n\tvirtual ~RHISwapchain() = default;\n\n\tbool GetVsync() const;\n\n\tuint32_t GetWidth() const;\n\n\tuint32_t GetHeight() const;\n\n\tstatic std::unique_ptr<RHISwapchain> Create(RHIDevice *device, void *window_handle, uint32_t width, uint32_t height, bool sync);\n\n\tvirtual uint32_t GetTextureCount() = 0;\n\n\tvirtual void AcquireNextTexture(RHISemaphore *signal_semaphore, RHIFence* signal_fence) = 0;\n\n\tvirtual RHITexture *GetCurrentTexture() = 0;\n\n\tvirtual uint32_t GetCurrentFrameIndex() = 0;\n\n\tvirtual bool Present(RHISemaphore *semaphore) = 0;\n\n\tvirtual void Resize(uint32_t width, uint32_t height, bool vsync) = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n\tuint32_t   m_width  = 0;\n\tuint32_t   m_height = 0;\n\tbool       m_vsync  = false;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHISynchronization.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nclass RHIFence\n{\n  public:\n\tRHIFence(RHIDevice *device);\n\tvirtual ~RHIFence() = default;\n\n\tstatic std::unique_ptr<RHIFence> Create(RHIDevice *device);\n\n\tvirtual void Wait(uint64_t timeout = std::numeric_limits<uint64_t>::max()) = 0;\n\tvirtual void Reset()                = 0;\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n};\n\nclass RHISemaphore\n{\n  public:\n\tRHISemaphore(RHIDevice *device);\n\n\tvirtual ~RHISemaphore() = default;\n\n\tvirtual void SetName(const std::string &name) = 0;\n\n\tstatic std::unique_ptr<RHISemaphore> Create(RHIDevice *device);\n\n  protected:\n\tRHIDevice *p_device = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/RHI/Public/RHI/RHITexture.hpp",
    "content": "#pragma once\n\n#include \"Fwd.hpp\"\n\nnamespace Ilum\n{\nSTRUCT(TextureDesc, Enable)\n{\n\tstd::string name;\n\n\tMETA(Min(1))\n\tuint32_t width = 1;\n\n\tMETA(Min(1))\n\tuint32_t height = 1;\n\n\tMETA(Min(1))\n\tuint32_t depth = 1;\n\n\tMETA(Min(1))\n\tuint32_t mips = 1;\n\n\tMETA(Min(1))\n\tuint32_t layers = 1;\n\n\tMETA(Min(1))\n\tuint32_t samples = 1;\n\n\tRHIFormat       format = RHIFormat::Undefined;\n\tRHITextureUsage usage  = RHITextureUsage::Undefined;\n\n\ttemplate<typename Archive>\n\tvoid serialize(Archive & archive)\n\t{\n\t\tarchive(name, width, height, depth, mips, layers, samples, format, usage);\n\t}\n};\n\nstruct TextureRange\n{\n\tRHITextureDimension dimension   = RHITextureDimension::Texture2D;\n\tuint32_t            base_mip    = 0;\n\tuint32_t            mip_count   = 1;\n\tuint32_t            base_layer  = 0;\n\tuint32_t            layer_count = 1;\n\n\tsize_t Hash() const\n\t{\n\t\tsize_t hash = 0;\n\t\tHashCombine(hash, dimension, base_mip, mip_count, base_layer, layer_count);\n\t\treturn hash;\n\t}\n};\n\nclass RHITexture\n{\n  public:\n\tRHITexture(RHIDevice *device, const TextureDesc &desc);\n\n\tvirtual ~RHITexture() = default;\n\n\tconst TextureDesc &GetDesc() const;\n\n\tconst std::string GetBackend() const;\n\n\tvirtual std::unique_ptr<RHITexture> Alias(const TextureDesc &desc);\n\n\tvirtual size_t GetMemorySize() const = 0;\n\n\tstatic std::unique_ptr<RHITexture> Create(RHIDevice *device, const TextureDesc &desc);\n\tstatic std::unique_ptr<RHITexture> Create2D(RHIDevice *device, uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples = 1);\n\tstatic std::unique_ptr<RHITexture> Create3D(RHIDevice *device, uint32_t width, uint32_t height, uint32_t depth, RHIFormat format, RHITextureUsage usage);\n\tstatic std::unique_ptr<RHITexture> CreateCube(RHIDevice *device, uint32_t width, uint32_t height, RHIFormat format, RHITextureUsage usage, bool mipmap);\n\tstatic std::unique_ptr<RHITexture> Create2DArray(RHIDevice *device, uint32_t width, uint32_t height, uint32_t layers, RHIFormat format, RHITextureUsage usage, bool mipmap, uint32_t samples = 1);\n\n  protected:\n\tRHIDevice  *p_device = nullptr;\n\tTextureDesc m_desc;\n};\n\nstruct TextureStateTransition\n{\n\tRHITexture *texture;\n\n\tRHIResourceState src;\n\tRHIResourceState dst;\n\n\tTextureRange range;\n\n\tRHIQueueFamily src_family = RHIQueueFamily::Graphics;\n\tRHIQueueFamily dst_family = RHIQueueFamily::Graphics;\n};\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Render/Material/Private/Material/MaterialCompiler.cpp",
    "content": ""
  },
  {
    "path": "Source/Runtime/Render/Material/Private/Material/MaterialData.cpp",
    "content": ""
  },
  {
    "path": "Source/Runtime/Render/Material/Private/Material/MaterialGraph.cpp",
    "content": "#include \"MaterialGraph.hpp\"\n\nnamespace Ilum\n{\nMaterialGraphDesc &MaterialGraphDesc::SetName(const std::string &name)\n{\n\tm_name = name;\n\treturn *this;\n}\n\nMaterialNodeDesc &MaterialGraphDesc::AddNode(size_t handle, MaterialNodeDesc &&desc)\n{\n\tfor (auto &[pin_handle, pin] : desc.GetPins())\n\t{\n\t\tm_node_lookup[pin_handle] = handle;\n\t}\n\n\tm_node_lookup[handle] = handle;\n\tdesc.SetHandle(handle);\n\tm_nodes.emplace(handle, std::move(desc));\n\treturn m_nodes.at(handle);\n}\n\nvoid MaterialGraphDesc::EraseNode(size_t handle)\n{\n\tconst auto &desc = m_nodes.at(handle);\n\tconst auto &pins = desc.GetPins();\n\n\tfor (auto iter = m_edges.begin(); iter != m_edges.end();)\n\t{\n\t\tif (pins.find(iter->first) != pins.end() ||\n\t\t    pins.find(iter->second) != pins.end())\n\t\t{\n\t\t\titer = m_edges.erase(iter);\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer++;\n\t\t}\n\t}\n\n\tfor (auto &[handle, name] : pins)\n\t{\n\t\tm_node_lookup.erase(handle);\n\t}\n\n\tm_nodes.erase(handle);\n}\n\nvoid MaterialGraphDesc::EraseLink(size_t source, size_t target)\n{\n\tif (m_edges.find(target) != m_edges.end() &&\n\t    m_edges.at(target) == source)\n\t{\n\t\tm_edges.erase(target);\n\t}\n}\n\nMaterialGraphDesc &MaterialGraphDesc::Link(size_t source, size_t target)\n{\n\tconst auto &src_node = m_nodes.at(m_node_lookup.at(source));\n\tconst auto &dst_node = m_nodes.at(m_node_lookup.at(target));\n\n\tconst auto &src_pin = src_node.GetPin(source);\n\tconst auto &dst_pin = dst_node.GetPin(target);\n\n\tif ((src_pin.type & dst_pin.accept) &&\n\t    src_pin.attribute != dst_pin.attribute)\n\t{\n\t\tm_edges[target] = source;\n\t}\n\n\treturn *this;\n}\n\nbool MaterialGraphDesc::HasLink(size_t target) const\n{\n\treturn m_edges.find(target) != m_edges.end();\n}\n\nsize_t MaterialGraphDesc::LinkFrom(size_t target) const\n{\n\treturn m_edges.at(target);\n}\n\nconst MaterialNodeDesc &MaterialGraphDesc::GetNode(size_t handle) const\n{\n\treturn m_nodes.at(m_node_lookup.at(handle));\n}\n\nconst std::string &MaterialGraphDesc::GetName() const\n{\n\treturn m_name;\n}\n\nconst std::map<size_t, MaterialNodeDesc> &MaterialGraphDesc::GetNodes() const\n{\n\treturn m_nodes;\n}\n\nconst std::map<size_t, size_t> &MaterialGraphDesc::GetEdges() const\n{\n\treturn m_edges;\n}\n\nvoid MaterialGraphDesc::Clear()\n{\n\tm_nodes.clear();\n\tm_edges.clear();\n\tm_node_lookup.clear();\n}\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Private/Material/MaterialNode.cpp",
    "content": "#include \"MaterialNode.hpp\"\n#include \"MaterialGraph.hpp\"\n\nnamespace Ilum\n{\nMaterialNodeDesc &MaterialNodeDesc::SetName(const std::string &name)\n{\n\tm_name = name;\n\treturn *this;\n}\n\nMaterialNodeDesc &MaterialNodeDesc::SetCategory(const std::string &category)\n{\n\tm_category = category;\n\treturn *this;\n}\n\nMaterialNodeDesc &MaterialNodeDesc::SetHandle(size_t handle)\n{\n\tm_handle = handle;\n\treturn *this;\n}\n\nMaterialNodeDesc &MaterialNodeDesc::Input(size_t handle, const std::string &name, MaterialNodePin::Type type, MaterialNodePin::Type accept, Variant &&variant)\n{\n\tMaterialNodePin pin{type, accept == MaterialNodePin::Type::Unknown ? type : accept, MaterialNodePin::Attribute::Input, name, handle, std::move(variant)};\n\tm_pins.emplace(handle, pin);\n\tm_pin_indices.emplace(name, handle);\n\treturn *this;\n}\n\nMaterialNodeDesc &MaterialNodeDesc::Output(size_t handle, const std::string &name, MaterialNodePin::Type type, Variant &&variant)\n{\n\tMaterialNodePin pin{type, MaterialNodePin::Type::Unknown, MaterialNodePin::Attribute::Output, name, handle, std::move(variant)};\n\tm_pins.emplace(handle, pin);\n\tm_pin_indices.emplace(name, handle);\n\treturn *this;\n}\n\nMaterialNodePin &MaterialNodeDesc::GetPin(size_t handle)\n{\n\treturn m_pins.at(handle);\n}\n\nconst MaterialNodePin &MaterialNodeDesc::GetPin(size_t handle) const\n{\n\treturn m_pins.at(handle);\n}\n\nMaterialNodePin &MaterialNodeDesc::GetPin(const std::string &name)\n{\n\treturn m_pins.at(m_pin_indices.at(name));\n}\n\nconst MaterialNodePin &MaterialNodeDesc::GetPin(const std::string &name) const\n{\n\treturn m_pins.at(m_pin_indices.at(name));\n}\n\nMaterialNodeDesc &MaterialNodeDesc::SetVariant(Variant variant)\n{\n\tm_variant = variant;\n\treturn *this;\n}\n\nconst Variant &MaterialNodeDesc::GetVariant() const\n{\n\treturn m_variant;\n}\n\nconst std::string &MaterialNodeDesc::GetName() const\n{\n\treturn m_name;\n}\n\nconst std::string &MaterialNodeDesc::GetCategory() const\n{\n\treturn m_category;\n}\n\nconst std::map<size_t, MaterialNodePin> &MaterialNodeDesc::GetPins() const\n{\n\treturn m_pins;\n}\n\nsize_t MaterialNodeDesc::GetHandle() const\n{\n\treturn m_handle;\n}\n\nvoid MaterialNodeDesc::EmitHLSL(const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) const\n{\n\tPluginManager::GetInstance().Call(fmt::format(\"shared/Material/Material.{}.{}.dll\", m_category, m_name), \"EmitHLSL\", *this, graph_desc, manager, context);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Private/Material/Spectrum.cpp",
    "content": "#include \"Spectrum.hpp\"\n\nnamespace Ilum\n{\ntemplate <typename Predicate>\nint32_t Findint32_terval(int32_t size, const Predicate &pred)\n{\n\tint32_t first = 0, len = size;\n\twhile (len > 0)\n\t{\n\t\tint32_t half = len >> 1, middle = first + half;\n\t\t// Bisect range based on value of _pred_ at _middle_\n\t\tif (pred(middle))\n\t\t{\n\t\t\tfirst = middle + 1;\n\t\t\tlen -= half + 1;\n\t\t}\n\t\telse\n\t\t\tlen = half;\n\t}\n\treturn glm::clamp(first - 1, 0, size - 2);\n}\n\nvoid XYZToRGB(const float xyz[3], float rgb[3])\n{\n\trgb[0] = 3.240479f * xyz[0] - 1.537150f * xyz[1] - 0.498535f * xyz[2];\n\trgb[1] = -0.969256f * xyz[0] + 1.875991f * xyz[1] + 0.041556f * xyz[2];\n\trgb[2] = 0.055648f * xyz[0] - 0.204043f * xyz[1] + 1.057311f * xyz[2];\n}\n\nvoid RGBToXYZ(const float rgb[3], float xyz[3])\n{\n\txyz[0] = 0.412453f * rgb[0] + 0.357580f * rgb[1] + 0.180423f * rgb[2];\n\txyz[1] = 0.212671f * rgb[0] + 0.715160f * rgb[1] + 0.072169f * rgb[2];\n\txyz[2] = 0.019334f * rgb[0] + 0.119193f * rgb[1] + 0.950227f * rgb[2];\n}\n\nbool SpectrumSamplesSorted(const float *lambda, const float *vals, int32_t n)\n{\n\tfor (int32_t i = 0; i < n - 1; ++i)\n    {\n        if (lambda[i] > lambda[i + 1])\n        {\n\t\t\treturn false;\n        }\n    }\n\treturn true;\n}\n\nvoid SortSpectrumSamples(float *lambda, float *vals, int32_t n)\n{\n\tstd::vector<std::pair<float, float>> sort_vec;\n\tsort_vec.reserve(n);\n    for (int32_t i = 0; i < n; ++i)\n    {\n\t\tsort_vec.push_back(std::make_pair(lambda[i], vals[i]));\n    }\n\tstd::sort(sort_vec.begin(), sort_vec.end());\n\tfor (int32_t i = 0; i < n; ++i)\n\t{\n\t\tlambda[i] = sort_vec[i].first;\n\t\tvals[i]   = sort_vec[i].second;\n\t}\n}\n\nfloat InterpolateSpectrumSamples(const float *lambda, const float *vals, int32_t n, float l)\n{\n    if (l <= lambda[0])\n    {\n\t\treturn vals[0];\n    }\n    if (l >= lambda[n - 1])\n    {\n\t\treturn vals[n - 1];\n    }\n\tint32_t offset = Findint32_terval(n, [&](int32_t index) { return lambda[index] <= l; });\n\n\tfloat t = (l - lambda[offset]) / (lambda[offset + 1] - lambda[offset]);\n\n\treturn glm::mix(vals[offset], vals[offset + 1], t);\n}\n\nglm::vec3 FromSampled(const float *lambda, const float *v, int32_t n)\n{\n\t// Sort samples if unordered, use sorted for returned spectrum\n\tif (!SpectrumSamplesSorted(lambda, v, n))\n\t{\n\t\tstd::vector<float> slambda(&lambda[0], &lambda[n]);\n\t\tstd::vector<float> sv(&v[0], &v[n]);\n\t\tSortSpectrumSamples(&slambda[0], &sv[0], n);\n\t\treturn FromSampled(&slambda[0], &sv[0], n);\n\t}\n\tfloat xyz[3] = {0, 0, 0};\n\tfor (int i = 0; i < nCIESamples; ++i)\n\t{\n\t\tfloat val = InterpolateSpectrumSamples(lambda, v, n, CIE_lambda[i]);\n\t\txyz[0] += val * CIE_X[i];\n\t\txyz[1] += val * CIE_Y[i];\n\t\txyz[2] += val * CIE_Z[i];\n\t}\n\tfloat scale = float(CIE_lambda[nCIESamples - 1] - CIE_lambda[0]) /\n\t              float(CIE_Y_integral * nCIESamples);\n\txyz[0] *= scale;\n\txyz[1] *= scale;\n\txyz[2] *= scale;\n\n    glm::vec3 rgb = glm::vec3(0.f);\n\tXYZToRGB(xyz, &rgb.x);\n\treturn rgb;\n}\n\nconst float CIE_X[nCIESamples] = {\n    // CIE X function values\n    0.0001299000f, 0.0001458470f, 0.0001638021f, 0.0001840037f,\n    0.0002066902f, 0.0002321000f, 0.0002607280f, 0.0002930750f,\n    0.0003293880f, 0.0003699140f, 0.0004149000f, 0.0004641587f,\n    0.0005189860f, 0.0005818540f, 0.0006552347f, 0.0007416000f,\n    0.0008450296f, 0.0009645268f, 0.001094949f, 0.001231154f,\n    0.001368000f, 0.001502050f, 0.001642328f, 0.001802382f,\n    0.001995757f, 0.002236000f, 0.002535385f, 0.002892603f,\n    0.003300829f, 0.003753236f, 0.004243000f, 0.004762389f,\n    0.005330048f, 0.005978712f, 0.006741117f, 0.007650000f,\n    0.008751373f, 0.01002888f, 0.01142170f, 0.01286901f,\n    0.01431000f, 0.01570443f, 0.01714744f, 0.01878122f,\n    0.02074801f, 0.02319000f, 0.02620736f, 0.02978248f,\n    0.03388092f, 0.03846824f, 0.04351000f, 0.04899560f,\n    0.05502260f, 0.06171880f, 0.06921200f, 0.07763000f,\n    0.08695811f, 0.09717672f, 0.1084063f, 0.1207672f,\n    0.1343800f, 0.1493582f, 0.1653957f, 0.1819831f,\n    0.1986110f, 0.2147700f, 0.2301868f, 0.2448797f,\n    0.2587773f, 0.2718079f, 0.2839000f, 0.2949438f,\n    0.3048965f, 0.3137873f, 0.3216454f, 0.3285000f,\n    0.3343513f, 0.3392101f, 0.3431213f, 0.3461296f,\n    0.3482800f, 0.3495999f, 0.3501474f, 0.3500130f,\n    0.3492870f, 0.3480600f, 0.3463733f, 0.3442624f,\n    0.3418088f, 0.3390941f, 0.3362000f, 0.3331977f,\n    0.3300411f, 0.3266357f, 0.3228868f, 0.3187000f,\n    0.3140251f, 0.3088840f, 0.3032904f, 0.2972579f,\n    0.2908000f, 0.2839701f, 0.2767214f, 0.2689178f,\n    0.2604227f, 0.2511000f, 0.2408475f, 0.2298512f,\n    0.2184072f, 0.2068115f, 0.1953600f, 0.1842136f,\n    0.1733273f, 0.1626881f, 0.1522833f, 0.1421000f,\n    0.1321786f, 0.1225696f, 0.1132752f, 0.1042979f,\n    0.09564000f, 0.08729955f, 0.07930804f, 0.07171776f,\n    0.06458099f, 0.05795001f, 0.05186211f, 0.04628152f,\n    0.04115088f, 0.03641283f, 0.03201000f, 0.02791720f,\n    0.02414440f, 0.02068700f, 0.01754040f, 0.01470000f,\n    0.01216179f, 0.009919960f, 0.007967240f, 0.006296346f,\n    0.004900000f, 0.003777173f, 0.002945320f, 0.002424880f,\n    0.002236293f, 0.002400000f, 0.002925520f, 0.003836560f,\n    0.005174840f, 0.006982080f, 0.009300000f, 0.01214949f,\n    0.01553588f, 0.01947752f, 0.02399277f, 0.02910000f,\n    0.03481485f, 0.04112016f, 0.04798504f, 0.05537861f,\n    0.06327000f, 0.07163501f, 0.08046224f, 0.08973996f,\n    0.09945645f, 0.1096000f, 0.1201674f, 0.1311145f,\n    0.1423679f, 0.1538542f, 0.1655000f, 0.1772571f,\n    0.1891400f, 0.2011694f, 0.2133658f, 0.2257499f,\n    0.2383209f, 0.2510668f, 0.2639922f, 0.2771017f,\n    0.2904000f, 0.3038912f, 0.3175726f, 0.3314384f,\n    0.3454828f, 0.3597000f, 0.3740839f, 0.3886396f,\n    0.4033784f, 0.4183115f, 0.4334499f, 0.4487953f,\n    0.4643360f, 0.4800640f, 0.4959713f, 0.5120501f,\n    0.5282959f, 0.5446916f, 0.5612094f, 0.5778215f,\n    0.5945000f, 0.6112209f, 0.6279758f, 0.6447602f,\n    0.6615697f, 0.6784000f, 0.6952392f, 0.7120586f,\n    0.7288284f, 0.7455188f, 0.7621000f, 0.7785432f,\n    0.7948256f, 0.8109264f, 0.8268248f, 0.8425000f,\n    0.8579325f, 0.8730816f, 0.8878944f, 0.9023181f,\n    0.9163000f, 0.9297995f, 0.9427984f, 0.9552776f,\n    0.9672179f, 0.9786000f, 0.9893856f, 0.9995488f,\n    1.0090892f, 1.0180064f, 1.0263000f, 1.0339827f,\n    1.0409860f, 1.0471880f, 1.0524667f, 1.0567000f,\n    1.0597944f, 1.0617992f, 1.0628068f, 1.0629096f,\n    1.0622000f, 1.0607352f, 1.0584436f, 1.0552244f,\n    1.0509768f, 1.0456000f, 1.0390369f, 1.0313608f,\n    1.0226662f, 1.0130477f, 1.0026000f, 0.9913675f,\n    0.9793314f, 0.9664916f, 0.9528479f, 0.9384000f,\n    0.9231940f, 0.9072440f, 0.8905020f, 0.8729200f,\n    0.8544499f, 0.8350840f, 0.8149460f, 0.7941860f,\n    0.7729540f, 0.7514000f, 0.7295836f, 0.7075888f,\n    0.6856022f, 0.6638104f, 0.6424000f, 0.6215149f,\n    0.6011138f, 0.5811052f, 0.5613977f, 0.5419000f,\n    0.5225995f, 0.5035464f, 0.4847436f, 0.4661939f,\n    0.4479000f, 0.4298613f, 0.4120980f, 0.3946440f,\n    0.3775333f, 0.3608000f, 0.3444563f, 0.3285168f,\n    0.3130192f, 0.2980011f, 0.2835000f, 0.2695448f,\n    0.2561184f, 0.2431896f, 0.2307272f, 0.2187000f,\n    0.2070971f, 0.1959232f, 0.1851708f, 0.1748323f,\n    0.1649000f, 0.1553667f, 0.1462300f, 0.1374900f,\n    0.1291467f, 0.1212000f, 0.1136397f, 0.1064650f,\n    0.09969044f, 0.09333061f, 0.08740000f, 0.08190096f,\n    0.07680428f, 0.07207712f, 0.06768664f, 0.06360000f,\n    0.05980685f, 0.05628216f, 0.05297104f, 0.04981861f,\n    0.04677000f, 0.04378405f, 0.04087536f, 0.03807264f,\n    0.03540461f, 0.03290000f, 0.03056419f, 0.02838056f,\n    0.02634484f, 0.02445275f, 0.02270000f, 0.02108429f,\n    0.01959988f, 0.01823732f, 0.01698717f, 0.01584000f,\n    0.01479064f, 0.01383132f, 0.01294868f, 0.01212920f,\n    0.01135916f, 0.01062935f, 0.009938846f, 0.009288422f,\n    0.008678854f, 0.008110916f, 0.007582388f, 0.007088746f,\n    0.006627313f, 0.006195408f, 0.005790346f, 0.005409826f,\n    0.005052583f, 0.004717512f, 0.004403507f, 0.004109457f,\n    0.003833913f, 0.003575748f, 0.003334342f, 0.003109075f,\n    0.002899327f, 0.002704348f, 0.002523020f, 0.002354168f,\n    0.002196616f, 0.002049190f, 0.001910960f, 0.001781438f,\n    0.001660110f, 0.001546459f, 0.001439971f, 0.001340042f,\n    0.001246275f, 0.001158471f, 0.001076430f, 0.0009999493f,\n    0.0009287358f, 0.0008624332f, 0.0008007503f, 0.0007433960f,\n    0.0006900786f, 0.0006405156f, 0.0005945021f, 0.0005518646f,\n    0.0005124290f, 0.0004760213f, 0.0004424536f, 0.0004115117f,\n    0.0003829814f, 0.0003566491f, 0.0003323011f, 0.0003097586f,\n    0.0002888871f, 0.0002695394f, 0.0002515682f, 0.0002348261f,\n    0.0002191710f, 0.0002045258f, 0.0001908405f, 0.0001780654f,\n    0.0001661505f, 0.0001550236f, 0.0001446219f, 0.0001349098f,\n    0.0001258520f, 0.0001174130f, 0.0001095515f, 0.0001022245f,\n    0.00009539445f, 0.00008902390f, 0.00008307527f, 0.00007751269f,\n    0.00007231304f, 0.00006745778f, 0.00006292844f, 0.00005870652f,\n    0.00005477028f, 0.00005109918f, 0.00004767654f, 0.00004448567f,\n    0.00004150994f, 0.00003873324f, 0.00003614203f, 0.00003372352f,\n    0.00003146487f, 0.00002935326f, 0.00002737573f, 0.00002552433f,\n    0.00002379376f, 0.00002217870f, 0.00002067383f, 0.00001927226f,\n    0.00001796640f, 0.00001674991f, 0.00001561648f, 0.00001455977f,\n    0.00001357387f, 0.00001265436f, 0.00001179723f, 0.00001099844f,\n    0.00001025398f, 0.000009559646f, 0.000008912044f, 0.000008308358f,\n    0.000007745769f, 0.000007221456f, 0.000006732475f, 0.000006276423f,\n    0.000005851304f, 0.000005455118f, 0.000005085868f, 0.000004741466f,\n    0.000004420236f, 0.000004120783f, 0.000003841716f, 0.000003581652f,\n    0.000003339127f, 0.000003112949f, 0.000002902121f, 0.000002705645f,\n    0.000002522525f, 0.000002351726f, 0.000002192415f, 0.000002043902f,\n    0.000001905497f, 0.000001776509f, 0.000001656215f, 0.000001544022f,\n    0.000001439440f, 0.000001341977f, 0.000001251141f};\n\nconst float CIE_Y[nCIESamples] = {\n    // CIE Y function values\n    0.000003917000f, 0.000004393581f, 0.000004929604f, 0.000005532136f,\n    0.000006208245f, 0.000006965000f, 0.000007813219f, 0.000008767336f,\n    0.000009839844f, 0.00001104323f, 0.00001239000f, 0.00001388641f,\n    0.00001555728f, 0.00001744296f, 0.00001958375f, 0.00002202000f,\n    0.00002483965f, 0.00002804126f, 0.00003153104f, 0.00003521521f,\n    0.00003900000f, 0.00004282640f, 0.00004691460f, 0.00005158960f,\n    0.00005717640f, 0.00006400000f, 0.00007234421f, 0.00008221224f,\n    0.00009350816f, 0.0001061361f, 0.0001200000f, 0.0001349840f,\n    0.0001514920f, 0.0001702080f, 0.0001918160f, 0.0002170000f,\n    0.0002469067f, 0.0002812400f, 0.0003185200f, 0.0003572667f,\n    0.0003960000f, 0.0004337147f, 0.0004730240f, 0.0005178760f,\n    0.0005722187f, 0.0006400000f, 0.0007245600f, 0.0008255000f,\n    0.0009411600f, 0.001069880f, 0.001210000f, 0.001362091f,\n    0.001530752f, 0.001720368f, 0.001935323f, 0.002180000f,\n    0.002454800f, 0.002764000f, 0.003117800f, 0.003526400f,\n    0.004000000f, 0.004546240f, 0.005159320f, 0.005829280f,\n    0.006546160f, 0.007300000f, 0.008086507f, 0.008908720f,\n    0.009767680f, 0.01066443f, 0.01160000f, 0.01257317f,\n    0.01358272f, 0.01462968f, 0.01571509f, 0.01684000f,\n    0.01800736f, 0.01921448f, 0.02045392f, 0.02171824f,\n    0.02300000f, 0.02429461f, 0.02561024f, 0.02695857f,\n    0.02835125f, 0.02980000f, 0.03131083f, 0.03288368f,\n    0.03452112f, 0.03622571f, 0.03800000f, 0.03984667f,\n    0.04176800f, 0.04376600f, 0.04584267f, 0.04800000f,\n    0.05024368f, 0.05257304f, 0.05498056f, 0.05745872f,\n    0.06000000f, 0.06260197f, 0.06527752f, 0.06804208f,\n    0.07091109f, 0.07390000f, 0.07701600f, 0.08026640f,\n    0.08366680f, 0.08723280f, 0.09098000f, 0.09491755f,\n    0.09904584f, 0.1033674f, 0.1078846f, 0.1126000f,\n    0.1175320f, 0.1226744f, 0.1279928f, 0.1334528f,\n    0.1390200f, 0.1446764f, 0.1504693f, 0.1564619f,\n    0.1627177f, 0.1693000f, 0.1762431f, 0.1835581f,\n    0.1912735f, 0.1994180f, 0.2080200f, 0.2171199f,\n    0.2267345f, 0.2368571f, 0.2474812f, 0.2586000f,\n    0.2701849f, 0.2822939f, 0.2950505f, 0.3085780f,\n    0.3230000f, 0.3384021f, 0.3546858f, 0.3716986f,\n    0.3892875f, 0.4073000f, 0.4256299f, 0.4443096f,\n    0.4633944f, 0.4829395f, 0.5030000f, 0.5235693f,\n    0.5445120f, 0.5656900f, 0.5869653f, 0.6082000f,\n    0.6293456f, 0.6503068f, 0.6708752f, 0.6908424f,\n    0.7100000f, 0.7281852f, 0.7454636f, 0.7619694f,\n    0.7778368f, 0.7932000f, 0.8081104f, 0.8224962f,\n    0.8363068f, 0.8494916f, 0.8620000f, 0.8738108f,\n    0.8849624f, 0.8954936f, 0.9054432f, 0.9148501f,\n    0.9237348f, 0.9320924f, 0.9399226f, 0.9472252f,\n    0.9540000f, 0.9602561f, 0.9660074f, 0.9712606f,\n    0.9760225f, 0.9803000f, 0.9840924f, 0.9874812f,\n    0.9903128f, 0.9928116f, 0.9949501f, 0.9967108f,\n    0.9980983f, 0.9991120f, 0.9997482f, 1.0000000f,\n    0.9998567f, 0.9993046f, 0.9983255f, 0.9968987f,\n    0.9950000f, 0.9926005f, 0.9897426f, 0.9864444f,\n    0.9827241f, 0.9786000f, 0.9740837f, 0.9691712f,\n    0.9638568f, 0.9581349f, 0.9520000f, 0.9454504f,\n    0.9384992f, 0.9311628f, 0.9234576f, 0.9154000f,\n    0.9070064f, 0.8982772f, 0.8892048f, 0.8797816f,\n    0.8700000f, 0.8598613f, 0.8493920f, 0.8386220f,\n    0.8275813f, 0.8163000f, 0.8047947f, 0.7930820f,\n    0.7811920f, 0.7691547f, 0.7570000f, 0.7447541f,\n    0.7324224f, 0.7200036f, 0.7074965f, 0.6949000f,\n    0.6822192f, 0.6694716f, 0.6566744f, 0.6438448f,\n    0.6310000f, 0.6181555f, 0.6053144f, 0.5924756f,\n    0.5796379f, 0.5668000f, 0.5539611f, 0.5411372f,\n    0.5283528f, 0.5156323f, 0.5030000f, 0.4904688f,\n    0.4780304f, 0.4656776f, 0.4534032f, 0.4412000f,\n    0.4290800f, 0.4170360f, 0.4050320f, 0.3930320f,\n    0.3810000f, 0.3689184f, 0.3568272f, 0.3447768f,\n    0.3328176f, 0.3210000f, 0.3093381f, 0.2978504f,\n    0.2865936f, 0.2756245f, 0.2650000f, 0.2547632f,\n    0.2448896f, 0.2353344f, 0.2260528f, 0.2170000f,\n    0.2081616f, 0.1995488f, 0.1911552f, 0.1829744f,\n    0.1750000f, 0.1672235f, 0.1596464f, 0.1522776f,\n    0.1451259f, 0.1382000f, 0.1315003f, 0.1250248f,\n    0.1187792f, 0.1127691f, 0.1070000f, 0.1014762f,\n    0.09618864f, 0.09112296f, 0.08626485f, 0.08160000f,\n    0.07712064f, 0.07282552f, 0.06871008f, 0.06476976f,\n    0.06100000f, 0.05739621f, 0.05395504f, 0.05067376f,\n    0.04754965f, 0.04458000f, 0.04175872f, 0.03908496f,\n    0.03656384f, 0.03420048f, 0.03200000f, 0.02996261f,\n    0.02807664f, 0.02632936f, 0.02470805f, 0.02320000f,\n    0.02180077f, 0.02050112f, 0.01928108f, 0.01812069f,\n    0.01700000f, 0.01590379f, 0.01483718f, 0.01381068f,\n    0.01283478f, 0.01192000f, 0.01106831f, 0.01027339f,\n    0.009533311f, 0.008846157f, 0.008210000f, 0.007623781f,\n    0.007085424f, 0.006591476f, 0.006138485f, 0.005723000f,\n    0.005343059f, 0.004995796f, 0.004676404f, 0.004380075f,\n    0.004102000f, 0.003838453f, 0.003589099f, 0.003354219f,\n    0.003134093f, 0.002929000f, 0.002738139f, 0.002559876f,\n    0.002393244f, 0.002237275f, 0.002091000f, 0.001953587f,\n    0.001824580f, 0.001703580f, 0.001590187f, 0.001484000f,\n    0.001384496f, 0.001291268f, 0.001204092f, 0.001122744f,\n    0.001047000f, 0.0009765896f, 0.0009111088f, 0.0008501332f,\n    0.0007932384f, 0.0007400000f, 0.0006900827f, 0.0006433100f,\n    0.0005994960f, 0.0005584547f, 0.0005200000f, 0.0004839136f,\n    0.0004500528f, 0.0004183452f, 0.0003887184f, 0.0003611000f,\n    0.0003353835f, 0.0003114404f, 0.0002891656f, 0.0002684539f,\n    0.0002492000f, 0.0002313019f, 0.0002146856f, 0.0001992884f,\n    0.0001850475f, 0.0001719000f, 0.0001597781f, 0.0001486044f,\n    0.0001383016f, 0.0001287925f, 0.0001200000f, 0.0001118595f,\n    0.0001043224f, 0.00009733560f, 0.00009084587f, 0.00008480000f,\n    0.00007914667f, 0.00007385800f, 0.00006891600f, 0.00006430267f,\n    0.00006000000f, 0.00005598187f, 0.00005222560f, 0.00004871840f,\n    0.00004544747f, 0.00004240000f, 0.00003956104f, 0.00003691512f,\n    0.00003444868f, 0.00003214816f, 0.00003000000f, 0.00002799125f,\n    0.00002611356f, 0.00002436024f, 0.00002272461f, 0.00002120000f,\n    0.00001977855f, 0.00001845285f, 0.00001721687f, 0.00001606459f,\n    0.00001499000f, 0.00001398728f, 0.00001305155f, 0.00001217818f,\n    0.00001136254f, 0.00001060000f, 0.000009885877f, 0.000009217304f,\n    0.000008592362f, 0.000008009133f, 0.000007465700f, 0.000006959567f,\n    0.000006487995f, 0.000006048699f, 0.000005639396f, 0.000005257800f,\n    0.000004901771f, 0.000004569720f, 0.000004260194f, 0.000003971739f,\n    0.000003702900f, 0.000003452163f, 0.000003218302f, 0.000003000300f,\n    0.000002797139f, 0.000002607800f, 0.000002431220f, 0.000002266531f,\n    0.000002113013f, 0.000001969943f, 0.000001836600f, 0.000001712230f,\n    0.000001596228f, 0.000001488090f, 0.000001387314f, 0.000001293400f,\n    0.000001205820f, 0.000001124143f, 0.000001048009f, 0.0000009770578f,\n    0.0000009109300f, 0.0000008492513f, 0.0000007917212f, 0.0000007380904f,\n    0.0000006881098f, 0.0000006415300f, 0.0000005980895f, 0.0000005575746f,\n    0.0000005198080f, 0.0000004846123f, 0.0000004518100f};\n\nconst float CIE_Z[nCIESamples] = {\n    // CIE Z function values\n    0.0006061000f,\n    0.0006808792f,\n    0.0007651456f,\n    0.0008600124f,\n    0.0009665928f,\n    0.001086000f,\n    0.001220586f,\n    0.001372729f,\n    0.001543579f,\n    0.001734286f,\n    0.001946000f,\n    0.002177777f,\n    0.002435809f,\n    0.002731953f,\n    0.003078064f,\n    0.003486000f,\n    0.003975227f,\n    0.004540880f,\n    0.005158320f,\n    0.005802907f,\n    0.006450001f,\n    0.007083216f,\n    0.007745488f,\n    0.008501152f,\n    0.009414544f,\n    0.01054999f,\n    0.01196580f,\n    0.01365587f,\n    0.01558805f,\n    0.01773015f,\n    0.02005001f,\n    0.02251136f,\n    0.02520288f,\n    0.02827972f,\n    0.03189704f,\n    0.03621000f,\n    0.04143771f,\n    0.04750372f,\n    0.05411988f,\n    0.06099803f,\n    0.06785001f,\n    0.07448632f,\n    0.08136156f,\n    0.08915364f,\n    0.09854048f,\n    0.1102000f,\n    0.1246133f,\n    0.1417017f,\n    0.1613035f,\n    0.1832568f,\n    0.2074000f,\n    0.2336921f,\n    0.2626114f,\n    0.2947746f,\n    0.3307985f,\n    0.3713000f,\n    0.4162091f,\n    0.4654642f,\n    0.5196948f,\n    0.5795303f,\n    0.6456000f,\n    0.7184838f,\n    0.7967133f,\n    0.8778459f,\n    0.9594390f,\n    1.0390501f,\n    1.1153673f,\n    1.1884971f,\n    1.2581233f,\n    1.3239296f,\n    1.3856000f,\n    1.4426352f,\n    1.4948035f,\n    1.5421903f,\n    1.5848807f,\n    1.6229600f,\n    1.6564048f,\n    1.6852959f,\n    1.7098745f,\n    1.7303821f,\n    1.7470600f,\n    1.7600446f,\n    1.7696233f,\n    1.7762637f,\n    1.7804334f,\n    1.7826000f,\n    1.7829682f,\n    1.7816998f,\n    1.7791982f,\n    1.7758671f,\n    1.7721100f,\n    1.7682589f,\n    1.7640390f,\n    1.7589438f,\n    1.7524663f,\n    1.7441000f,\n    1.7335595f,\n    1.7208581f,\n    1.7059369f,\n    1.6887372f,\n    1.6692000f,\n    1.6475287f,\n    1.6234127f,\n    1.5960223f,\n    1.5645280f,\n    1.5281000f,\n    1.4861114f,\n    1.4395215f,\n    1.3898799f,\n    1.3387362f,\n    1.2876400f,\n    1.2374223f,\n    1.1878243f,\n    1.1387611f,\n    1.0901480f,\n    1.0419000f,\n    0.9941976f,\n    0.9473473f,\n    0.9014531f,\n    0.8566193f,\n    0.8129501f,\n    0.7705173f,\n    0.7294448f,\n    0.6899136f,\n    0.6521049f,\n    0.6162000f,\n    0.5823286f,\n    0.5504162f,\n    0.5203376f,\n    0.4919673f,\n    0.4651800f,\n    0.4399246f,\n    0.4161836f,\n    0.3938822f,\n    0.3729459f,\n    0.3533000f,\n    0.3348578f,\n    0.3175521f,\n    0.3013375f,\n    0.2861686f,\n    0.2720000f,\n    0.2588171f,\n    0.2464838f,\n    0.2347718f,\n    0.2234533f,\n    0.2123000f,\n    0.2011692f,\n    0.1901196f,\n    0.1792254f,\n    0.1685608f,\n    0.1582000f,\n    0.1481383f,\n    0.1383758f,\n    0.1289942f,\n    0.1200751f,\n    0.1117000f,\n    0.1039048f,\n    0.09666748f,\n    0.08998272f,\n    0.08384531f,\n    0.07824999f,\n    0.07320899f,\n    0.06867816f,\n    0.06456784f,\n    0.06078835f,\n    0.05725001f,\n    0.05390435f,\n    0.05074664f,\n    0.04775276f,\n    0.04489859f,\n    0.04216000f,\n    0.03950728f,\n    0.03693564f,\n    0.03445836f,\n    0.03208872f,\n    0.02984000f,\n    0.02771181f,\n    0.02569444f,\n    0.02378716f,\n    0.02198925f,\n    0.02030000f,\n    0.01871805f,\n    0.01724036f,\n    0.01586364f,\n    0.01458461f,\n    0.01340000f,\n    0.01230723f,\n    0.01130188f,\n    0.01037792f,\n    0.009529306f,\n    0.008749999f,\n    0.008035200f,\n    0.007381600f,\n    0.006785400f,\n    0.006242800f,\n    0.005749999f,\n    0.005303600f,\n    0.004899800f,\n    0.004534200f,\n    0.004202400f,\n    0.003900000f,\n    0.003623200f,\n    0.003370600f,\n    0.003141400f,\n    0.002934800f,\n    0.002749999f,\n    0.002585200f,\n    0.002438600f,\n    0.002309400f,\n    0.002196800f,\n    0.002100000f,\n    0.002017733f,\n    0.001948200f,\n    0.001889800f,\n    0.001840933f,\n    0.001800000f,\n    0.001766267f,\n    0.001737800f,\n    0.001711200f,\n    0.001683067f,\n    0.001650001f,\n    0.001610133f,\n    0.001564400f,\n    0.001513600f,\n    0.001458533f,\n    0.001400000f,\n    0.001336667f,\n    0.001270000f,\n    0.001205000f,\n    0.001146667f,\n    0.001100000f,\n    0.001068800f,\n    0.001049400f,\n    0.001035600f,\n    0.001021200f,\n    0.001000000f,\n    0.0009686400f,\n    0.0009299200f,\n    0.0008868800f,\n    0.0008425600f,\n    0.0008000000f,\n    0.0007609600f,\n    0.0007236800f,\n    0.0006859200f,\n    0.0006454400f,\n    0.0006000000f,\n    0.0005478667f,\n    0.0004916000f,\n    0.0004354000f,\n    0.0003834667f,\n    0.0003400000f,\n    0.0003072533f,\n    0.0002831600f,\n    0.0002654400f,\n    0.0002518133f,\n    0.0002400000f,\n    0.0002295467f,\n    0.0002206400f,\n    0.0002119600f,\n    0.0002021867f,\n    0.0001900000f,\n    0.0001742133f,\n    0.0001556400f,\n    0.0001359600f,\n    0.0001168533f,\n    0.0001000000f,\n    0.00008613333f,\n    0.00007460000f,\n    0.00006500000f,\n    0.00005693333f,\n    0.00004999999f,\n    0.00004416000f,\n    0.00003948000f,\n    0.00003572000f,\n    0.00003264000f,\n    0.00003000000f,\n    0.00002765333f,\n    0.00002556000f,\n    0.00002364000f,\n    0.00002181333f,\n    0.00002000000f,\n    0.00001813333f,\n    0.00001620000f,\n    0.00001420000f,\n    0.00001213333f,\n    0.00001000000f,\n    0.000007733333f,\n    0.000005400000f,\n    0.000003200000f,\n    0.000001333333f,\n    0.000000000000f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f,\n    0.0f};\n\nconst float CIE_lambda[nCIESamples] = {\n    360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,\n    375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389,\n    390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,\n    405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419,\n    420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,\n    435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449,\n    450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,\n    465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479,\n    480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494,\n    495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509,\n    510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524,\n    525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539,\n    540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554,\n    555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569,\n    570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584,\n    585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599,\n    600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614,\n    615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629,\n    630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,\n    645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659,\n    660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674,\n    675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689,\n    690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,\n    705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719,\n    720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734,\n    735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749,\n    750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764,\n    765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779,\n    780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794,\n    795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809,\n    810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824,\n    825, 826, 827, 828, 829, 830};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Public/Material/MaterialCompiler.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n#include <RHI/RHISampler.hpp>\n\n#include \"MaterialGraph.hpp\"\n#include \"MaterialNode.hpp\"\n\nnamespace Ilum\n{\nstruct MaterialCompilationContext\n{\n\tstruct BSDF\n\t{\n\t\tstd::string name = \"\";\n\t\tstd::string type = \"\";\n\n\t\tstd::string initialization = \"\";\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(name, type, initialization);\n\t\t}\n\t};\n\n\tstd::vector<std::string> variables;\n\n\tstd::map<std::string, std::string> textures;\n\n\tstd::map<std::string, SamplerDesc> samplers;\n\n\tstd::vector<BSDF> bsdfs;\n\n\tstruct\n\t{\n\t\tstd::string bsdf = \"\";\n\t} output;\n\n\tstd::unordered_set<size_t> finish_nodes;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(variables, textures, samplers, bsdfs, output.bsdf, finish_nodes);\n\t}\n\n\tvoid Reset()\n\t{\n\t\tvariables.clear();\n\t\ttextures.clear();\n\t\tsamplers.clear();\n\t\tbsdfs.clear();\n\t\tfinish_nodes.clear();\n\t}\n\n\tbool IsCompiled(const MaterialNodeDesc &desc)\n\t{\n\t\tif (finish_nodes.find(desc.GetHandle()) == finish_nodes.end())\n\t\t{\n\t\t\tfinish_nodes.insert(desc.GetHandle());\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\ttemplate <typename T>\n\tinline void SetParameter(const std::string &name, std::map<std::string, std::string> &parameters, T var)\n\t{\n\t}\n\n\ttemplate <>\n\tinline void SetParameter(const std::string &name, std::map<std::string, std::string> &parameters, float var)\n\t{\n\t\tparameters[name] = fmt::format(\"{}\", var);\n\t}\n\n\ttemplate <>\n\tinline void SetParameter(const std::string &name, std::map<std::string, std::string> &parameters, bool var)\n\t{\n\t\tparameters[name] = fmt::format(\"{}\", var);\n\t}\n\n\ttemplate <>\n\tinline void SetParameter(const std::string &name, std::map<std::string, std::string> &parameters, glm::vec3 var)\n\t{\n\t\tparameters[name] = fmt::format(\"float3({}, {}, {})\", var.x, var.y, var.z);\n\t}\n\n\ttemplate <typename T>\n\tinline bool HasParameter(std::map<std::string, std::string> &parameters, const MaterialNodePin &node_pin, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context)\n\t{\n\t\tif (graph_desc.HasLink(node_pin.handle))\n\t\t{\n\t\t\tauto &src_node = graph_desc.GetNode(graph_desc.LinkFrom(node_pin.handle));\n\t\t\tsrc_node.EmitHLSL(graph_desc, manager, context);\n\t\t\tauto &src_pin = src_node.GetPin(graph_desc.LinkFrom(node_pin.handle));\n\t\t\tif (src_pin.type != node_pin.type && src_pin.type == MaterialNodePin::Type::Float)\n\t\t\t{\n\t\t\t\tparameters[node_pin.name] = fmt::format(\"float3(S_{}, S_{}, S_{})\", src_pin.handle, src_pin.handle, src_pin.handle);\n\t\t\t}\n\t\t\telse if (src_pin.type != node_pin.type && node_pin.type == MaterialNodePin::Type::Float)\n\t\t\t{\n\t\t\t\tparameters[node_pin.name] = fmt::format(\"S_{}.x\", src_pin.handle);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tparameters[node_pin.name] = fmt::format(\"S_{}\", src_pin.handle);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\ttemplate <typename T>\n\tinline void SetParameter(std::map<std::string, std::string> &parameters, const MaterialNodePin &node_pin, const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context)\n\t{\n\t\tif (!HasParameter<T>(parameters, node_pin, graph_desc, manager, context))\n\t\t{\n\t\t\tSetParameter<T>(node_pin.name, parameters, *node_pin.variant.Convert<T>());\n\t\t}\n\t}\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Public/Material/MaterialData.hpp",
    "content": "#pragma once\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nenum class BlendMode\n{\n\tOpaque,\n\tMask,\n\tBlend\n};\n\nstruct MaterialData\n{\n\tstd::vector<uint32_t> textures;\n\tstd::vector<uint32_t> samplers;\n\n\tstd::string shader    = \"Material/Material.hlsli\";\n\tstd::string signature = \"Signature_0\";\n\n\tBlendMode blend_mode = BlendMode::Opaque;\n\n\tvoid Reset()\n\t{\n\t\ttextures.clear();\n\t\tsamplers.clear();\n\t\tshader    = \"Material/Material.hlsli\";\n\t\tsignature = \"Signature_0\";\n\t}\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(textures, samplers, shader, signature, blend_mode);\n\t}\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Public/Material/MaterialGraph.hpp",
    "content": "#pragma once\n\n#include \"MaterialNode.hpp\"\n\nnamespace Ilum\n{\nclass MaterialGraphDesc\n{\n  public:\n\tMaterialGraphDesc() = default;\n\n\t~MaterialGraphDesc() = default;\n\n\tMaterialGraphDesc &SetName(const std::string &name);\n\n\tMaterialNodeDesc &AddNode(size_t handle, MaterialNodeDesc &&desc);\n\n\tvoid EraseNode(size_t handle);\n\n\tvoid EraseLink(size_t source, size_t target);\n\n\tMaterialGraphDesc &Link(size_t source, size_t target);\n\n\tbool HasLink(size_t target) const;\n\n\tsize_t LinkFrom(size_t target) const;\n\n\tconst MaterialNodeDesc &GetNode(size_t handle) const;\n\n\tconst std::string &GetName() const;\n\n\tconst std::map<size_t, MaterialNodeDesc> &GetNodes() const;\n\n\tconst std::map<size_t, size_t> &GetEdges() const;\n\n\tvoid Clear();\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(m_name, m_nodes, m_edges, m_node_lookup);\n\t}\n\n  private:\n\tstd::string m_name;\n\n\tstd::map<size_t, MaterialNodeDesc> m_nodes;\n\n\tstd::map<size_t, size_t> m_edges;        // Target - Source\n\n\tstd::map<size_t, size_t> m_node_lookup;        // Pin ID - Node ID\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Public/Material/MaterialNode.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\nnamespace Ilum\n{\nclass MaterialGraphDesc;\nclass Editor;\nclass ResourceManager;\nstruct MaterialCompilationContext;\n\nstruct MaterialNodePin\n{\n\tenum class Type : uint64_t\n\t{\n\t\tUnknown = 0,\n\t\tBool    = 1,\n\t\tFloat   = 1 << 2,\n\t\tFloat3  = 1 << 3,\n\t\tRGB     = 1 << 4,\n\t\tBSDF    = 1 << 5,\n\t\tMedia   = 1 << 6,\n\t};\n\n\tenum class Attribute\n\t{\n\t\tInput,\n\t\tOutput\n\t};\n\n\tType        type;\n\tType        accept;        //\tfor input pin\n\tAttribute   attribute;\n\tstd::string name;\n\tsize_t      handle;\n\tVariant     variant;\n\n\tbool enable = true;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(type, accept, attribute, name, handle, variant, enable);\n\t}\n};\n\nDEFINE_ENUMCLASS_OPERATION(MaterialNodePin::Type)\n\nclass MaterialNodeDesc\n{\n  public:\n\tMaterialNodeDesc() = default;\n\n\t~MaterialNodeDesc() = default;\n\n\tMaterialNodeDesc &SetName(const std::string &name);\n\n\tMaterialNodeDesc &SetCategory(const std::string &category);\n\n\tMaterialNodeDesc &SetHandle(size_t handle);\n\n\tMaterialNodeDesc &Input(size_t handle, const std::string &name, MaterialNodePin::Type type, MaterialNodePin::Type accept = MaterialNodePin::Type::Unknown, Variant &&variant = {});\n\n\tMaterialNodeDesc &Output(size_t handle, const std::string &name, MaterialNodePin::Type type, Variant &&variant = {});\n\n\tconst MaterialNodePin &GetPin(size_t handle) const;\n\n\tMaterialNodePin &GetPin(size_t handle);\n\n\tconst MaterialNodePin &GetPin(const std::string &name) const;\n\n\tMaterialNodePin &GetPin(const std::string &name);\n\n\tMaterialNodeDesc &SetVariant(Variant variant);\n\n\tconst Variant &GetVariant() const;\n\n\tconst std::string &GetName() const;\n\n\tconst std::string &GetCategory() const;\n\n\tconst std::map<size_t, MaterialNodePin> &GetPins() const;\n\n\tsize_t GetHandle() const;\n\n\tvoid EmitHLSL(const MaterialGraphDesc &graph_desc, ResourceManager *manager, MaterialCompilationContext *context) const;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(m_name, m_category, m_handle, m_pins, m_pin_indices, m_variant);\n\t}\n\n  private:\n\tstd::string m_name;\n\tstd::string m_category;\n\n\tsize_t m_handle = ~0ull;\n\n\tstd::map<size_t, MaterialNodePin> m_pins;\n\tstd::map<std::string, size_t>     m_pin_indices;\n\n\tVariant m_variant;\n};\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Material/Public/Material/Spectrum.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nstatic const int sampledLambdaStart = 400;\nstatic const int sampledLambdaEnd   = 700;\nstatic const int nSpectralSamples   = 60;\n\nextern void XYZToRGB(const float xyz[3], float rgb[3]);\nextern void RGBToXYZ(const float rgb[3], float xyz[3]);\n\nstatic const int   nCIESamples = 471;\nextern const float CIE_X[nCIESamples];\nextern const float CIE_Y[nCIESamples];\nextern const float CIE_Z[nCIESamples];\nextern const float CIE_lambda[nCIESamples];\nstatic const float CIE_Y_integral    = 106.856895f;\n\nextern bool  SpectrumSamplesSorted(const float *lambda, const float *vals, int32_t n);\nextern void  SortSpectrumSamples(float *lambda, float *vals, int32_t n);\nextern float InterpolateSpectrumSamples(const float *lambda, const float *vals, int32_t n, float l);\n\nglm::vec3 FromSampled(const float *lambda, const float *v, int32_t n);\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Private/RenderGraph.cpp",
    "content": "#include \"RenderGraph.hpp\"\n\n#include <Core/JobSystem.hpp>\n\nnamespace Ilum\n{\nRenderGraphDesc &RenderGraphDesc::SetName(const std::string &name)\n{\n\tm_name = name;\n\treturn *this;\n}\n\nRenderGraphDesc &RenderGraphDesc::AddPass(size_t handle, RenderPassDesc &&desc)\n{\n\tfor (auto &[pin_handle, pin] : desc.GetPins())\n\t{\n\t\tm_pass_lookup[pin_handle] = handle;\n\t}\n\n\tm_pass_lookup[handle] = handle;\n\tm_pass_lookup[handle] = handle;\n\tm_pass_lookup[handle] = handle;\n\tdesc.SetHandle(handle);\n\tm_passes.emplace(handle, std::move(desc));\n\treturn *this;\n}\n\nvoid RenderGraphDesc::ErasePass(size_t handle)\n{\n\tauto &desc = m_passes.at(handle);\n\tauto &pins = desc.GetPins();\n\n\tfor (auto iter = m_edges.begin(); iter != m_edges.end();)\n\t{\n\t\tif (pins.find(iter->first) != pins.end() ||\n\t\t    pins.find(iter->second) != pins.end() ||\n\t\t    iter->first == handle ||\n\t\t    iter->second == handle)\n\t\t{\n\t\t\titer = m_edges.erase(iter);\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer++;\n\t\t}\n\t}\n\n\tfor (auto &[handle, name] : pins)\n\t{\n\t\tm_pass_lookup.erase(handle);\n\t}\n\n\tm_passes.erase(handle);\n}\n\nvoid RenderGraphDesc::EraseLink(size_t source, size_t target)\n{\n\tif (m_edges.find(target) != m_edges.end() &&\n\t    m_edges.at(target) == source)\n\t{\n\t\tm_edges.erase(target);\n\t}\n}\n\nRenderGraphDesc &RenderGraphDesc::Link(size_t source, size_t target)\n{\n\tconst auto &src_node = m_passes.at(m_pass_lookup.at(source));\n\tconst auto &dst_node = m_passes.at(m_pass_lookup.at(target));\n\n\tif ((source == src_node.GetHandle()) &&\n\t    (target == dst_node.GetHandle()))\n\t{\n\t\t// Link Node\n\t\tm_edges[target] = source;\n\t}\n\telse if ((source != src_node.GetHandle()) &&\n\t         (target != dst_node.GetHandle()))\n\t{\n\t\t// Link Pin\n\t\tconst auto &src_pin = src_node.GetPin(source);\n\t\tconst auto &dst_pin = dst_node.GetPin(target);\n\n\t\tif ((src_pin.type == dst_pin.type) &&\n\t\t    src_pin.attribute != dst_pin.attribute)\n\t\t{\n\t\t\tm_edges[target] = source;\n\t\t}\n\t}\n\n\treturn *this;\n}\n\nbool RenderGraphDesc::HasLink(size_t target) const\n{\n\treturn m_edges.find(target) != m_edges.end();\n}\n\nsize_t RenderGraphDesc::LinkFrom(size_t target) const\n{\n\treturn m_edges.at(target);\n}\n\nstd::set<size_t> RenderGraphDesc::LinkTo(size_t source) const\n{\n\tstd::set<size_t> result;\n\tfor (auto &[dst, src] : m_edges)\n\t{\n\t\tif (src == source)\n\t\t{\n\t\t\tresult.insert(dst);\n\t\t}\n\t}\n\treturn result;\n}\n\nbool RenderGraphDesc::HasPass(size_t handle) const\n{\n\treturn m_passes.find(handle) != m_passes.end();\n}\n\nRenderPassDesc &RenderGraphDesc::GetPass(size_t handle)\n{\n\treturn m_passes.at(m_pass_lookup.at(handle));\n}\n\nconst std::string &RenderGraphDesc::GetName() const\n{\n\treturn m_name;\n}\n\nstd::map<size_t, RenderPassDesc> &RenderGraphDesc::GetPasses()\n{\n\treturn m_passes;\n}\n\nconst std::map<size_t, size_t> &RenderGraphDesc::GetEdges() const\n{\n\treturn m_edges;\n}\n\nvoid RenderGraphDesc::Clear()\n{\n\tm_passes.clear();\n\tm_edges.clear();\n\tm_pass_lookup.clear();\n}\n\nstruct RenderGraph::Impl\n{\n\tRHIContext *rhi_context = nullptr;\n\n\tInitializeBarrierTask initialize_barrier;\n\n\tstd::vector<RenderPassInfo> render_passes;\n\n\tstd::vector<std::unique_ptr<RHITexture>> textures;\n\tstd::map<size_t, RHITexture *>           texture_lookup;\n\tstd::map<size_t, RHITexture *>           cuda_textures;\n\n\tstd::vector<std::unique_ptr<RHIBuffer>> buffers;\n\tstd::map<size_t, RHIBuffer *>           buffer_lookup;\n\n\tstd::map<RHISemaphore *, std::unique_ptr<RHISemaphore>> cuda_semaphore_map;\n\n\tbool init = false;\n};\n\nRenderGraph::RenderGraph(RHIContext *rhi_context)\n{\n\tm_impl              = new Impl;\n\tm_impl->rhi_context = rhi_context;\n}\n\nRenderGraph::~RenderGraph()\n{\n\tm_impl->rhi_context->Reset();\n\tm_impl->rhi_context->WaitIdle();\n\n\tdelete m_impl;\n}\n\nstd::unique_ptr<RHITexture> RenderGraph::SetTexture(size_t handle, std::unique_ptr<RHITexture> &&texture)\n{\n\tif (texture->GetBackend() == \"CUDA\")\n\t{\n\t\tif (m_impl->cuda_textures.find(handle) != m_impl->cuda_textures.end())\n\t\t{\n\t\t\tsize_t idx    = 0;\n\t\t\tauto  *target = m_impl->cuda_textures.at(handle);\n\n\t\t\tfor (auto &it : m_impl->textures)\n\t\t\t{\n\t\t\t\tif (it.get() == target)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor (auto &[handle, tex] : m_impl->cuda_textures)\n\t\t\t{\n\t\t\t\tif (tex == target)\n\t\t\t\t{\n\t\t\t\t\ttex = texture.get();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::unique_ptr<RHITexture> old = std::move(m_impl->textures[idx]);\n\t\t\tm_impl->textures[idx] = std::move(texture);\n\t\t\treturn old;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (m_impl->texture_lookup.find(handle) != m_impl->texture_lookup.end())\n\t\t{\n\t\t\tsize_t idx    = 0;\n\t\t\tauto  *target = m_impl->texture_lookup.at(handle);\n\n\t\t\tfor (auto &it : m_impl->textures)\n\t\t\t{\n\t\t\t\tif (it.get() == target)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor (auto &[handle, tex] : m_impl->texture_lookup)\n\t\t\t{\n\t\t\t\tif (tex == target)\n\t\t\t\t{\n\t\t\t\t\ttex = texture.get();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::unique_ptr<RHITexture> old = std::move(m_impl->textures[idx]);\n\t\t\tm_impl->textures[idx]           = std::move(texture);\n\t\t\treturn old;\n\t\t}\n\t}\n\n\treturn nullptr;\n}\n\nRHITexture *RenderGraph::GetTexture(size_t handle)\n{\n\tauto iter = m_impl->texture_lookup.find(handle);\n\treturn iter == m_impl->texture_lookup.end() ? nullptr : iter->second;\n}\n\nRHIBuffer *RenderGraph::GetBuffer(size_t handle)\n{\n\tauto iter = m_impl->buffer_lookup.find(handle);\n\treturn iter == m_impl->buffer_lookup.end() ? nullptr : iter->second;\n}\n\nRHITexture *RenderGraph::GetCUDATexture(size_t handle)\n{\n\tif (m_impl->cuda_textures.find(handle) == m_impl->cuda_textures.end())\n\t{\n\t\tm_impl->textures.emplace_back(m_impl->rhi_context->MapToCUDATexture(m_impl->texture_lookup.at(handle)));\n\t\tm_impl->cuda_textures.emplace(handle, m_impl->textures.back().get());\n\t}\n\treturn m_impl->cuda_textures.at(handle);\n}\n\nvoid RenderGraph::Execute(RenderGraphBlackboard &black_board)\n{\n\tif (m_impl->render_passes.empty())\n\t{\n\t\treturn;\n\t}\n\n\tif (!m_impl->init)\n\t{\n\t\tauto *graphics_cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\tauto *compute_cmd_buffer  = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\t\tgraphics_cmd_buffer->Begin();\n\t\tcompute_cmd_buffer->Begin();\n\t\tgraphics_cmd_buffer->BeginMarker(\"Initialize - Graphics Queue\");\n\t\tcompute_cmd_buffer->BeginMarker(\"Initialize - Compute Queue\");\n\t\tm_impl->initialize_barrier(*this, graphics_cmd_buffer, compute_cmd_buffer);\n\t\tm_impl->init = true;\n\t\tgraphics_cmd_buffer->EndMarker();\n\t\tcompute_cmd_buffer->EndMarker();\n\t\tgraphics_cmd_buffer->End();\n\t\tcompute_cmd_buffer->End();\n\t\tm_impl->rhi_context->Execute({graphics_cmd_buffer});\n\t\tm_impl->rhi_context->Execute({compute_cmd_buffer});\n\t}\n\n\t// Collect cmd buffers\n\t/*std::vector<std::future<RHICommand *>> cmd_buffer_futures;\n\tfor (auto &pass : m_impl->render_passes)\n\t{\n\t    auto future = JobSystem::GetInstance().ExecuteAsync([&]() {\n\t        if (pass.bind_point == BindPoint::CUDA)\n\t        {\n\t            auto *cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Compute, true);\n\t            cmd_buffer->Begin();\n\t            pass.profiler->Begin(cmd_buffer, m_impl->rhi_context->GetSwapchain()->GetCurrentFrameIndex());\n\t            pass.execute(*this, cmd_buffer, pass.config, black_board);\n\t            pass.profiler->End(cmd_buffer);\n\t            cmd_buffer->End();\n\t            return cmd_buffer;\n\t        }\n\t        else\n\t        {\n\t            RHIQueueFamily family = RHIQueueFamily::Graphics;\n\t            if (pass.bind_point == BindPoint::Rasterization)\n\t            {\n\t                family = RHIQueueFamily::Graphics;\n\t            }\n\t            else\n\t            {\n\t                family = RHIQueueFamily::Compute;\n\t            }\n\n\t            auto *cmd_buffer = m_impl->rhi_context->CreateCommand(family);\n\t            cmd_buffer->SetName(pass.name);\n\t            cmd_buffer->Begin();\n\t            cmd_buffer->BeginMarker(pass.name);\n\t            pass.profiler->Begin(cmd_buffer, m_impl->rhi_context->GetSwapchain()->GetCurrentFrameIndex());\n\t            pass.barrier(*this, cmd_buffer);\n\t            pass.execute(*this, cmd_buffer, pass.config, black_board);\n\t            pass.profiler->End(cmd_buffer);\n\t            cmd_buffer->EndMarker();\n\t            cmd_buffer->End();\n\t            return cmd_buffer;\n\t        }\n\t    });\n\t    cmd_buffer_futures.emplace_back(std::move(future));\n\t}\n\n\tif (!cmd_buffer_futures.empty())\n\t{\n\t    std::vector<RHICommand *> cmd_buffers(cmd_buffer_futures.size());\n\t    std::transform(cmd_buffer_futures.begin(), cmd_buffer_futures.end(), cmd_buffers.begin(), [](std::future<RHICommand *> &iter) { return iter.get(); });\n\n\t    RHIQueueFamily            last_queue_family = cmd_buffers[0]->GetQueueFamily();\n\t    std::string               last_backend      = cmd_buffers[0]->GetBackend();\n\t    RHISemaphore             *last_semaphore    = nullptr;\n\t    std::vector<RHICommand *> submit_cmd_buffers;\n\t    for (auto &cmd_buffer : cmd_buffers)\n\t    {\n\t        if (last_queue_family != cmd_buffer->GetQueueFamily() ||\n\t            cmd_buffer->GetBackend() != last_backend &&\n\t                !submit_cmd_buffers.empty())\n\t        {\n\t            RHISemaphore *pass_semaphore   = m_impl->rhi_context->CreateFrameSemaphore();\n\t            RHISemaphore *signal_semaphore = last_backend == \"CUDA\" ? MapToCUDASemaphore(pass_semaphore) : pass_semaphore;\n\t            RHISemaphore *wait_semaphore   = last_semaphore ? last_backend == \"CUDA\" ? MapToCUDASemaphore(last_semaphore) : last_semaphore : nullptr;\n\n\t            m_impl->rhi_context->Submit(std::move(submit_cmd_buffers), wait_semaphore ? std::vector<RHISemaphore *>{wait_semaphore} : std::vector<RHISemaphore *>{}, {signal_semaphore});\n\t            submit_cmd_buffers.clear();\n\t            last_semaphore    = pass_semaphore;\n\t            last_queue_family = cmd_buffer->GetQueueFamily();\n\t        }\n\n\t        submit_cmd_buffers.push_back(cmd_buffer);\n\t    }\n\t    if (!submit_cmd_buffers.empty())\n\t    {\n\t        m_impl->rhi_context->Submit(std::move(submit_cmd_buffers), last_semaphore ? std::vector<RHISemaphore *>{last_semaphore} : std::vector<RHISemaphore *>{}, {});\n\t    }\n\t}*/\n\n\tstd::vector<RHICommand *> cmd_buffers;\n\tfor (auto &pass : m_impl->render_passes)\n\t{\n\t\tif (pass.bind_point == BindPoint::CUDA)\n\t\t{\n\t\t\tauto *cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Compute, true);\n\t\t\tcmd_buffer->Begin();\n\t\t\tpass.profiler->Begin(cmd_buffer, m_impl->rhi_context->GetSwapchain()->GetCurrentFrameIndex());\n\t\t\tpass.execute(*this, cmd_buffer, pass.config, black_board);\n\t\t\tpass.profiler->End(cmd_buffer);\n\t\t\tcmd_buffer->End();\n\t\t\tcmd_buffers.emplace_back(cmd_buffer);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tRHIQueueFamily family = RHIQueueFamily::Graphics;\n\t\t\tif (pass.bind_point == BindPoint::Rasterization)\n\t\t\t{\n\t\t\t\tfamily = RHIQueueFamily::Graphics;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfamily = RHIQueueFamily::Compute;\n\t\t\t}\n\n\t\t\tauto *cmd_buffer = m_impl->rhi_context->CreateCommand(family);\n\t\t\tcmd_buffer->SetName(pass.name);\n\t\t\tcmd_buffer->Begin();\n\t\t\tcmd_buffer->BeginMarker(pass.name);\n\t\t\tpass.profiler->Begin(cmd_buffer, m_impl->rhi_context->GetSwapchain()->GetCurrentFrameIndex());\n\t\t\tpass.barrier(*this, cmd_buffer);\n\t\t\tpass.execute(*this, cmd_buffer, pass.config, black_board);\n\t\t\tpass.profiler->End(cmd_buffer);\n\t\t\tcmd_buffer->EndMarker();\n\t\t\tcmd_buffer->End();\n\t\t\tcmd_buffers.emplace_back(cmd_buffer);\n\t\t}\n\t}\n\n\tif (!cmd_buffers.empty())\n\t{\n\t\tRHIQueueFamily            last_queue_family = cmd_buffers[0]->GetQueueFamily();\n\t\tstd::string               last_backend      = cmd_buffers[0]->GetBackend();\n\t\tRHISemaphore             *last_semaphore    = nullptr;\n\t\tstd::vector<RHICommand *> submit_cmd_buffers;\n\t\tfor (auto &cmd_buffer : cmd_buffers)\n\t\t{\n\t\t\tif (last_queue_family != cmd_buffer->GetQueueFamily() ||\n\t\t\t    cmd_buffer->GetBackend() != last_backend &&\n\t\t\t        !submit_cmd_buffers.empty())\n\t\t\t{\n\t\t\t\tRHISemaphore *pass_semaphore   = m_impl->rhi_context->CreateFrameSemaphore();\n\t\t\t\tRHISemaphore *signal_semaphore = last_backend == \"CUDA\" ? MapToCUDASemaphore(pass_semaphore) : pass_semaphore;\n\t\t\t\tRHISemaphore *wait_semaphore   = last_semaphore ? last_backend == \"CUDA\" ? MapToCUDASemaphore(last_semaphore) : last_semaphore : nullptr;\n\n\t\t\t\tm_impl->rhi_context->Submit(std::move(submit_cmd_buffers), wait_semaphore ? std::vector<RHISemaphore *>{wait_semaphore} : std::vector<RHISemaphore *>{}, {signal_semaphore});\n\t\t\t\tsubmit_cmd_buffers.clear();\n\t\t\t\tlast_semaphore    = pass_semaphore;\n\t\t\t\tlast_queue_family = cmd_buffer->GetQueueFamily();\n\t\t\t}\n\n\t\t\tsubmit_cmd_buffers.push_back(cmd_buffer);\n\t\t}\n\t\tif (!submit_cmd_buffers.empty())\n\t\t{\n\t\t\tm_impl->rhi_context->Submit(std::move(submit_cmd_buffers), last_semaphore ? std::vector<RHISemaphore *>{last_semaphore} : std::vector<RHISemaphore *>{}, {});\n\t\t}\n\t}\n}\n\nconst std::vector<RenderGraph::RenderPassInfo> &RenderGraph::GetRenderPasses() const\n{\n\treturn m_impl->render_passes;\n}\n\nRenderGraph &RenderGraph::AddPass(\n    const std::string &name,\n    const std::string &category,\n    BindPoint          bind_point,\n    const Variant     &config,\n    RenderTask       &&task,\n    BarrierTask      &&barrier)\n{\n\tm_impl->render_passes.emplace_back(RenderPassInfo{\n\t    name,\n\t    category,\n\t    bind_point,\n\t    config,\n\t    std::move(task),\n\t    std::move(barrier),\n\t    m_impl->rhi_context->CreateProfiler(bind_point == BindPoint::CUDA)});\n\treturn *this;\n}\n\nRenderGraph &RenderGraph::AddInitializeBarrier(InitializeBarrierTask &&barrier)\n{\n\tm_impl->initialize_barrier = std::move(barrier);\n\treturn *this;\n}\n\nRenderGraph &RenderGraph::RegisterTexture(const TextureCreateInfo &create_info)\n{\n\tTextureDesc desc    = create_info.desc;\n\tauto       &texture = m_impl->textures.emplace_back(m_impl->rhi_context->CreateTexture(desc));\n\tfor (auto &handle : create_info.handles)\n\t{\n\t\tm_impl->texture_lookup.emplace(handle, texture.get());\n\t}\n\treturn *this;\n}\n\nRenderGraph &RenderGraph::RegisterTexture(const std::vector<TextureCreateInfo> &create_infos)\n{\n\tif (create_infos.size() == 1)\n\t{\n\t\treturn RegisterTexture(create_infos[0]);\n\t}\n\n\tTextureDesc pool_desc = {};\n\tpool_desc.name        = \"Pool Texture \" + std::to_string(m_impl->textures.size());\n\tpool_desc.width       = 0;\n\tpool_desc.width       = 0;\n\tpool_desc.height      = 0;\n\tpool_desc.depth       = 0;\n\tpool_desc.mips        = 0;\n\tpool_desc.layers      = 0;\n\tpool_desc.samples     = 0;\n\tpool_desc.format      = (RHIFormat) 0;\n\tpool_desc.usage       = RHITextureUsage::Transfer | RHITextureUsage::ShaderResource;\n\n\t// Memory alias\n\tfor (auto &info : create_infos)\n\t{\n\t\tpool_desc.width   = std::max(pool_desc.width, info.desc.width);\n\t\tpool_desc.height  = std::max(pool_desc.height, info.desc.height);\n\t\tpool_desc.depth   = std::max(pool_desc.depth, info.desc.depth);\n\t\tpool_desc.mips    = std::max(pool_desc.mips, info.desc.mips);\n\t\tpool_desc.layers  = std::max(pool_desc.layers, info.desc.layers);\n\t\tpool_desc.samples = std::max(pool_desc.samples, info.desc.samples);\n\t\tpool_desc.format  = (RHIFormat) std::max((uint64_t) pool_desc.format, (uint64_t) info.desc.format);\n\t}\n\n\t//m_impl->textures.emplace_back(m_impl->rhi_context->CreateTexture(pool_desc));\n\t//auto pool_texture = m_impl->textures.back().get();\n\n\tfor (auto &info : create_infos)\n\t{\n\t\tTextureDesc desc = info.desc;\n\t\tdesc.usage |= RHITextureUsage::ShaderResource | RHITextureUsage::Transfer;\n\t\tauto &texture = m_impl->textures.emplace_back(m_impl->rhi_context->CreateTexture(desc));\n\t\t//auto &texture = m_impl->textures.emplace_back(pool_texture->Alias(desc));\n\t\tfor (auto &handle : info.handles)\n\t\t{\n\t\t\tm_impl->texture_lookup.emplace(handle, texture.get());\n\t\t}\n\t}\n\n\treturn *this;\n}\n\nRenderGraph &RenderGraph::RegisterBuffer(const BufferCreateInfo &create_info)\n{\n\tBufferDesc desc = create_info.desc;\n\tdesc.usage      = desc.usage | RHIBufferUsage::Transfer | RHIBufferUsage::ConstantBuffer;\n\tauto &buffer    = m_impl->buffers.emplace_back(m_impl->rhi_context->CreateBuffer(desc));\n\tfor (auto &handle : create_info.handles)\n\t{\n\t\tm_impl->buffer_lookup.emplace(handle, buffer.get());\n\t}\n\treturn *this;\n}\n\nRHISemaphore *RenderGraph::MapToCUDASemaphore(RHISemaphore *semaphore)\n{\n\tif (m_impl->cuda_semaphore_map.find(semaphore) != m_impl->cuda_semaphore_map.end())\n\t{\n\t\treturn m_impl->cuda_semaphore_map.at(semaphore).get();\n\t}\n\tm_impl->cuda_semaphore_map.emplace(semaphore, m_impl->rhi_context->MapToCUDASemaphore(semaphore));\n\treturn m_impl->cuda_semaphore_map.at(semaphore).get();\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Private/RenderGraphBlackboard.cpp",
    "content": "#include \"RenderGraphBlackboard.hpp\"\n\nnamespace Ilum\n{\nstd::shared_ptr<void> &RenderGraphBlackboard::Add(std::type_index type, std::shared_ptr<void> &&ptr)\n{\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_mutex);\n\n\t\tif (m_data.find(type) == m_data.end())\n\t\t{\n\t\t\tm_data.emplace(type, std::move(ptr));\n\t\t}\n\t}\n\n\treturn m_data.at(type);\n}\n\nbool RenderGraphBlackboard::Has(std::type_index type)\n{\n\treturn m_data.find(type) != m_data.end();\n}\n\nstd::shared_ptr<void>& RenderGraphBlackboard::Get(std::type_index type)\n{\n\treturn m_data.at(type);\n}\n\nRenderGraphBlackboard &RenderGraphBlackboard::Erase(std::type_index type)\n{\n\tif (Has(type))\n\t{\n\t\tm_data.erase(type);\n\t}\n\treturn *this;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Private/RenderGraphBuilder.cpp",
    "content": "#include \"RenderGraph/RenderGraphBuilder.hpp\"\n\nnamespace Ilum\n{\nRenderGraphBuilder::RenderGraphBuilder(RHIContext *rhi_context) :\n    p_rhi_context(rhi_context)\n{\n}\n\nRenderGraphBuilder &RenderGraphBuilder::AddPass(RenderGraph &render_graph, const std::string &name, const std::string &category, BindPoint bind_point, const Variant &config, RenderGraph::RenderTask &&task, RenderGraph::BarrierTask &&barrier)\n{\n\trender_graph.AddPass(name, category, bind_point, config, std::move(task), std::move(barrier));\n\treturn *this;\n}\n\nbool RenderGraphBuilder::Validate(RenderGraphDesc &desc)\n{\n\tbool result = true;\n\n\tstd::set<size_t> used_pass;\n\tfor (auto &[handle, pass] : desc.GetPasses())\n\t{\n\t\tif (desc.HasLink(handle))\n\t\t{\n\t\t\tused_pass.insert(handle);\n\t\t\tused_pass.insert(desc.GetPass(desc.LinkFrom(handle)).GetHandle());\n\t\t}\n\t}\n\n\tstd::unordered_set<size_t> culling_passes;\n\tfor (auto &[handle, pass] : desc.GetPasses())\n\t{\n\t\tif (used_pass.find(handle) == used_pass.end())\n\t\t{\n\t\t\tLOG_WARN(\"Pass <{}> is not used, culling it\", pass.GetName());\n\t\t\tculling_passes.insert(handle);\n\t\t}\n\t}\n\n\tfor (auto &pass : culling_passes)\n\t{\n\t\tdesc.ErasePass(pass);\n\t}\n\n\tstd::unordered_set<size_t> invalid_resources;\n\tfor (auto &[pass_handle, pass] : desc.GetPasses())\n\t{\n\t\tfor (auto &[pin_handle, pin] : pass.GetPins())\n\t\t{\n\t\t\tif (pin.attribute == RenderPassPin::Attribute::Input &&\n\t\t\t    !desc.HasLink(pin_handle))\n\t\t\t{\n\t\t\t\tinvalid_resources.insert(pin_handle);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (auto &resource : invalid_resources)\n\t{\n\t\tLOG_WARN(\"Input {} is not linked to a source\", resource);\n\t\tresult = false;\n\t}\n\n\treturn result;\n}\n\nstd::unique_ptr<RenderGraph> RenderGraphBuilder::Compile(RenderGraphDesc &desc, Renderer *renderer)\n{\n\t// if (!Validate(desc))\n\t//{\n\t//\tLOG_ERROR(\"Render graph compilation failed!\");\n\t//\treturn nullptr;\n\t// }\n\n\tconst std::unordered_map<BindPoint, RHIQueueFamily> queue_family_map = {\n\t    {BindPoint::None, RHIQueueFamily::Graphics},\n\t    {BindPoint::Rasterization, RHIQueueFamily::Graphics},\n\t    {BindPoint::RayTracing, RHIQueueFamily::Compute},\n\t    {BindPoint::Compute, RHIQueueFamily::Compute},\n\t    {BindPoint::CUDA, RHIQueueFamily::Compute},\n\t};\n\n\tstruct ResourceState\n\t{\n\t\tRHIResourceState rhi_state;\n\t\tRHIQueueFamily   family;\n\n\t\tbool operator==(const ResourceState &lhs)\n\t\t{\n\t\t\treturn this->rhi_state == lhs.rhi_state && this->family == lhs.family;\n\t\t}\n\t};\n\n\t// Sorting passes\n\tstd::vector<size_t> ordered_passes;\n\tordered_passes.reserve(desc.GetPasses().size());\n\n\tstd::vector<size_t> pass_handles;\n\n\tstd::map<size_t, std::map<uint32_t, ResourceState>> resource_lifetime;\n\n\tstd::map<size_t, ResourceState> last_resource_state;\n\n\tfor (auto &[pass_handle, pass] : desc.GetPasses())\n\t{\n\t\tpass_handles.push_back(pass_handle);\n\t\tfor (auto &[pin_handle, pin] : pass.GetPins())\n\t\t{\n\t\t\tif (pin.attribute == RenderPassPin::Attribute::Output)\n\t\t\t{\n\t\t\t\tlast_resource_state[pin_handle] = ResourceState{RHIResourceState::Undefined, queue_family_map.at(pass.GetBindPoint())};\n\t\t\t}\n\t\t}\n\t}\n\n\tstd::vector<std::map<size_t, std::pair<ResourceState, ResourceState>>> resource_states;\n\n\tstruct PassSemaphore\n\t{\n\t\tstd::vector<RHISemaphore *> wait_semaphores;\n\t\tstd::vector<RHISemaphore *> signal_semaphores;\n\t};\n\n\tstd::map<size_t, PassSemaphore> pass_semaphores;        // [signal - wait]\n\n\tRenderGraphDesc tmp_desc = desc;\n\n\tstd::set<size_t> collected_passes;\n\n\t// Create new render graph\n\tstd::unique_ptr<RenderGraph> render_graph = std::make_unique<RenderGraph>(p_rhi_context);\n\n\twhile (!pass_handles.empty())\n\t{\n\t\tuint32_t pass_idx = static_cast<uint32_t>(ordered_passes.size());\n\n\t\tfor (auto iter = pass_handles.begin(); iter != pass_handles.end();)\n\t\t{\n\t\t\tauto &pass = desc.GetPass(*iter);\n\n\t\t\tif (!desc.HasLink(pass.GetHandle()) ||\n\t\t\t    collected_passes.find(desc.LinkFrom(pass.GetHandle())) != collected_passes.end())\n\t\t\t{\n\t\t\t\tstd::map<size_t, std::pair<ResourceState, ResourceState>> pass_resource_state;\n\n\t\t\t\tfor (auto &[pin_handle, pin] : pass.GetPins())\n\t\t\t\t{\n\t\t\t\t\tsize_t resource_pin = (pin.attribute == RenderPassPin::Attribute::Output) ? pin_handle : (desc.HasLink(pin_handle) ? desc.LinkFrom(pin_handle) : ~0ull);\n\t\t\t\t\tif (resource_pin == ~0ull)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tResourceState resource_state = ResourceState{pin.resource_state, queue_family_map.at(pass.GetBindPoint())};\n\n\t\t\t\t\t// Record resource state\n\t\t\t\t\tif (pass.GetBindPoint() != BindPoint::CUDA)\n\t\t\t\t\t{\n\t\t\t\t\t\tpass_resource_state[resource_pin]         = std::make_pair(last_resource_state[resource_pin], resource_state);\n\t\t\t\t\t\tlast_resource_state[resource_pin]         = resource_state;\n\t\t\t\t\t\tresource_lifetime[resource_pin][pass_idx] = resource_state;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tResourceState state = last_resource_state.find(resource_pin) != last_resource_state.end() ? last_resource_state[resource_pin] : ResourceState{RHIResourceState::Undefined, RHIQueueFamily::Graphics};\n\n\t\t\t\t\t\tresource_lifetime[resource_pin][pass_idx] = state;\n\t\t\t\t\t\tpass_resource_state[resource_pin]         = std::make_pair(state, state);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set resource info\n\t\t\t\t\tauto &resource = desc.GetPass(resource_pin).GetPin(resource_pin);\n\t\t\t\t\tif (resource.type == RenderPassPin::Type::Texture)\n\t\t\t\t\t{\n\t\t\t\t\t\tresource.texture.usage |= ResourceStateToTextureUsage(resource_state.rhi_state) | RHITextureUsage::Transfer;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tresource.buffer.usage |= ResourceStateToBufferUsage(resource_state.rhi_state) | RHIBufferUsage::Transfer;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Add pass\n\t\t\t\tresource_states.push_back(pass_resource_state);\n\t\t\t\tordered_passes.push_back(pass.GetHandle());\n\t\t\t\tcollected_passes.insert(pass.GetHandle());\n\t\t\t\tpass_handles.erase(iter);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\titer++;\n\t\t\t}\n\t\t}\n\t}\n\n\tstd::set<size_t> alias_textures;\n\n\t// Register resource\n\t{\n\t\t// Collect texture alias info\n\t\tstruct TexturePool\n\t\t{\n\t\t\tstd::vector<size_t> handles;\n\n\t\t\tuint32_t start;\n\t\t\tuint32_t end;\n\t\t};\n\n\t\tstd::vector<TexturePool> texture_pools;\n\n\t\tfor (auto &[handle, resource_states] : resource_lifetime)\n\t\t{\n\t\t\tconst auto &resource = desc.GetPass(handle).GetPin(handle);\n\t\t\tif (resource.type == RenderPassPin::Type::Texture)\n\t\t\t{\n\t\t\t\tbool alias = false;\n\t\t\t\tfor (auto &pool : texture_pools)\n\t\t\t\t{\n\t\t\t\t\tif (pool.start > (--resource_states.end())->first ||\n\t\t\t\t\t    pool.end < resource_states.begin()->first)\n\t\t\t\t\t{\n\t\t\t\t\t\tpool.handles.push_back(handle);\n\t\t\t\t\t\tpool.start = std::min(pool.start, (--resource_states.end())->first);\n\t\t\t\t\t\tpool.end   = std::max(pool.end, resource_states.begin()->first);\n\t\t\t\t\t\talias      = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!alias)\n\t\t\t\t{\n\t\t\t\t\ttexture_pools.push_back(TexturePool{{handle}, resource_states.begin()->first, (--resource_states.end())->first});\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstd::set<size_t> handles = desc.LinkTo(handle);\n\t\t\t\thandles.insert(handle);\n\t\t\t\trender_graph->RegisterBuffer(RenderGraph::BufferCreateInfo{resource.buffer, handles});\n\t\t\t}\n\t\t}\n\n\t\tfor (auto &pool : texture_pools)\n\t\t{\n\t\t\tstd::vector<RenderGraph::TextureCreateInfo> texture_create_infos;\n\t\t\ttexture_create_infos.reserve(pool.handles.size());\n\t\t\tfor (auto &handle : pool.handles)\n\t\t\t{\n\t\t\t\tconst auto      &resource = desc.GetPass(handle).GetPin(handle);\n\t\t\t\tstd::set<size_t> handles  = desc.LinkTo(handle);\n\t\t\t\thandles.insert(handle);\n\t\t\t\ttexture_create_infos.push_back(RenderGraph::TextureCreateInfo{resource.texture, handles});\n\t\t\t\tif (pool.handles.size() > 1)\n\t\t\t\t{\n\t\t\t\t\talias_textures.insert(handle);\n\t\t\t\t}\n\t\t\t}\n\t\t\trender_graph->RegisterTexture(texture_create_infos);\n\t\t}\n\t}\n\n\t// Resource state tracking\n\tfor (auto &resource_state : resource_states)\n\t{\n\t\tfor (auto &[resource_handle, state_transition] : resource_state)\n\t\t{\n\t\t\tauto &[src, dst] = state_transition;\n\t\t\tif (src.rhi_state == RHIResourceState::Undefined)\n\t\t\t{\n\t\t\t\tif (alias_textures.find(resource_handle) == alias_textures.end())\n\t\t\t\t{\n\t\t\t\t\tsrc = (--resource_lifetime[resource_handle].end())->second;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Initialize Barrier\n\t{\n\t\tstd::vector<BufferStateTransition>  buffer_state_transitions;\n\t\tstd::vector<TextureStateTransition> texture_state_transitions;\n\n\t\tfor (auto &[handle, resource_states] : resource_lifetime)\n\t\t{\n\t\t\tconst auto &resource = desc.GetPass(handle).GetPin(handle);\n\t\t\tif ((--resource_states.end())->second.rhi_state != RHIResourceState::Undefined)\n\t\t\t{\n\t\t\t\tif (resource.type == RenderPassPin::Type::Texture)\n\t\t\t\t{\n\t\t\t\t\tauto *texture = render_graph->GetTexture(handle);\n\n\t\t\t\t\tconst auto &texture_desc = texture->GetDesc();\n\n\t\t\t\t\ttexture_state_transitions.push_back(TextureStateTransition{\n\t\t\t\t\t    texture,\n\t\t\t\t\t    RHIResourceState::Undefined,\n\t\t\t\t\t    (--resource_states.end())->second.rhi_state,\n\t\t\t\t\t    TextureRange{\n\t\t\t\t\t        GetTextureDimension(texture_desc.width, texture_desc.height, texture_desc.depth, texture_desc.layers),\n\t\t\t\t\t        0,\n\t\t\t\t\t        texture_desc.mips,\n\t\t\t\t\t        0,\n\t\t\t\t\t        texture_desc.layers},\n\t\t\t\t\t    (--resource_states.end())->second.family,\n\t\t\t\t\t    (--resource_states.end())->second.family});\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tauto *buffer = render_graph->GetBuffer(handle);\n\n\t\t\t\t\tconst auto &buffer_desc = buffer->GetDesc();\n\n\t\t\t\t\tbuffer_state_transitions.push_back(BufferStateTransition{\n\t\t\t\t\t    buffer,\n\t\t\t\t\t    RHIResourceState::Undefined,\n\t\t\t\t\t    (--resource_states.end())->second.rhi_state});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trender_graph->AddInitializeBarrier([=](RenderGraph &render_graph, RHICommand *graphics_cmd_buffer, RHICommand *compute_cmd_buffer) {\n\t\t\tstd::vector<TextureStateTransition> graphics_texture_transitions;\n\t\t\tstd::vector<TextureStateTransition> compute_texture_transitions;\n\t\t\tfor (auto &transition : texture_state_transitions)\n\t\t\t{\n\t\t\t\tif (transition.dst_family == RHIQueueFamily::Compute)\n\t\t\t\t{\n\t\t\t\t\tcompute_texture_transitions.push_back(transition);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tgraphics_texture_transitions.push_back(transition);\n\t\t\t\t}\n\t\t\t}\n\t\t\tgraphics_cmd_buffer->ResourceStateTransition(graphics_texture_transitions, buffer_state_transitions);\n\t\t\tcompute_cmd_buffer->ResourceStateTransition(compute_texture_transitions, {});\n\t\t});\n\t}\n\n\tstruct ResourceStateTransitionInfo\n\t{\n\t\tsize_t           handle;\n\t\tRHIResourceState src_state;\n\t\tRHIResourceState dst_state;\n\t};\n\n\tfor (uint32_t i = 0; i < ordered_passes.size(); i++)\n\t{\n\t\tconst auto &pass = desc.GetPass(ordered_passes[i]);\n\n\t\tstd::vector<ResourceStateTransitionInfo> buffer_state_transition_infos;\n\t\tstd::vector<ResourceStateTransitionInfo> texture_state_transition_infos;\n\n\t\tfor (auto &[handle, resource_transition] : resource_states[i])\n\t\t{\n\t\t\tconst auto &resource = desc.GetPass(handle).GetPin(handle);\n\n\t\t\tif (resource_transition.first == resource_transition.second)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (resource.type == RenderPassPin::Type::Texture)\n\t\t\t{\n\t\t\t\ttexture_state_transition_infos.push_back(ResourceStateTransitionInfo{\n\t\t\t\t    handle,\n\t\t\t\t    resource_transition.first.rhi_state,\n\t\t\t\t    resource_transition.second.rhi_state});\n\n\t\t\t\t/*texture_state_transitions.push_back(TextureStateTransition{\n\t\t\t\t    texture,\n\t\t\t\t    resource_transition.first.rhi_state,\n\t\t\t\t    resource_transition.second.rhi_state,\n\t\t\t\t    TextureRange{\n\t\t\t\t        GetTextureDimension(texture_desc.width, texture_desc.height, texture_desc.depth, texture_desc.layers),\n\t\t\t\t        0,\n\t\t\t\t        texture_desc.mips,\n\t\t\t\t        0,\n\t\t\t\t        texture_desc.layers},\n\t\t\t\t    i == 0 ? resource_transition.second.family : resource_transition.first.family,\n\t\t\t\t    resource_transition.second.family});*/\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbuffer_state_transition_infos.push_back(ResourceStateTransitionInfo{\n\t\t\t\t    handle,\n\t\t\t\t    resource_transition.first.rhi_state,\n\t\t\t\t    resource_transition.second.rhi_state});\n\n\t\t\t\t// buffer_state_transitions.push_back(BufferStateTransition{\n\t\t\t\t//     buffer,\n\t\t\t\t//     resource_transition.first.rhi_state,\n\t\t\t\t//     resource_transition.second.rhi_state});\n\t\t\t}\n\t\t}\n\n\t\tRenderGraph::RenderTask render_task;\n\n\t\tPluginManager::GetInstance().Call(fmt::format(\"shared/RenderPass/RenderPass.{}.{}.dll\", pass.GetCategory(), pass.GetName()), \"CreateCallback\", &render_task, pass, *this, renderer);\n\n\t\trender_graph->AddPass(\n\t\t    pass.GetName(),\n\t\t    pass.GetCategory(),\n\t\t    pass.GetBindPoint(),\n\t\t    pass.GetConfig(),\n\t\t    std::move(render_task),\n\t\t    [=](RenderGraph &render_graph, RHICommand *cmd_buffer) {\n\t\t\t    std::vector<BufferStateTransition>  buffer_state_transitions(buffer_state_transition_infos.size());\n\t\t\t    std::vector<TextureStateTransition> texture_state_transitions(texture_state_transition_infos.size());\n\n\t\t\t    std::transform(\n\t\t\t        texture_state_transition_infos.begin(),\n\t\t\t        texture_state_transition_infos.end(),\n\t\t\t        texture_state_transitions.begin(),\n\t\t\t        [&](const ResourceStateTransitionInfo &info) {\n\t\t\t\t        auto       *texture = render_graph.GetTexture(info.handle);\n\t\t\t\t        const auto &desc    = texture->GetDesc();\n\t\t\t\t        return TextureStateTransition{\n\t\t\t\t            texture,\n\t\t\t\t            info.src_state,\n\t\t\t\t            info.dst_state,\n\t\t\t\t            TextureRange{\n\t\t\t\t                GetTextureDimension(desc.width, desc.height, desc.depth, desc.layers),\n\t\t\t\t                0,\n\t\t\t\t                desc.mips,\n\t\t\t\t                0,\n\t\t\t\t                desc.layers}};\n\t\t\t        });\n\n\t\t\t    std::transform(\n\t\t\t        buffer_state_transition_infos.begin(),\n\t\t\t        buffer_state_transition_infos.end(),\n\t\t\t        buffer_state_transitions.begin(),\n\t\t\t        [&](const ResourceStateTransitionInfo &info) {\n\t\t\t\t        auto       *buffer = render_graph.GetBuffer(info.handle);\n\t\t\t\t        const auto &desc   = buffer->GetDesc();\n\t\t\t\t        return BufferStateTransition{\n\t\t\t\t            buffer,\n\t\t\t\t            info.src_state,\n\t\t\t\t            info.dst_state};\n\t\t\t        });\n\n\t\t\t    cmd_buffer->ResourceStateTransition(texture_state_transitions, buffer_state_transitions);\n\t\t    });\n\t}\n\n\treturn render_graph;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Private/RenderPass.cpp",
    "content": "#include \"RenderPass.hpp\"\n\nnamespace Ilum\n{\nRenderPassDesc &RenderPassDesc::SetName(const std::string &name)\n{\n\tm_name = name;\n\treturn *this;\n}\n\nRenderPassDesc &RenderPassDesc::SetCategory(const std::string &category)\n{\n\tm_category = category;\n\treturn *this;\n}\n\nRenderPassDesc &RenderPassDesc::SetHandle(size_t handle)\n{\n\tm_handle = handle;\n\treturn *this;\n}\n\nRenderPassDesc &RenderPassDesc::WriteTexture2D(size_t handle, const std::string &name, RHIFormat format, RHIResourceState resource_state, uint32_t width, uint32_t height, uint32_t layer, uint32_t mips)\n{\n\tRenderPassPin pin;\n\tpin.type           = RenderPassPin::Type::Texture;\n\tpin.attribute      = RenderPassPin::Attribute::Output;\n\tpin.name           = name;\n\tpin.handle         = handle;\n\tpin.texture        = TextureDesc{name, width, height, 1, mips, layer, 1, format, RHITextureUsage::Undefined};\n\tpin.resource_state = resource_state;\n\n\tm_pins.emplace(handle, pin);\n\tm_pin_indices.emplace(name, handle);\n\treturn *this;\n}\n\nRenderPassDesc &RenderPassDesc::ReadTexture2D(size_t handle, const std::string &name, RHIResourceState resource_state)\n{\n\tRenderPassPin pin;\n\tpin.type           = RenderPassPin::Type::Texture;\n\tpin.attribute      = RenderPassPin::Attribute::Input;\n\tpin.name           = name;\n\tpin.handle         = handle;\n\tpin.texture        = TextureDesc{name, 1, 1, 1, 1, 1, 1, RHIFormat::Undefined, RHITextureUsage::Undefined};\n\tpin.resource_state = resource_state;\n\n\tm_pins.emplace(handle, pin);\n\tm_pin_indices.emplace(name, handle);\n\treturn *this;\n}\n\nRenderPassDesc &RenderPassDesc::WriteBuffer(size_t handle, const std::string &name, size_t size, RHIResourceState resource_state)\n{\n\tRenderPassPin pin;\n\tpin.type           = RenderPassPin::Type::Buffer;\n\tpin.attribute      = RenderPassPin::Attribute::Output;\n\tpin.name           = name;\n\tpin.handle         = handle;\n\tpin.buffer         = BufferDesc{name, RHIBufferUsage::UnorderedAccess | RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::GPU_Only, size, 0, 0};\n\tpin.resource_state = resource_state;\n\n\tm_pins.emplace(handle, pin);\n\tm_pin_indices.emplace(name, handle);\n\treturn *this;\n}\n\nRenderPassDesc &RenderPassDesc::ReadBuffer(size_t handle, const std::string &name, RHIResourceState resource_state)\n{\n\tRenderPassPin pin;\n\tpin.type           = RenderPassPin::Type::Buffer;\n\tpin.attribute      = RenderPassPin::Attribute::Input;\n\tpin.name           = name;\n\tpin.handle         = handle;\n\tpin.buffer         = BufferDesc{name, RHIBufferUsage::UnorderedAccess | RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::GPU_Only, 0, 0, 0};\n\tpin.resource_state = resource_state;\n\n\tm_pins.emplace(handle, pin);\n\tm_pin_indices.emplace(name, handle);\n\treturn *this;\n}\n\nconst RenderPassPin &RenderPassDesc::GetPin(size_t handle) const\n{\n\treturn m_pins.at(handle);\n}\n\nRenderPassPin &RenderPassDesc::GetPin(size_t handle)\n{\n\treturn m_pins.at(handle);\n}\n\nRenderPassPin &RenderPassDesc::GetPin(const std::string &name)\n{\n\treturn m_pins.at(m_pin_indices.at(name));\n}\n\nconst RenderPassPin &RenderPassDesc::GetPin(const std::string &name) const\n{\n\treturn m_pins.at(m_pin_indices.at(name));\n}\n\nRenderPassDesc &RenderPassDesc::SetConfig(Variant config)\n{\n\tm_config = config;\n\treturn *this;\n}\n\nconst Variant &RenderPassDesc::GetConfig() const\n{\n\treturn m_config;\n}\n\nconst std::string &RenderPassDesc::GetName() const\n{\n\treturn m_name;\n}\n\nconst std::string &RenderPassDesc::GetCategory() const\n{\n\treturn m_category;\n}\n\nstd::map<size_t, RenderPassPin> &RenderPassDesc::GetPins()\n{\n\treturn m_pins;\n}\n\nsize_t RenderPassDesc::GetHandle() const\n{\n\treturn m_handle;\n}\n\nBindPoint RenderPassDesc::GetBindPoint() const\n{\n\treturn m_bind_point;\n}\n\nRenderPassDesc &RenderPassDesc::SetBindPoint(BindPoint bind_point)\n{\n\tm_bind_point = bind_point;\n\treturn *this;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Public/RenderGraph/Impl/RenderGraphBuilder.inl",
    "content": "//#pragma once\n//\n//#include \"../RenderGraphBuilder.hpp\"\n//\n//#include <Core/Plugin.hpp>\n//\n//#include <set>\n//\n//namespace Ilum\n//{\n//template <typename... Args>\n//std::unique_ptr<RenderGraph> RenderGraphBuilder::Compile(RenderGraphDesc &desc, Args &&...args)\n//{\n//\tif (!Validate(desc))\n//\t{\n//\t\tLOG_ERROR(\"Render graph compilation failed!\");\n//\t\treturn nullptr;\n//\t}\n//\n//\t// Sorting passes\n//\tstd::vector<RenderPassDesc> ordered_passes;\n//\tordered_passes.reserve(desc.passes.size());\n//\n//\tstd::vector<RGHandle> pass_handles;\n//\n//\tstd::map<RGHandle, std::map<uint32_t, RHIResourceState>> resource_lifetime;\n//\tstd::map<RGHandle, RHIResourceState>                     last_resource_state;\n//\tfor (auto &[texture_handle, texture_desc] : desc.textures)\n//\t{\n//\t\tlast_resource_state[texture_handle] = RHIResourceState::Undefined;\n//\t}\n//\tfor (auto &[buffer_handle, buffer_desc] : desc.buffers)\n//\t{\n//\t\tlast_resource_state[buffer_handle] = RHIResourceState::Undefined;\n//\t}\n//\n//\tstd::vector<std::map<RGHandle, std::pair<RHIResourceState, RHIResourceState>>> resource_states;\n//\n//\tstruct PassSemaphore\n//\t{\n//\t\tstd::vector<RHISemaphore *> wait_semaphores;\n//\t\tstd::vector<RHISemaphore *> signal_semaphores;\n//\t};\n//\n//\tstd::map<RGHandle, PassSemaphore> pass_semaphores;        // [signal - wait]\n//\n//\tRenderGraphDesc tmp_desc = desc;\n//\n//\tstd::set<RGHandle> collected_passes;\n//\n//\t// Create new render graph\n//\tstd::unique_ptr<RenderGraph> render_graph = std::make_unique<RenderGraph>(p_rhi_context);\n//\n//\twhile (!tmp_desc.passes.empty())\n//\t{\n//\t\tuint32_t pass_idx = static_cast<uint32_t>(ordered_passes.size());\n//\n//\t\tfor (auto iter = tmp_desc.passes.begin(); iter != tmp_desc.passes.end();)\n//\t\t{\n//\t\t\tif (!iter->second.prev_pass.IsValid() || collected_passes.find(iter->second.prev_pass) != collected_passes.end())\n//\t\t\t{\n//\t\t\t\t// Select pass\n//\t\t\t\tstd::map<RGHandle, std::pair<RHIResourceState, RHIResourceState>> pass_resource_state;\n//\t\t\t\tfor (auto &[name, resource] : iter->second.resources)\n//\t\t\t\t{\n//\t\t\t\t\tif (resource.handle.IsValid())\n//\t\t\t\t\t{\n//\t\t\t\t\t\t// Record resource state\n//\t\t\t\t\t\tif (iter->second.bind_point != BindPoint::CUDA)\n//\t\t\t\t\t\t{\n//\t\t\t\t\t\t\tlast_resource_state[resource.handle]         = resource.state;\n//\t\t\t\t\t\t\tresource_lifetime[resource.handle][pass_idx] = resource.state;\n//\t\t\t\t\t\t\tpass_resource_state[resource.handle]         = std::make_pair(last_resource_state[resource.handle], resource.state);\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telse\n//\t\t\t\t\t\t{\n//\t\t\t\t\t\t\tRHIResourceState state = last_resource_state.find(resource.handle) != last_resource_state.end() ? last_resource_state[resource.handle] : RHIResourceState::Undefined;\n//\n//\t\t\t\t\t\t\tresource_lifetime[resource.handle][pass_idx] = state;\n//\t\t\t\t\t\t\tpass_resource_state[resource.handle]         = std::make_pair(state, state);\n//\t\t\t\t\t\t}\n//\n//\t\t\t\t\t\t// Set resource info\n//\t\t\t\t\t\tif (desc.textures.find(resource.handle) != desc.textures.end())\n//\t\t\t\t\t\t{\n//\t\t\t\t\t\t\tdesc.textures[resource.handle].usage |= ResourceStateToTextureUsage(resource.state);\n//\t\t\t\t\t\t}\n//\t\t\t\t\t\telse if (desc.buffers.find(resource.handle) != desc.buffers.end())\n//\t\t\t\t\t\t{\n//\t\t\t\t\t\t\tdesc.buffers[resource.handle].usage |= ResourceStateToBufferUsage(resource.state);\n//\t\t\t\t\t\t}\n//\t\t\t\t\t}\n//\t\t\t\t}\n//\n//\t\t\t\t// Add pass\n//\t\t\t\tresource_states.push_back(pass_resource_state);\n//\t\t\t\tordered_passes.push_back(iter->second);\n//\t\t\t\tpass_handles.push_back(iter->first);\n//\t\t\t\tcollected_passes.insert(iter->first);\n//\n//\t\t\t\titer = tmp_desc.passes.erase(iter);\n//\t\t\t\tbreak;\n//\t\t\t}\n//\t\t\telse\n//\t\t\t{\n//\t\t\t\titer++;\n//\t\t\t}\n//\t\t}\n//\t}\n//\n//\tstd::set<RGHandle> alias_textures;\n//\n//\t// Register resource\n//\t{\n//\t\t// Collect texture alias info\n//\t\tstruct TexturePool\n//\t\t{\n//\t\t\tstd::vector<RGHandle> handles;\n//\n//\t\t\tuint32_t start;\n//\t\t\tuint32_t end;\n//\t\t};\n//\n//\t\tstd::vector<TexturePool> texture_pools;\n//\n//\t\tfor (auto &[handle, resource] : resource_lifetime)\n//\t\t{\n//\t\t\tif (desc.textures.find(handle) != desc.textures.end())\n//\t\t\t{\n//\t\t\t\tbool alias = false;\n//\t\t\t\tfor (auto &pool : texture_pools)\n//\t\t\t\t{\n//\t\t\t\t\tif (pool.start > (--resource.end())->first ||\n//\t\t\t\t\t    pool.end < resource.begin()->first)\n//\t\t\t\t\t{\n//\t\t\t\t\t\tpool.handles.push_back(handle);\n//\t\t\t\t\t\tpool.start = std::min(pool.start, (--resource.end())->first);\n//\t\t\t\t\t\tpool.end   = std::max(pool.end, resource.begin()->first);\n//\t\t\t\t\t\talias      = true;\n//\t\t\t\t\t\tbreak;\n//\t\t\t\t\t}\n//\t\t\t\t}\n//\t\t\t\tif (!alias)\n//\t\t\t\t{\n//\t\t\t\t\ttexture_pools.push_back(TexturePool{{handle}, resource.begin()->first, (--resource.end())->first});\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\telse\n//\t\t\t{\n//\t\t\t\trender_graph->RegisterBuffer(RenderGraph::BufferCreateInfo{desc.buffers[handle], handle});\n//\t\t\t}\n//\t\t}\n//\n//\t\tfor (auto &pool : texture_pools)\n//\t\t{\n//\t\t\tstd::vector<RenderGraph::TextureCreateInfo> texture_create_infos;\n//\t\t\ttexture_create_infos.reserve(pool.handles.size());\n//\t\t\tfor (auto &handle : pool.handles)\n//\t\t\t{\n//\t\t\t\ttexture_create_infos.push_back(RenderGraph::TextureCreateInfo{desc.textures[handle], handle});\n//\t\t\t\tif (pool.handles.size() > 1)\n//\t\t\t\t{\n//\t\t\t\t\talias_textures.insert(handle);\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\trender_graph->RegisterTexture(texture_create_infos);\n//\t\t}\n//\t}\n//\n//\t// Resource state tracking\n//\tfor (auto &resource_state : resource_states)\n//\t{\n//\t\tfor (auto &[resource_handle, state_transition] : resource_state)\n//\t\t{\n//\t\t\tauto &[src, dst] = state_transition;\n//\t\t\tif (src == RHIResourceState::Undefined)\n//\t\t\t{\n//\t\t\t\tif (alias_textures.find(resource_handle) == alias_textures.end())\n//\t\t\t\t{\n//\t\t\t\t\tsrc = (--resource_lifetime[resource_handle].end())->second;\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\t}\n//\n//\t// Initialize Barrier\n//\t{\n//\t\tstd::vector<BufferStateTransition>  buffer_state_transitions;\n//\t\tstd::vector<TextureStateTransition> texture_state_transitions;\n//\n//\t\tfor (auto &[handle, resource] : resource_lifetime)\n//\t\t{\n//\t\t\tif ((--resource.end())->second != RHIResourceState::Undefined)\n//\t\t\t{\n//\t\t\t\tif (desc.textures.find(handle) != desc.textures.end())\n//\t\t\t\t{\n//\t\t\t\t\tauto *texture = render_graph->GetTexture(handle);\n//\n//\t\t\t\t\tconst auto &texture_desc = texture->GetDesc();\n//\n//\t\t\t\t\ttexture_state_transitions.push_back(TextureStateTransition{\n//\t\t\t\t\t    texture,\n//\t\t\t\t\t    RHIResourceState::Undefined,\n//\t\t\t\t\t    (--resource.end())->second,\n//\t\t\t\t\t    TextureRange{\n//\t\t\t\t\t        GetTextureDimension(texture_desc.width, texture_desc.height, texture_desc.depth, texture_desc.layers),\n//\t\t\t\t\t        0,\n//\t\t\t\t\t        texture_desc.mips,\n//\t\t\t\t\t        0,\n//\t\t\t\t\t        texture_desc.layers}});\n//\t\t\t\t}\n//\t\t\t\telse\n//\t\t\t\t{\n//\t\t\t\t\tauto *buffer = render_graph->GetBuffer(handle);\n//\n//\t\t\t\t\tconst auto &buffer_desc = buffer->GetDesc();\n//\n//\t\t\t\t\tbuffer_state_transitions.push_back(BufferStateTransition{\n//\t\t\t\t\t    buffer,\n//\t\t\t\t\t    RHIResourceState::Undefined,\n//\t\t\t\t\t    (--resource.end())->second});\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\n//\t\trender_graph->AddInitializeBarrier([=](RenderGraph &render_graph, RHICommand *cmd_buffer) {\n//\t\t\tcmd_buffer->ResourceStateTransition(texture_state_transitions, buffer_state_transitions);\n//\t\t});\n//\t}\n//\n//\tfor (uint32_t i = 0; i < ordered_passes.size(); i++)\n//\t{\n//\t\tconst auto &pass = ordered_passes[i];\n//\n//\t\tstd::vector<BufferStateTransition>  buffer_state_transitions;\n//\t\tstd::vector<TextureStateTransition> texture_state_transitions;\n//\n//\t\tfor (auto &[handle, resource_transition] : resource_states[i])\n//\t\t{\n//\t\t\tif (resource_transition.first == resource_transition.second)\n//\t\t\t{\n//\t\t\t\tcontinue;\n//\t\t\t}\n//\n//\t\t\tif (desc.textures.find(handle) != desc.textures.end())\n//\t\t\t{\n//\t\t\t\tauto *texture = render_graph->GetTexture(handle);\n//\n//\t\t\t\tconst auto &texture_desc = texture->GetDesc();\n//\n//\t\t\t\ttexture_state_transitions.push_back(TextureStateTransition{\n//\t\t\t\t    texture,\n//\t\t\t\t    resource_transition.first,\n//\t\t\t\t    resource_transition.second,\n//\t\t\t\t    TextureRange{\n//\t\t\t\t        GetTextureDimension(texture_desc.width, texture_desc.height, texture_desc.depth, texture_desc.layers),\n//\t\t\t\t        0,\n//\t\t\t\t        texture_desc.mips,\n//\t\t\t\t        0,\n//\t\t\t\t        texture_desc.layers}});\n//\t\t\t}\n//\t\t\telse\n//\t\t\t{\n//\t\t\t\tauto *buffer = render_graph->GetBuffer(handle);\n//\n//\t\t\t\tconst auto &buffer_desc = buffer->GetDesc();\n//\n//\t\t\t\tbuffer_state_transitions.push_back(BufferStateTransition{\n//\t\t\t\t    buffer,\n//\t\t\t\t    resource_transition.first,\n//\t\t\t\t    resource_transition.second});\n//\t\t\t}\n//\t\t}\n//\n//\t\tRenderGraph::RenderTask render_task;\n//\n//\t\tPluginManager::GetInstance().Call(fmt::format(\"shared/RenderPass/RenderPass.{}.dll\", pass.name), \"CreateCallback\", &render_task, pass, *this, std::forward<Args>(args)...);\n//\n//\t\trender_graph->AddPass(\n//\t\t    pass.name,\n//\t\t    pass.bind_point,\n//\t\t    pass.config,\n//\t\t    std::move(render_task),\n//\t\t    [=](RenderGraph &render_graph, RHICommand *cmd_buffer) {\n//\t\t\t    cmd_buffer->ResourceStateTransition(texture_state_transitions, buffer_state_transitions);\n//\t\t    });\n//\t}\n//\n//\treturn render_graph;\n//}\n//}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Public/RenderGraph/Precompile.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Public/RenderGraph/RenderGraph.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n#include \"RenderPass.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass RenderGraphBlackboard;\n\nclass  RenderGraphDesc\n{\n  public:\n\tRenderGraphDesc() = default;\n\n\t~RenderGraphDesc() = default;\n\n\tRenderGraphDesc &SetName(const std::string &name);\n\n\tRenderGraphDesc &AddPass(size_t handle, RenderPassDesc &&desc);\n\n\tvoid ErasePass(size_t handle);\n\n\tvoid EraseLink(size_t source, size_t target);\n\n\tRenderGraphDesc &Link(size_t source, size_t target);\n\n\tbool HasLink(size_t target) const;\n\n\tsize_t LinkFrom(size_t target) const;\n\n\tstd::set<size_t> LinkTo(size_t source) const;\n\n\tbool HasPass(size_t handle) const;\n\n\tRenderPassDesc &GetPass(size_t handle);\n\n\tconst std::string &GetName() const;\n\n\tstd::map<size_t, RenderPassDesc> &GetPasses();\n\n\tconst std::map<size_t, size_t> &GetEdges() const;\n\n\tvoid Clear();\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(m_name, m_passes, m_edges, m_pass_lookup);\n\t}\n\n  private:\n\tstd::string m_name;\n\n\tstd::map<size_t, RenderPassDesc> m_passes;\n\n\tstd::map<size_t, size_t> m_edges;        // Target - Source\n\n\tstd::map<size_t, size_t> m_pass_lookup;        // Pin ID - Node ID\n};\n\nclass  RenderGraph\n{\n\tfriend class RenderGraphBuilder;\n\n  public:\n\tusing RenderTask  = std::function<void(RenderGraph &, RHICommand *, Variant &, RenderGraphBlackboard &)>;\n\tusing BarrierTask = std::function<void(RenderGraph &, RHICommand *)>;\n\tusing InitializeBarrierTask = std::function<void(RenderGraph &, RHICommand *, RHICommand *)>;\n\n\tstruct RenderPassInfo\n\t{\n\t\tstd::string name;\n\t\tstd::string category;\n\n\t\tBindPoint bind_point;\n\n\t\tVariant config;\n\n\t\tRenderTask  execute;\n\t\tBarrierTask barrier;\n\n\t\tstd::unique_ptr<RHIProfiler> profiler = nullptr;\n\t};\n\n  public:\n\tRenderGraph(RHIContext *rhi_context);\n\n\t~RenderGraph();\n\n\t// Return the old one\n\tstd::unique_ptr<RHITexture> SetTexture(size_t handle, std::unique_ptr<RHITexture> &&texture);\n\n\tRHITexture *GetTexture(size_t handle);\n\n\tRHIBuffer *GetBuffer(size_t handle);\n\n\tRHITexture *GetCUDATexture(size_t handle);\n\n\tvoid Execute(RenderGraphBlackboard &black_board);\n\n\tconst std::vector<RenderPassInfo> &GetRenderPasses() const;\n\n  private:\n\tstruct TextureCreateInfo\n\t{\n\t\tTextureDesc      desc;\n\t\tstd::set<size_t> handles;\n\t};\n\n\tstruct BufferCreateInfo\n\t{\n\t\tBufferDesc       desc;\n\t\tstd::set<size_t> handles;\n\t};\n\n\tRenderGraph &AddPass(\n\t    const std::string &name,\n\t    const std::string &category,\n\t    BindPoint          bind_point,\n\t    const Variant     &config,\n\t    RenderTask       &&execute,\n\t    BarrierTask      &&barrier);\n\n\tRenderGraph &AddInitializeBarrier(InitializeBarrierTask &&barrier);\n\n\t// Without memory alias\n\tRenderGraph &RegisterTexture(const TextureCreateInfo &create_infos);\n\n\t// With memory alias\n\tRenderGraph &RegisterTexture(const std::vector<TextureCreateInfo> &create_info);\n\n\tRenderGraph &RegisterBuffer(const BufferCreateInfo &create_info);\n\n\tRHISemaphore *MapToCUDASemaphore(RHISemaphore *semaphore);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Public/RenderGraph/RenderGraphBlackboard.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\nnamespace Ilum\n{\nclass RenderGraphBlackboard\n{\n  public:\n\tRenderGraphBlackboard() = default;\n\n\t~RenderGraphBlackboard() = default;\n\n\ttemplate <typename _Ty>\n\t_Ty *Add()\n\t{\n\t\treturn std::static_pointer_cast<_Ty>(Add(typeid(_Ty), std::make_shared<_Ty>())).get();\n\t}\n\n\ttemplate <typename _Ty>\n\tbool Has()\n\t{\n\t\treturn Has(typeid(_Ty));\n\t}\n\n\ttemplate <typename _Ty>\n\t_Ty *Get()\n\t{\n\t\tif (!Has<_Ty>())\n\t\t{\n\t\t\tAdd<_Ty>();\n\t\t}\n\n\t\treturn std::static_pointer_cast<_Ty>(Get(typeid(_Ty))).get();\n\t}\n\n\ttemplate <typename _Ty>\n\tRenderGraphBlackboard &Erase()\n\t{\n\t\treturn Erase(typeid(_Ty));\n\t}\n\n  private:\n\tstd::shared_ptr<void> &Add(std::type_index type, std::shared_ptr<void> &&ptr);\n\n\tbool Has(std::type_index type);\n\n\tstd::shared_ptr<void> &Get(std::type_index type);\n\n\tRenderGraphBlackboard &Erase(std::type_index type);\n\n  private:\n\tstd::unordered_map<std::type_index, std::shared_ptr<void>> m_data;\n\n\tstd::mutex m_mutex;\n};\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Public/RenderGraph/RenderGraphBuilder.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include \"RenderGraph.hpp\"\n\nnamespace Ilum\n{\nclass RenderGraph;\nclass Renderer;\n\nclass  RenderGraphBuilder\n{\n  public:\n\tRenderGraphBuilder(RHIContext *rhi_context);\n\n\t~RenderGraphBuilder() = default;\n\n\tRenderGraphBuilder &AddPass(RenderGraph &render_graph, const std::string &name, const std::string &category, BindPoint bind_point, const Variant &config, RenderGraph::RenderTask &&task, RenderGraph::BarrierTask &&barrier);\n\n\tbool Validate(RenderGraphDesc &desc);\n\n\tstd::unique_ptr<RenderGraph> Compile(RenderGraphDesc &desc, Renderer* renderer);\n\n  private:\n\tRHIContext *p_rhi_context = nullptr;\n};\n}        // namespace Ilum\n\n#include \"Impl/RenderGraphBuilder.inl\""
  },
  {
    "path": "Source/Runtime/Render/RenderGraph/Public/RenderGraph/RenderPass.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass Editor;\n\nenum class BindPoint\n{\n\tNone,\n\tRasterization,\n\tCompute,\n\tRayTracing,\n\tCUDA\n};\n\nstruct RenderPassPin\n{\n\tenum class Type\n\t{\n\t\tUnknown,\n\t\tTexture,\n\t\tBuffer\n\t};\n\n\tenum class Attribute\n\t{\n\t\tInput,\n\t\tOutput\n\t};\n\n\t// Common\n\tType      type;\n\tAttribute attribute;\n\n\tstd::string name;\n\tsize_t      handle;\n\n\tTextureDesc texture;\n\tBufferDesc  buffer;\n\n\tRHIResourceState resource_state;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(type, attribute, name, handle, texture, buffer, resource_state);\n\t}\n};\n\nclass RenderPassDesc\n{\n  public:\n\tRenderPassDesc() = default;\n\n\t~RenderPassDesc() = default;\n\n\tRenderPassDesc &SetName(const std::string &name);\n\n\tRenderPassDesc &SetCategory(const std::string &category);\n\n\tRenderPassDesc &SetHandle(size_t handle);\n\n\tRenderPassDesc &WriteTexture2D(size_t handle, const std::string &name, RHIFormat format, RHIResourceState resource_state, uint32_t width = 0, uint32_t height = 0, uint32_t layer = 1, uint32_t mips = 1);\n\n\tRenderPassDesc &ReadTexture2D(size_t handle, const std::string &name, RHIResourceState resource_state);\n\n\tRenderPassDesc &WriteBuffer(size_t handle, const std::string &name, size_t size, RHIResourceState resource_state);\n\n\tRenderPassDesc &ReadBuffer(size_t handle, const std::string &name, RHIResourceState resource_state);\n\n\tconst RenderPassPin &GetPin(size_t handle) const;\n\n\tRenderPassPin &GetPin(size_t handle);\n\n\tRenderPassPin &GetPin(const std::string &name);\n\n\tconst RenderPassPin &GetPin(const std::string &name) const;\n\n\tRenderPassDesc &SetConfig(Variant config);\n\n\tconst Variant &GetConfig() const;\n\n\tconst std::string &GetName() const;\n\n\tconst std::string &GetCategory() const;\n\n\tstd::map<size_t, RenderPassPin> &GetPins();\n\n\tsize_t GetHandle() const;\n\n\tBindPoint GetBindPoint() const;\n\n\tRenderPassDesc &SetBindPoint(BindPoint bind_point);\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(m_name, m_category, m_bind_point, m_handle, m_pins, m_pin_indices, m_config);\n\t}\n\n  private:\n\tstd::string m_name;\n\tstd::string m_category;\n\n\tBindPoint m_bind_point = BindPoint::None;\n\n\tsize_t m_handle = ~0ull;\n\n\tstd::map<size_t, RenderPassPin> m_pins;\n\tstd::map<std::string, size_t>   m_pin_indices;\n\n\tVariant m_config;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Renderer/Private/Renderer.cpp",
    "content": "#include \"Renderer.hpp\"\n#include \"RenderData.hpp\"\n\n#include <Core/Path.hpp>\n#include <Material/MaterialCompiler.hpp>\n#include <Material/MaterialData.hpp>\n#include <RHI/RHIContext.hpp>\n#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBlackboard.hpp>\n#include <Resource/Resource/Animation.hpp>\n#include <Resource/Resource/Material.hpp>\n#include <Resource/Resource/Mesh.hpp>\n#include <Resource/Resource/SkinnedMesh.hpp>\n#include <Resource/Resource/Texture2D.hpp>\n#include <Resource/Resource/TextureCube.hpp>\n#include <Resource/ResourceManager.hpp>\n#include <Scene/Components/AllComponents.hpp>\n#include <Scene/Node.hpp>\n#include <Scene/Scene.hpp>\n#include <ShaderCompiler/ShaderBuilder.hpp>\n#include <ShaderCompiler/ShaderCompiler.hpp>\n\n#include <cereal/types/vector.hpp>\n\nnamespace Ilum\n{\nstruct Renderer::Impl\n{\n\tRHIContext *rhi_context = nullptr;\n\n\tScene *scene = nullptr;\n\n\tResourceManager *resource_manager = nullptr;\n\n\tglm::vec2 viewport = {1.f, 1.f};\n\n\tRHITexture *present_texture = nullptr;\n\n\tstd::unique_ptr<RenderGraph> render_graph     = nullptr;\n\tstd::unique_ptr<RenderGraph> new_render_graph = nullptr;\n\n\tRenderGraphBlackboard black_board;\n\n\tstd::unique_ptr<ShaderBuilder> shader_builder = nullptr;\n\n\tstd::unique_ptr<RHIPipelineState> gpu_skinning_pipeline = nullptr;\n\n\tShaderMeta gpu_skinning_shader_meta;\n\n\tfloat animation_time   = 0.f;\n\tbool  update_animation = false;\n\n\tCmpt::Camera *main_camera = nullptr;\n};\n\nRenderer::Renderer(RHIContext *rhi_context, Scene *scene, ResourceManager *resource_manager)\n{\n\tm_impl                        = new Impl;\n\tm_impl->rhi_context           = rhi_context;\n\tm_impl->scene                 = scene;\n\tm_impl->resource_manager      = resource_manager;\n\tm_impl->shader_builder        = std::make_unique<ShaderBuilder>(rhi_context);\n\tm_impl->gpu_skinning_pipeline = rhi_context->CreatePipelineState();\n\n\t// GPU Skinning Pipeline\n\t{\n\t\tRHIShader *shader = m_impl->shader_builder->RequireShader(\"./Source/Shaders/UpdateBoneMatrics.hlsl\", \"CSmain\", RHIShaderStage::Compute);\n\t\tm_impl->gpu_skinning_pipeline->SetShader(RHIShaderStage::Compute, shader);\n\t\tm_impl->gpu_skinning_shader_meta = m_impl->shader_builder->RequireShaderMeta(shader);\n\t}\n\n\t// View\n\t{\n\t\tauto *view   = m_impl->black_board.Add<View>();\n\t\tview->buffer = m_impl->rhi_context->CreateBuffer<View::Info>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\t}\n\n\t// GPU Scene\n\t{\n\t\tauto *gpu_scene            = m_impl->black_board.Add<GPUScene>();\n\t\tgpu_scene->opaque_tlas     = m_impl->rhi_context->CreateAcccelerationStructure();\n\t\tgpu_scene->non_opaque_tlas = m_impl->rhi_context->CreateAcccelerationStructure();\n\n\t\tgpu_scene->animation.update_info = m_impl->rhi_context->CreateBuffer<GPUScene::AnimationBuffer::UpdateInfo>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\t}\n\n\t// Dummy Textures\n\t{\n\t\tauto *dummy_texture              = m_impl->black_board.Add<DummyTexture>();\n\t\tdummy_texture->white_opaque      = m_impl->rhi_context->CreateTexture2D(1, 1, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::Transfer | RHITextureUsage::ShaderResource, false);\n\t\tdummy_texture->black_opaque      = m_impl->rhi_context->CreateTexture2D(1, 1, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::Transfer | RHITextureUsage::ShaderResource, false);\n\t\tdummy_texture->white_transparent = m_impl->rhi_context->CreateTexture2D(1, 1, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::Transfer | RHITextureUsage::ShaderResource, false);\n\t\tdummy_texture->black_transparent = m_impl->rhi_context->CreateTexture2D(1, 1, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::Transfer | RHITextureUsage::ShaderResource, false);\n\n\t\tauto white_opaque_buffer      = m_impl->rhi_context->CreateBuffer<glm::vec4>(1, RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\t\tauto black_opaque_buffer      = m_impl->rhi_context->CreateBuffer<glm::vec4>(1, RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\t\tauto white_transparent_buffer = m_impl->rhi_context->CreateBuffer<glm::vec4>(1, RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\t\tauto black_transparent_buffer = m_impl->rhi_context->CreateBuffer<glm::vec4>(1, RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\n\t\tglm::vec4 white_opaque      = {1.f, 1.f, 1.f, 1.f};\n\t\tglm::vec4 black_opaque      = {0.f, 0.f, 0.f, 1.f};\n\t\tglm::vec4 white_transparent = {1.f, 1.f, 1.f, 0.f};\n\t\tglm::vec4 black_transparent = {0.f, 0.f, 0.f, 0.f};\n\n\t\twhite_opaque_buffer->CopyToDevice(&white_opaque, sizeof(white_opaque));\n\t\tblack_opaque_buffer->CopyToDevice(&black_opaque, sizeof(white_opaque));\n\t\twhite_transparent_buffer->CopyToDevice(&white_transparent, sizeof(white_opaque));\n\t\tblack_transparent_buffer->CopyToDevice(&black_transparent, sizeof(white_opaque));\n\n\t\tauto *cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\tcmd_buffer->Begin();\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{dummy_texture->white_opaque.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{dummy_texture->black_opaque.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{dummy_texture->white_transparent.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{dummy_texture->black_transparent.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t\t                                    {});\n\t\tcmd_buffer->CopyBufferToTexture(white_opaque_buffer.get(), dummy_texture->white_opaque.get(), 0, 0, 1);\n\t\tcmd_buffer->CopyBufferToTexture(black_opaque_buffer.get(), dummy_texture->black_opaque.get(), 0, 0, 1);\n\t\tcmd_buffer->CopyBufferToTexture(white_transparent_buffer.get(), dummy_texture->white_transparent.get(), 0, 0, 1);\n\t\tcmd_buffer->CopyBufferToTexture(black_transparent_buffer.get(), dummy_texture->black_transparent.get(), 0, 0, 1);\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{dummy_texture->white_opaque.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{dummy_texture->black_opaque.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{dummy_texture->white_transparent.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t\t                                     TextureStateTransition{dummy_texture->black_transparent.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource, TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t\t                                    {});\n\t\tcmd_buffer->End();\n\t\tm_impl->rhi_context->Execute(cmd_buffer);\n\t}\n\n\t// LUT\n\t{\n\t\tauto *lut = m_impl->black_board.Add<LUT>();\n\t\tlut->ggx  = rhi_context->CreateTexture2D(512, 512, RHIFormat::R16G16_FLOAT, RHITextureUsage::ShaderResource | RHITextureUsage::UnorderedAccess, false);\n\n\t\t{\n\t\t\tstd::unique_ptr<RHIPipelineState> ggx_preintegration = rhi_context->CreatePipelineState();\n\n\t\t\tRHIShader *shader = RequireShader(\"Source/Shaders/PreProcess/GGXBRDFLUT.hlsl\", \"CSmain\", RHIShaderStage::Compute);\n\t\t\tggx_preintegration->SetShader(RHIShaderStage::Compute, shader);\n\t\t\tShaderMeta meta = RequireShaderMeta(shader);\n\n\t\t\tauto *descriptor = rhi_context->CreateDescriptor(meta);\n\t\t\tdescriptor->BindTexture(\"Output\", lut->ggx.get(), RHITextureDimension::Texture2D);\n\n\t\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\t\t\tcmd_buffer->Begin();\n\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t                                        TextureStateTransition{lut->ggx.get(), RHIResourceState::Undefined, RHIResourceState::UnorderedAccess},\n\t\t\t                                    },\n\t\t\t                                    {});\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(ggx_preintegration.get());\n\t\t\tcmd_buffer->Dispatch(512, 512, 1, 8, 8, 1);\n\t\t\tcmd_buffer->ResourceStateTransition({\n\t\t\t                                        TextureStateTransition{lut->ggx.get(), RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource},\n\t\t\t                                    },\n\t\t\t                                    {});\n\t\t\tcmd_buffer->End();\n\t\t\tm_impl->rhi_context->Execute(cmd_buffer);\n\t\t}\n\t}\n}\n\nRenderer::~Renderer()\n{\n\tdelete m_impl;\n}\n\nvoid Renderer::Tick()\n{\n\tm_impl->present_texture = nullptr;\n\n\tm_impl->scene->Update();\n\n\tUpdateGPUScene();\n\n\tif (m_impl->new_render_graph)\n\t{\n\t\tm_impl->rhi_context->WaitIdle();\n\t\tm_impl->render_graph = std::move(m_impl->new_render_graph);\n\t\tm_impl->new_render_graph.reset();\n\t}\n\n\tif (m_impl->render_graph)\n\t{\n\t\tm_impl->render_graph->Execute(m_impl->black_board);\n\t}\n\n\tm_impl->scene->Reset();\n}\n\nvoid Renderer::SetRenderGraph(std::unique_ptr<RenderGraph> &&render_graph)\n{\n\tm_impl->new_render_graph = std::move(render_graph);\n}\n\nRenderGraph *Renderer::GetRenderGraph() const\n{\n\treturn m_impl->render_graph.get();\n}\n\nRHIContext *Renderer::GetRHIContext() const\n{\n\treturn m_impl->rhi_context;\n}\n\nResourceManager *Renderer::GetResourceManager() const\n{\n\treturn m_impl->resource_manager;\n}\n\nRenderGraphBlackboard &Renderer::GetRenderGraphBlackboard()\n{\n\treturn m_impl->black_board;\n}\n\nvoid Renderer::SetViewport(float width, float height)\n{\n\tm_impl->viewport = glm::vec2{width, height};\n}\n\nglm::vec2 Renderer::GetViewport() const\n{\n\treturn m_impl->viewport;\n}\n\nvoid Renderer::SetAnimationTime(float time)\n{\n\tm_impl->animation_time   = time;\n\tm_impl->update_animation = true;\n}\n\nvoid Renderer::SetPresentTexture(RHITexture *present_texture)\n{\n\tm_impl->present_texture = present_texture;\n}\n\nRHITexture *Renderer::GetPresentTexture() const\n{\n\treturn m_impl->present_texture ? m_impl->present_texture : m_impl->black_board.Get<DummyTexture>()->black_opaque.get();\n}\n\nfloat Renderer::GetMaxAnimationTime() const\n{\n\treturn static_cast<float>(m_impl->black_board.Get<GPUScene>()->animation.max_frame_count) / 30.f;\n}\n\nvoid Renderer::UpdateView(Cmpt::Camera *camera)\n{\n\tm_impl->main_camera = camera;\n\n\tif (camera)\n\t{\n\t\tauto *view = m_impl->black_board.Get<View>();\n\n\t\tView::Info view_info = {};\n\n\t\tstd::memcpy(view_info.frustum, camera->GetFrustumPlanes().data(), sizeof(glm::vec4) * 6);\n\t\tview_info.position                   = camera->GetNode()->GetComponent<Cmpt::Transform>()->GetWorldTransform()[3];\n\t\tview_info.projection_matrix          = camera->GetProjectionMatrix();\n\t\tview_info.view_matrix                = camera->GetViewMatrix();\n\t\tview_info.inv_projection_matrix      = camera->GetInvProjectionMatrix();\n\t\tview_info.inv_view_matrix            = camera->GetInvViewMatrix();\n\t\tview_info.view_projection_matrix     = camera->GetViewProjectionMatrix();\n\t\tview_info.inv_view_projection_matrix = camera->GetInvViewProjectionMatrix();\n\t\tview_info.viewport                   = m_impl->viewport;\n\n\t\tview->buffer->CopyToDevice(&view_info, sizeof(View::Info));\n\t}\n}\n\nScene *Renderer::GetScene() const\n{\n\treturn m_impl->scene;\n}\n\nvoid Renderer::Reset()\n{\n\tm_impl->rhi_context->WaitIdle();\n}\n\nRHIShader *Renderer::RequireShader(const std::string &filename, const std::string &entry_point, RHIShaderStage stage, std::vector<std::string> &&macros, std::vector<std::string> &&includes, bool cuda, bool force_recompile)\n{\n\treturn m_impl->shader_builder->RequireShader(filename, entry_point, stage, std::move(macros), std::move(includes), cuda, force_recompile);\n}\n\nShaderMeta Renderer::RequireShaderMeta(RHIShader *shader) const\n{\n\treturn m_impl->shader_builder->RequireShaderMeta(shader);\n}\n\nvoid Renderer::UpdateLight()\n{\n\tauto *gpu_scene = m_impl->black_board.Get<GPUScene>();\n\n\tauto point_lights       = m_impl->scene->GetComponents<Cmpt::PointLight>();\n\tauto spot_lights        = m_impl->scene->GetComponents<Cmpt::SpotLight>();\n\tauto directional_lights = m_impl->scene->GetComponents<Cmpt::DirectionalLight>();\n\tauto rectangle_lights   = m_impl->scene->GetComponents<Cmpt::RectLight>();\n\tauto environment_lights = m_impl->scene->GetComponents<Cmpt::EnvironmentLight>();\n\n\tif (!gpu_scene->light.light_info_buffer)\n\t{\n\t\tgpu_scene->light.light_info_buffer = m_impl->rhi_context->CreateBuffer<GPUScene::LightBuffer::Info>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\t}\n\n#define COPY_LIGHT_DATA(DATA, BUFFER)                                                                                                             \\\n\tif (!DATA.empty())                                                                                                                            \\\n\t{                                                                                                                                             \\\n\t\tsize_t light_size = DATA.empty() ? 0 : DATA.size() * DATA[0]->GetDataSize();                                                              \\\n\t\tif (!gpu_scene->light.BUFFER || gpu_scene->light.BUFFER->GetDesc().size != light_size)                                                    \\\n\t\t{                                                                                                                                         \\\n\t\t\tgpu_scene->light.BUFFER = m_impl->rhi_context->CreateBuffer(light_size, RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU); \\\n\t\t}                                                                                                                                         \\\n\t\tauto    *light_buffer = gpu_scene->light.BUFFER->Map();                                                                                   \\\n\t\tsize_t   offset       = 0;                                                                                                                \\\n\t\tuint32_t shadow_id    = 0;                                                                                                                \\\n\t\tfor (auto &light : DATA)                                                                                                                  \\\n\t\t{                                                                                                                                         \\\n\t\t\tlight->SetShadowID(shadow_id);                                                                                                        \\\n\t\t\tstd::memcpy((uint8_t *) light_buffer + offset, light->GetData(m_impl->main_camera), light->GetDataSize());                            \\\n\t\t\toffset += light->GetDataSize();                                                                                                       \\\n\t\t}                                                                                                                                         \\\n\t\tgpu_scene->light.BUFFER->Unmap();                                                                                                         \\\n\t}                                                                                                                                             \\\n\telse                                                                                                                                          \\\n\t{                                                                                                                                             \\\n\t\tif (!gpu_scene->light.BUFFER)                                                                                                             \\\n\t\t{                                                                                                                                         \\\n\t\t\tgpu_scene->light.BUFFER = m_impl->rhi_context->CreateBuffer(1, RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);          \\\n\t\t}                                                                                                                                         \\\n\t}\n\n\tCOPY_LIGHT_DATA(point_lights, point_light_buffer);\n\tCOPY_LIGHT_DATA(spot_lights, spot_light_buffer);\n\tCOPY_LIGHT_DATA(directional_lights, directional_light_buffer);\n\tCOPY_LIGHT_DATA(rectangle_lights, rect_light_buffer);\n\n\tgpu_scene->light.info.point_light_count       = static_cast<uint32_t>(point_lights.size());\n\tgpu_scene->light.info.spot_light_count        = static_cast<uint32_t>(spot_lights.size());\n\tgpu_scene->light.info.directional_light_count = static_cast<uint32_t>(directional_lights.size());\n\tgpu_scene->light.info.rect_light_count        = static_cast<uint32_t>(rectangle_lights.size());\n\tgpu_scene->light.light_info_buffer->CopyToDevice(&gpu_scene->light.info, sizeof(gpu_scene->light.info));\n\n\t// Copy environment light data\n\tif (environment_lights.empty())\n\t{\n\t\tgpu_scene->texture.texture_cube = nullptr;\n\t}\n\telse\n\t{\n\t\tauto resource = m_impl->resource_manager->Get<ResourceType::TextureCube>(static_cast<const char *>(environment_lights.back()->GetData()));\n\t\tif (resource)\n\t\t{\n\t\t\tgpu_scene->texture.texture_cube = resource->GetTexture();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgpu_scene->texture.texture_cube = nullptr;\n\t\t}\n\t}\n}\n\nvoid Renderer::UpdateAnimation()\n{\n\tauto *gpu_scene = m_impl->black_board.Get<GPUScene>();\n\n\t// Update animation\n\tif (gpu_scene->animation.max_bone_count > 0 && m_impl->update_animation)\n\t{\n\t\t{\n\t\t\tGPUScene::AnimationBuffer::UpdateInfo update_info = {};\n\n\t\t\tupdate_info.count = static_cast<uint32_t>(gpu_scene->animation.bone_matrics.size());\n\t\t\tupdate_info.time  = m_impl->animation_time;\n\t\t\tgpu_scene->animation.update_info->CopyToDevice(&update_info, sizeof(update_info));\n\t\t}\n\n\t\tstd::vector<BufferStateTransition> begin_transitions(gpu_scene->animation.bone_matrics.size());\n\t\tstd::vector<BufferStateTransition> end_transitions(gpu_scene->animation.bone_matrics.size());\n\n\t\tfor (size_t i = 0; i < gpu_scene->animation.bone_matrics.size(); i++)\n\t\t{\n\t\t\tbegin_transitions[i] = BufferStateTransition{gpu_scene->animation.bone_matrics[i], RHIResourceState::ShaderResource, RHIResourceState::UnorderedAccess};\n\t\t\tend_transitions[i]   = BufferStateTransition{gpu_scene->animation.bone_matrics[i], RHIResourceState::UnorderedAccess, RHIResourceState::ShaderResource};\n\t\t}\n\n\t\tauto *descriptor = m_impl->rhi_context->CreateDescriptor(m_impl->gpu_skinning_shader_meta);\n\t\tdescriptor->BindBuffer(\"UpdateInfo\", gpu_scene->animation.update_info.get());\n\t\tauto *cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\t\tcmd_buffer->Begin();\n\t\tcmd_buffer->ResourceStateTransition({}, begin_transitions);\n\t\tfor (size_t i = 0; i < gpu_scene->animation.bone_matrics.size(); i++)\n\t\t{\n\t\t\tdescriptor->BindBuffer(\"BoneMatrics\", gpu_scene->animation.bone_matrics[i])\n\t\t\t    .BindTexture(\"SkinnedMatrics\", gpu_scene->animation.skinned_matrics[i], RHITextureDimension::Texture2D);\n\t\t\tcmd_buffer->BindDescriptor(descriptor);\n\t\t\tcmd_buffer->BindPipelineState(m_impl->gpu_skinning_pipeline.get());\n\t\t\tcmd_buffer->Dispatch(gpu_scene->animation.max_bone_count, 1, 1, 8, 1, 1);\n\t\t}\n\t\tcmd_buffer->ResourceStateTransition({}, end_transitions);\n\t\tcmd_buffer->End();\n\t\tm_impl->rhi_context->Submit({cmd_buffer});\n\t\tm_impl->update_animation = false;\n\t}\n\n\t// Update resource\n\tif (m_impl->resource_manager->Update<ResourceType::Animation>())\n\t{\n\t\tm_impl->scene->Update(true);\n\n\t\tgpu_scene->animation.bone_matrics.clear();\n\t\tgpu_scene->animation.skinned_matrics.clear();\n\n\t\tauto resources = m_impl->resource_manager->GetResources<ResourceType::Animation>();\n\n\t\tgpu_scene->animation.max_bone_count  = 0;\n\t\tgpu_scene->animation.max_frame_count = 0;\n\t\tfor (auto &resource : resources)\n\t\t{\n\t\t\tauto *animation = m_impl->resource_manager->Get<ResourceType::Animation>(resource);\n\t\t\tgpu_scene->animation.skinned_matrics.push_back(animation->GetSkinnedMatrics());\n\t\t\tgpu_scene->animation.bone_matrics.push_back(animation->GetBoneMatrics());\n\t\t\tgpu_scene->animation.max_bone_count  = glm::max(gpu_scene->animation.max_bone_count, animation->GetBoneCount());\n\t\t\tgpu_scene->animation.max_frame_count = glm::max(gpu_scene->animation.max_frame_count, animation->GetFrameCount());\n\t\t}\n\t}\n}\n\nvoid Renderer::UpdateMesh()\n{\n\tauto *gpu_scene = m_impl->black_board.Get<GPUScene>();\n\n\tauto meshes = m_impl->scene->GetComponents<Cmpt::MeshRenderer>();\n\n\tTLASDesc opaque_tlas_desc     = {fmt::format(\"{} - Opaque\", m_impl->scene->GetName())};\n\tTLASDesc non_opaque_tlas_desc = {fmt::format(\"{} - Non Opaque\", m_impl->scene->GetName())};\n\n\tstd::vector<GPUScene::Instance> opaque_instances;\n\tstd::vector<GPUScene::Instance> non_opaque_instances;\n\n\tgpu_scene->opaque_mesh.max_meshlet_count     = 0;\n\tgpu_scene->non_opaque_mesh.max_meshlet_count = 0;\n\n\t// Update mesh instances\n\t{\n\t\tfor (auto &mesh : meshes)\n\t\t{\n\t\t\tauto &submeshes = mesh->GetSubmeshes();\n\t\t\tauto &materials = mesh->GetMaterials();\n\t\t\tfor (uint32_t i = 0; i < submeshes.size(); i++)\n\t\t\t{\n\t\t\t\tauto &submesh = submeshes[i];\n\n\t\t\t\tauto *resource = m_impl->resource_manager->Get<ResourceType::Mesh>(submesh);\n\n\t\t\t\tif (resource)\n\t\t\t\t{\n\t\t\t\t\tGPUScene::Instance instance = {};\n\t\t\t\t\tinstance.transform          = mesh->GetNode()->GetComponent<Cmpt::Transform>()->GetWorldTransform();\n\t\t\t\t\tinstance.mesh_id            = static_cast<uint32_t>(m_impl->resource_manager->Index<ResourceType::Mesh>(submesh));\n\t\t\t\t\tinstance.material_id        = 0;\n\n\t\t\t\t\tif (i < materials.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tinstance.material_id = static_cast<uint32_t>(m_impl->resource_manager->Index<ResourceType::Material>(materials[i])) + 1;\n\t\t\t\t\t\tauto *material       = m_impl->resource_manager->Get<ResourceType::Material>(materials[i]);\n\t\t\t\t\t\tif (material->GetMaterialData().blend_mode == BlendMode::Opaque)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\topaque_instances.push_back(instance);\n\t\t\t\t\t\t\topaque_tlas_desc.instances.push_back(TLASDesc::InstanceInfo{instance.transform, instance.material_id, resource->GetBLAS()});\n\t\t\t\t\t\t\tgpu_scene->opaque_mesh.max_meshlet_count = glm::max(gpu_scene->opaque_mesh.max_meshlet_count, static_cast<uint32_t>(resource->GetMeshletCount()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnon_opaque_instances.push_back(instance);\n\t\t\t\t\t\t\tnon_opaque_tlas_desc.instances.push_back(TLASDesc::InstanceInfo{instance.transform, instance.material_id, resource->GetBLAS()});\n\t\t\t\t\t\t\tgpu_scene->non_opaque_mesh.max_meshlet_count = glm::max(gpu_scene->non_opaque_mesh.max_meshlet_count, static_cast<uint32_t>(resource->GetMeshletCount()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\topaque_instances.push_back(instance);\n\t\t\t\t\t\topaque_tlas_desc.instances.push_back(TLASDesc::InstanceInfo{instance.transform, instance.material_id, resource->GetBLAS()});\n\t\t\t\t\t\tgpu_scene->opaque_mesh.max_meshlet_count = glm::max(gpu_scene->opaque_mesh.max_meshlet_count, static_cast<uint32_t>(resource->GetMeshletCount()));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tgpu_scene->opaque_mesh.instance_count     = static_cast<uint32_t>(opaque_instances.size());\n\t\tgpu_scene->non_opaque_mesh.instance_count = static_cast<uint32_t>(non_opaque_instances.size());\n\t}\n\n\t// Copy to device\n\t{\n\t\tif (!opaque_instances.empty())\n\t\t{\n\t\t\tif (!gpu_scene->opaque_mesh.instances ||\n\t\t\t    gpu_scene->opaque_mesh.instances->GetDesc().size < opaque_instances.size() * sizeof(GPUScene::Instance))\n\t\t\t{\n\t\t\t\tgpu_scene->opaque_mesh.instances = m_impl->rhi_context->CreateBuffer<GPUScene::Instance>(opaque_instances.size(), RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\t\t\tgpu_scene->opaque_mesh.instances->CopyToDevice(opaque_instances.data(), opaque_instances.size() * sizeof(GPUScene::Instance));\n\t\t}\n\n\t\tif (!non_opaque_instances.empty())\n\t\t{\n\t\t\tif (!gpu_scene->non_opaque_mesh.instances ||\n\t\t\t    gpu_scene->non_opaque_mesh.instances->GetDesc().size < non_opaque_instances.size() * sizeof(GPUScene::Instance))\n\t\t\t{\n\t\t\t\tgpu_scene->non_opaque_mesh.instances = m_impl->rhi_context->CreateBuffer<GPUScene::Instance>(non_opaque_instances.size(), RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\t\t\tgpu_scene->non_opaque_mesh.instances->CopyToDevice(non_opaque_instances.data(), non_opaque_instances.size() * sizeof(GPUScene::Instance));\n\t\t}\n\t}\n\n\t// Update TLAS\n\t{\n\t\tif (!opaque_tlas_desc.instances.empty())\n\t\t{\n\t\t\tauto *cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\t\t\tcmd_buffer->Begin();\n\t\t\tgpu_scene->opaque_tlas->Update(cmd_buffer, opaque_tlas_desc);\n\t\t\tcmd_buffer->End();\n\t\t\tm_impl->rhi_context->Submit({cmd_buffer});\n\t\t}\n\n\t\tif (!non_opaque_tlas_desc.instances.empty())\n\t\t{\n\t\t\tauto *cmd_buffer = m_impl->rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\t\t\tcmd_buffer->Begin();\n\t\t\tgpu_scene->non_opaque_tlas->Update(cmd_buffer, non_opaque_tlas_desc);\n\t\t\tcmd_buffer->End();\n\t\t\tm_impl->rhi_context->Submit({cmd_buffer});\n\t\t}\n\t}\n\n\t// Update resource\n\tif (m_impl->resource_manager->Update<ResourceType::Mesh>())\n\t{\n\t\tm_impl->scene->Update(true);\n\n\t\tgpu_scene->mesh_buffer.vertex_buffers.clear();\n\t\tgpu_scene->mesh_buffer.index_buffers.clear();\n\t\tgpu_scene->mesh_buffer.meshlet_buffers.clear();\n\t\tgpu_scene->mesh_buffer.meshlet_data_buffers.clear();\n\t\tauto resources = m_impl->resource_manager->GetResources<ResourceType::Mesh>();\n\t\tfor (auto &resource : resources)\n\t\t{\n\t\t\tauto *mesh = m_impl->resource_manager->Get<ResourceType::Mesh>(resource);\n\t\t\tgpu_scene->mesh_buffer.vertex_buffers.push_back(mesh->GetVertexBuffer());\n\t\t\tgpu_scene->mesh_buffer.index_buffers.push_back(mesh->GetIndexBuffer());\n\t\t\tgpu_scene->mesh_buffer.meshlet_buffers.push_back(mesh->GetMeshletBuffer());\n\t\t\tgpu_scene->mesh_buffer.meshlet_data_buffers.push_back(mesh->GetMeshletDataBuffer());\n\t\t}\n\t}\n}\n\nvoid Renderer::UpdateSkinnedMesh()\n{\n\tauto *gpu_scene      = m_impl->black_board.Get<GPUScene>();\n\tauto  skinned_meshes = m_impl->scene->GetComponents<Cmpt::SkinnedMeshRenderer>();\n\n\tstd::vector<GPUScene::Instance> opaque_instances;\n\tstd::vector<GPUScene::Instance> non_opaque_instances;\n\n\tgpu_scene->opaque_skinned_mesh.max_meshlet_count     = 0;\n\tgpu_scene->non_opaque_skinned_mesh.max_meshlet_count = 0;\n\n\t// Update skinned mesh instances\n\t{\n\t\tfor (auto &skinned_mesh : skinned_meshes)\n\t\t{\n\t\t\tauto &submeshes  = skinned_mesh->GetSubmeshes();\n\t\t\tauto &animations = skinned_mesh->GetAnimations();\n\t\t\tauto &materials  = skinned_mesh->GetMaterials();\n\t\t\tfor (uint32_t i = 0; i < submeshes.size(); i++)\n\t\t\t{\n\t\t\t\tauto *resource = m_impl->resource_manager->Get<ResourceType::SkinnedMesh>(submeshes[i]);\n\n\t\t\t\tif (resource)\n\t\t\t\t{\n\t\t\t\t\tGPUScene::Instance instance = {};\n\t\t\t\t\tinstance.transform          = skinned_mesh->GetNode()->GetComponent<Cmpt::Transform>()->GetWorldTransform();\n\t\t\t\t\tinstance.mesh_id            = static_cast<uint32_t>(m_impl->resource_manager->Index<ResourceType::SkinnedMesh>(submeshes[i]));\n\t\t\t\t\tinstance.material_id        = 0;\n\n\t\t\t\t\tif (i < animations.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tinstance.animation_id = static_cast<uint32_t>(m_impl->resource_manager->Index<ResourceType::Animation>(animations[i]));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (i < materials.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tinstance.material_id = static_cast<uint32_t>(m_impl->resource_manager->Index<ResourceType::Material>(materials[i])) + 1;\n\t\t\t\t\t\tauto *material       = m_impl->resource_manager->Get<ResourceType::Material>(materials[i]);\n\t\t\t\t\t\tif (material->GetMaterialData().blend_mode == BlendMode::Opaque)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\topaque_instances.push_back(instance);\n\t\t\t\t\t\t\tgpu_scene->opaque_skinned_mesh.max_meshlet_count = glm::max(gpu_scene->opaque_skinned_mesh.max_meshlet_count, static_cast<uint32_t>(resource->GetMeshletCount()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnon_opaque_instances.push_back(instance);\n\t\t\t\t\t\t\tgpu_scene->non_opaque_skinned_mesh.max_meshlet_count = glm::max(gpu_scene->non_opaque_skinned_mesh.max_meshlet_count, static_cast<uint32_t>(resource->GetMeshletCount()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\topaque_instances.push_back(instance);\n\t\t\t\t\t\tgpu_scene->opaque_skinned_mesh.max_meshlet_count = glm::max(gpu_scene->opaque_skinned_mesh.max_meshlet_count, static_cast<uint32_t>(resource->GetMeshletCount()));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tgpu_scene->opaque_skinned_mesh.instance_count     = static_cast<uint32_t>(opaque_instances.size());\n\t\tgpu_scene->non_opaque_skinned_mesh.instance_count = static_cast<uint32_t>(non_opaque_instances.size());\n\t}\n\n\t// Copy to device\n\t{\n\t\tif (!opaque_instances.empty())\n\t\t{\n\t\t\tif (!gpu_scene->opaque_skinned_mesh.instances ||\n\t\t\t    gpu_scene->opaque_skinned_mesh.instances->GetDesc().size < opaque_instances.size() * sizeof(GPUScene::Instance))\n\t\t\t{\n\t\t\t\tgpu_scene->opaque_skinned_mesh.instances = m_impl->rhi_context->CreateBuffer<GPUScene::Instance>(opaque_instances.size(), RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\t\t\tgpu_scene->opaque_skinned_mesh.instances->CopyToDevice(opaque_instances.data(), opaque_instances.size() * sizeof(GPUScene::Instance));\n\t\t}\n\n\t\tif (!non_opaque_instances.empty())\n\t\t{\n\t\t\tif (!gpu_scene->non_opaque_skinned_mesh.instances ||\n\t\t\t    gpu_scene->non_opaque_skinned_mesh.instances->GetDesc().size < non_opaque_instances.size() * sizeof(GPUScene::Instance))\n\t\t\t{\n\t\t\t\tgpu_scene->non_opaque_skinned_mesh.instances = m_impl->rhi_context->CreateBuffer<GPUScene::Instance>(non_opaque_instances.size(), RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\t\t\tgpu_scene->non_opaque_skinned_mesh.instances->CopyToDevice(non_opaque_instances.data(), non_opaque_instances.size() * sizeof(GPUScene::Instance));\n\t\t}\n\t}\n\n\t// Update resource\n\tif (m_impl->resource_manager->Update<ResourceType::SkinnedMesh>())\n\t{\n\t\tm_impl->scene->Update(true);\n\n\t\tgpu_scene->skinned_mesh_buffer.vertex_buffers.clear();\n\t\tgpu_scene->skinned_mesh_buffer.index_buffers.clear();\n\t\tgpu_scene->skinned_mesh_buffer.meshlet_buffers.clear();\n\t\tgpu_scene->skinned_mesh_buffer.meshlet_data_buffers.clear();\n\t\tauto resources = m_impl->resource_manager->GetResources<ResourceType::SkinnedMesh>();\n\t\tfor (auto &resource : resources)\n\t\t{\n\t\t\tauto *skinned_mesh = m_impl->resource_manager->Get<ResourceType::SkinnedMesh>(resource);\n\t\t\tgpu_scene->skinned_mesh_buffer.vertex_buffers.push_back(skinned_mesh->GetVertexBuffer());\n\t\t\tgpu_scene->skinned_mesh_buffer.index_buffers.push_back(skinned_mesh->GetIndexBuffer());\n\t\t\tgpu_scene->skinned_mesh_buffer.meshlet_buffers.push_back(skinned_mesh->GetMeshletBuffer());\n\t\t\tgpu_scene->skinned_mesh_buffer.meshlet_data_buffers.push_back(skinned_mesh->GetMeshletDataBuffer());\n\t\t}\n\t}\n}\n\nvoid Renderer::UpdateMaterial()\n{\n\tauto *gpu_scene = m_impl->black_board.Get<GPUScene>();\n\n\t// Update Sampler\n\tif (m_impl->rhi_context->GetSamplerCount() != gpu_scene->samplers.size())\n\t{\n\t\tm_impl->scene->Update(true);\n\n\t\tgpu_scene->samplers = m_impl->rhi_context->GetSamplers();\n\t}\n\n\t// Update 2D Textures\n\tif (m_impl->resource_manager->Update<ResourceType::Texture2D>())\n\t{\n\t\tm_impl->scene->Update(true);\n\t}\n\n\t// Update Material & Texture\n\tif (m_impl->resource_manager->Update<ResourceType::Material>() ||\n\t    m_impl->resource_manager->Update<ResourceType::Texture2D>())\n\t{\n\t\tm_impl->scene->Update(true);\n\n\t\t// Flush Texture\n\t\tif (m_impl->resource_manager->Update<ResourceType::Material>())\n\t\t{\n\t\t\tauto resources = m_impl->resource_manager->GetResources<ResourceType::Material>();\n\t\t\tfor (auto &resource : resources)\n\t\t\t{\n\t\t\t\tauto *material = m_impl->resource_manager->Get<ResourceType::Material>(resource);\n\t\t\t\tif (!material->IsValid())\n\t\t\t\t{\n\t\t\t\t\tmaterial->Compile(\n\t\t\t\t\t    m_impl->rhi_context,\n\t\t\t\t\t    m_impl->resource_manager,\n\t\t\t\t\t    m_impl->black_board.Get<DummyTexture>()->black_opaque.get());\n\t\t\t\t}\n\t\t\t\tfor (auto &[texture, texture_name] : material->GetCompilationContext().textures)\n\t\t\t\t{\n\t\t\t\t\tm_impl->resource_manager->Index<ResourceType::Texture2D>(texture_name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Update Texture\n\t\tif (m_impl->resource_manager->Update<ResourceType::Texture2D>())\n\t\t{\n\t\t\tgpu_scene->texture.texture_2d.clear();\n\t\t\tauto resources = m_impl->resource_manager->GetResources<ResourceType::Texture2D>();\n\t\t\tfor (auto &resource : resources)\n\t\t\t{\n\t\t\t\tauto *texture2d = m_impl->resource_manager->Get<ResourceType::Texture2D>(resource);\n\t\t\t\tgpu_scene->texture.texture_2d.push_back(texture2d->GetTexture());\n\t\t\t}\n\t\t}\n\n\t\t// Update Material\n\t\tif (m_impl->resource_manager->Update<ResourceType::Material>())\n\t\t{\n\t\t\tgpu_scene->material.data.clear();\n\t\t\tauto resources = m_impl->resource_manager->GetResources<ResourceType::Material>();\n\n\t\t\tstd::vector<uint32_t> material_data;\n\t\t\tstd::vector<uint32_t> material_offset = {0};\n\n\t\t\tfor (auto &resource : resources)\n\t\t\t{\n\t\t\t\tauto *material = m_impl->resource_manager->Get<ResourceType::Material>(resource);\n\n\t\t\t\tmaterial->Update(\n\t\t\t\t    m_impl->rhi_context,\n\t\t\t\t    m_impl->resource_manager,\n\t\t\t\t    m_impl->black_board.Get<DummyTexture>()->black_opaque.get());\n\n\t\t\t\tconst auto &data = material->GetMaterialData();\n\n\t\t\t\tmaterial_offset.push_back(static_cast<uint32_t>(material_data.size() * sizeof(uint32_t)));\n\t\t\t\tmaterial_data.insert(material_data.end(), data.textures.begin(), data.textures.end());\n\t\t\t\tmaterial_data.insert(material_data.end(), data.samplers.begin(), data.samplers.end());\n\n\t\t\t\tgpu_scene->material.data.push_back(&data);\n\t\t\t}\n\n\t\t\tif (!material_data.empty())\n\t\t\t{\n\t\t\t\tif (!gpu_scene->material.material_buffer ||\n\t\t\t\t    material_data.size() * sizeof(uint32_t) != gpu_scene->material.material_buffer->GetDesc().size)\n\t\t\t\t{\n\t\t\t\t\tgpu_scene->material.material_buffer = m_impl->rhi_context->CreateBuffer<uint32_t>(material_data.size(), RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t\t}\n\t\t\t\tgpu_scene->material.material_buffer->CopyToDevice(material_data.data(), material_data.size() * sizeof(uint32_t));\n\t\t\t}\n\t\t\telse if (!gpu_scene->material.material_buffer)\n\t\t\t{\n\t\t\t\tgpu_scene->material.material_buffer = m_impl->rhi_context->CreateBuffer<uint32_t>(1, RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\n\t\t\tif (!material_offset.empty())\n\t\t\t{\n\t\t\t\tif (!gpu_scene->material.material_offset ||\n\t\t\t\t    material_offset.size() * sizeof(uint32_t) != gpu_scene->material.material_offset->GetDesc().size)\n\t\t\t\t{\n\t\t\t\t\tgpu_scene->material.material_offset = m_impl->rhi_context->CreateBuffer<uint32_t>(material_offset.size(), RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t\t}\n\t\t\t\tgpu_scene->material.material_offset->CopyToDevice(material_offset.data(), material_offset.size() * sizeof(uint32_t));\n\t\t\t}\n\t\t\telse if (!gpu_scene->material.material_offset)\n\t\t\t{\n\t\t\t\tgpu_scene->material.material_offset = m_impl->rhi_context->CreateBuffer<uint32_t>(1, RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\t\t\t}\n\n\t\t\tfor (auto &resource : resources)\n\t\t\t{\n\t\t\t\tauto *material = m_impl->resource_manager->Get<ResourceType::Material>(resource);\n\n\t\t\t\tGPUScene *gpu_scene = m_impl->black_board.Get<GPUScene>();\n\n\t\t\t\tmaterial->PostUpdate(\n\t\t\t\t    m_impl->rhi_context,\n\t\t\t\t    static_cast<uint32_t>(m_impl->resource_manager->Index<ResourceType::Material>(resource)),\n\t\t\t\t    gpu_scene->texture.texture_2d,\n\t\t\t\t    gpu_scene->samplers,\n\t\t\t\t    gpu_scene->material.material_buffer.get(),\n\t\t\t\t    gpu_scene->material.material_offset.get());\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Renderer::UpdateGPUScene()\n{\n\tauto *gpu_scene = m_impl->black_board.Get<GPUScene>();\n\n\tTLASDesc tlas_desc = {};\n\ttlas_desc.name     = m_impl->scene->GetName();\n\n\tauto meshes         = m_impl->scene->GetComponents<Cmpt::MeshRenderer>();\n\tauto skinned_meshes = m_impl->scene->GetComponents<Cmpt::SkinnedMeshRenderer>();\n\n\tUpdateLight();\n\tUpdateMesh();\n\tUpdateSkinnedMesh();\n\tUpdateAnimation();\n\tUpdateMaterial();\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Renderer/Public/Renderer/RenderData.hpp",
    "content": "#pragma once\n\n#include <RHI/RHIContext.hpp>\n#include <Resource/Resource/Material.hpp>\n\nnamespace Ilum\n{\nstruct DummyTexture\n{\n\tstd::unique_ptr<RHITexture> white_opaque      = nullptr;\n\tstd::unique_ptr<RHITexture> black_opaque      = nullptr;\n\tstd::unique_ptr<RHITexture> white_transparent = nullptr;\n\tstd::unique_ptr<RHITexture> black_transparent = nullptr;\n};\n\nstruct LUT\n{\n\tstd::unique_ptr<RHITexture> ggx = nullptr;\n};\n\nstruct View\n{\n\tstruct Info\n\t{\n\t\tglm::vec4 frustum[6];\n\t\tglm::mat4 view_matrix;\n\t\tglm::mat4 inv_view_matrix;\n\t\tglm::mat4 projection_matrix;\n\t\tglm::mat4 inv_projection_matrix;\n\t\tglm::mat4 view_projection_matrix;\n\t\tglm::mat4 inv_view_projection_matrix;\n\t\tglm::vec3 position;\n\t\tuint32_t  frame_count;\n\t\tglm::vec2 viewport;\n\t};\n\n\tstd::unique_ptr<RHIBuffer> buffer = nullptr;\n};\n\nstruct GPUScene\n{\n\tstruct Instance\n\t{\n\t\tglm::mat4 transform;\n\t\tuint32_t  mesh_id      = ~0U;\n\t\tuint32_t  material_id  = ~0U;\n\t\tuint32_t  animation_id = ~0U;\n\t\tuint32_t  visible      = 0U;\n\t};\n\n\tstruct MeshInstance\n\t{\n\t\tstd::unique_ptr<RHIBuffer> instances = nullptr;\n\n\t\tuint32_t max_meshlet_count = 0;\n\t\tuint32_t instance_count    = 0;\n\t};\n\n\tstruct MeshBuffer\n\t{\n\t\tstd::vector<RHIBuffer *> vertex_buffers;\n\t\tstd::vector<RHIBuffer *> index_buffers;\n\t\tstd::vector<RHIBuffer *> meshlet_data_buffers;\n\t\tstd::vector<RHIBuffer *> meshlet_buffers;\n\t};\n\n\tstruct SkinnedMeshInstance\n\t{\n\t\tstd::unique_ptr<RHIBuffer> instances = nullptr;\n\n\t\tuint32_t max_meshlet_count = 0;\n\t\tuint32_t instance_count    = 0;\n\t};\n\n\tstruct SkinnedMeshBuffer\n\t{\n\t\tstd::vector<RHIBuffer *> vertex_buffers;\n\t\tstd::vector<RHIBuffer *> index_buffers;\n\t\tstd::vector<RHIBuffer *> meshlet_data_buffers;\n\t\tstd::vector<RHIBuffer *> meshlet_buffers;\n\t};\n\n\tstruct AnimationBuffer\n\t{\n\t\tstruct UpdateInfo\n\t\t{\n\t\t\tuint32_t count;\n\t\t\tfloat    time;\n\t\t};\n\n\t\tstd::vector<RHITexture *> skinned_matrics;\n\t\tstd::vector<RHIBuffer *>  bone_matrics;\n\n\t\tstd::unique_ptr<RHIBuffer> update_info = nullptr;\n\n\t\tuint32_t max_frame_count = 0;\n\t\tuint32_t max_bone_count  = 0;\n\t};\n\n\tstruct LightBuffer\n\t{\n\t\tstruct Info\n\t\t{\n\t\t\tuint32_t point_light_count       = 0;\n\t\t\tuint32_t spot_light_count        = 0;\n\t\t\tuint32_t directional_light_count = 0;\n\t\t\tuint32_t rect_light_count        = 0;\n\t\t} info;\n\n\t\tstd::unique_ptr<RHIBuffer> point_light_buffer       = nullptr;\n\t\tstd::unique_ptr<RHIBuffer> spot_light_buffer        = nullptr;\n\t\tstd::unique_ptr<RHIBuffer> directional_light_buffer = nullptr;\n\t\tstd::unique_ptr<RHIBuffer> rect_light_buffer        = nullptr;\n\t\tstd::unique_ptr<RHIBuffer> light_info_buffer        = nullptr;\n\t};\n\n\tstruct TextureBuffer\n\t{\n\t\tstd::vector<RHITexture *> texture_2d;\n\n\t\tRHITexture *texture_cube = nullptr;\n\t};\n\n\tstruct MaterialBuffer\n\t{\n\t\tstd::vector<const MaterialData *> data;\n\n\t\tstd::unique_ptr<RHIBuffer> material_buffer = nullptr;\n\t\tstd::unique_ptr<RHIBuffer> material_offset = nullptr;\n\t};\n\n\tstd::vector<RHISampler *> samplers;\n\n\tMeshInstance      opaque_mesh;\n\tMeshInstance      non_opaque_mesh;\n\tMeshBuffer        mesh_buffer;\n\tSkinnedMeshInstance opaque_skinned_mesh;\n\tSkinnedMeshInstance non_opaque_skinned_mesh;\n\tSkinnedMeshBuffer   skinned_mesh_buffer;\n\tAnimationBuffer   animation;\n\tMaterialBuffer    material;\n\tLightBuffer       light;\n\tTextureBuffer     texture;\n\n\tstd::unique_ptr<RHIAccelerationStructure> opaque_tlas     = nullptr;\n\tstd::unique_ptr<RHIAccelerationStructure> non_opaque_tlas = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/Renderer/Public/Renderer/Renderer.hpp",
    "content": "#pragma once\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass Scene;\nclass ResourceManager;\nclass MaterialGraph;\nclass RenderGraph;\nclass RenderGraphBlackboard;\nclass ShaderBuilder;\n\nnamespace Cmpt\n{\nclass Camera;\n}\n\nclass EXPORT_API Renderer\n{\n  public:\n\tRenderer(RHIContext *rhi_context, Scene *scene, ResourceManager *resource_manager);\n\n\t~Renderer();\n\n\tvoid Tick();\n\n\tvoid SetRenderGraph(std::unique_ptr<RenderGraph> &&render_graph);\n\n\tRenderGraph *GetRenderGraph() const;\n\n\tRHIContext *GetRHIContext() const;\n\n\tResourceManager *GetResourceManager() const;\n\n\tRenderGraphBlackboard &GetRenderGraphBlackboard();\n\n\tvoid SetViewport(float width, float height);\n\n\tglm::vec2 GetViewport() const;\n\n\tvoid SetAnimationTime(float time);\n\n\tvoid SetPresentTexture(RHITexture *present_texture);\n\n\tRHITexture *GetPresentTexture() const;\n\n\tfloat GetMaxAnimationTime() const;\n\n\tvoid UpdateView(Cmpt::Camera *camera);\n\n\tScene *GetScene() const;\n\n\tvoid Reset();\n\n  public:\n\t// Shader utils\n\tRHIShader *RequireShader(const std::string &filename, const std::string &entry_point, RHIShaderStage stage, std::vector<std::string> &&macros = {}, std::vector<std::string> &&includes = {}, bool cuda = false, bool force_recompile = false);\n\n\tShaderMeta RequireShaderMeta(RHIShader *shader) const;\n\n\t// RHIShader *RequireMaterialShader(MaterialGraph *material_graph, const std::string &filename, const std::string &entry_point, RHIShaderStage stage, std::vector<std::string> &&macros = {}, std::vector<std::string> &&includes = {});\n\n  private:\n\tvoid UpdateLight();\n\tvoid UpdateAnimation();\n\tvoid UpdateMesh();\n\tvoid UpdateSkinnedMesh();\n\tvoid UpdateMaterial();\n\tvoid UpdateGPUScene();\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Private/ShaderBuilder.cpp",
    "content": "#include \"ShaderBuilder.hpp\"\n#include \"ShaderCompiler.hpp\"\n\n#include <RHI/RHIDefinitions.hpp>\n\nnamespace Ilum\n{\nstruct ShaderBuilder::Impl\n{\n\tstd::unordered_map<size_t, std::unique_ptr<RHIShader>> shader_cache;\n\tstd::unordered_map<RHIShader *, ShaderMeta>            shader_meta_cache;\n\n\tstd::mutex mutex;\n};\n\nShaderBuilder::ShaderBuilder(RHIContext *context) :\n    p_rhi_context(context)\n{\n\tm_impl = new Impl;\n}\n\nShaderBuilder::~ShaderBuilder()\n{\n\tp_rhi_context->WaitIdle();\n\tdelete m_impl;\n}\n\nRHIShader *ShaderBuilder::RequireShader(const std::string &filename, const std::string &entry_point, RHIShaderStage stage, std::vector<std::string> &&macros, std::vector<std::string> &&includes, bool cuda, bool force_recompile)\n{\n\tsize_t hash = Hash(filename, entry_point, stage, macros, includes, cuda);\n\n\tif (!Path::GetInstance().IsExist(\"./bin/Shaders\"))\n\t{\n\t\tPath::GetInstance().CreatePath(\"./bin/Shaders\");\n\t}\n\n\tif (m_impl->shader_cache.find(hash) != m_impl->shader_cache.end() && !force_recompile)\n\t{\n\t\treturn m_impl->shader_cache.at(hash).get();\n\t}\n\n\tstd::string cache_path = \"./bin/Shaders/\" + std::to_string(hash) + \".shader\";\n\n\tstd::vector<uint8_t> shader_bin;\n\tShaderMeta           meta;\n\n\tif (Path::GetInstance().IsExist(cache_path) && !force_recompile)\n\t{\n\t\t// Read from cache\n\t\tsize_t last_write = 0;\n\n\t\tDESERIALIZE(\n\t\t    cache_path,\n\t\t    last_write,\n\t\t    shader_bin,\n\t\t    meta);\n\n\t\tif (last_write == std::filesystem::last_write_time(filename).time_since_epoch().count() && !shader_bin.empty())\n\t\t{\n\t\t\tstd::unique_ptr<RHIShader> shader = p_rhi_context->CreateShader(entry_point, shader_bin, cuda);\n\t\t\tm_impl->shader_meta_cache.emplace(shader.get(), std::move(meta));\n\t\t\tm_impl->shader_cache.emplace(hash, std::move(shader));\n\t\t\treturn m_impl->shader_cache.at(hash).get();\n\t\t}\n\t}\n\n\t{\n\t\tstd::vector<uint8_t> shader_code;\n\t\tPath::GetInstance().Read(filename, shader_code);\n\n\t\tShaderDesc desc = {};\n\t\tdesc.path       = filename;\n\t\tdesc.code.resize(shader_code.size());\n\t\tstd::memcpy(desc.code.data(), shader_code.data(), shader_code.size());\n\t\tfor (auto &include : includes)\n\t\t{\n\t\t\tdesc.code = fmt::format(\"#include \\\"{}\\\"\\n\", include) + desc.code;\n\t\t}\n\n\t\tdesc.source      = Path::GetInstance().GetFileExtension(filename) == \".hlsl\" ? ShaderSource::HLSL : ShaderSource::GLSL;\n\t\tdesc.stage       = stage;\n\t\tdesc.entry_point = entry_point;\n\t\tdesc.macros      = macros;\n\n\t\tif (cuda)\n\t\t{\n\t\t\tdesc.target = ShaderTarget::PTX;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (p_rhi_context->GetBackend() == \"Vulkan\")\n\t\t\t{\n\t\t\t\tdesc.target = ShaderTarget::SPIRV;\n\t\t\t}\n\t\t\telse if (p_rhi_context->GetBackend() == \"DX12\")\n\t\t\t{\n\t\t\t\tdesc.target = ShaderTarget::DXIL;\n\t\t\t}\n\t\t}\n\n\t\tshader_bin = ShaderCompiler::GetInstance().Compile(desc, meta);\n\n\t\tif (shader_bin.empty())\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\n\t\tSERIALIZE(\n\t\t    cache_path,\n\t\t    (size_t) std::filesystem::last_write_time(filename).time_since_epoch().count(),\n\t\t    shader_bin,\n\t\t    meta);\n\n\t\tstd::unique_ptr<RHIShader> shader = p_rhi_context->CreateShader(entry_point, shader_bin, cuda);\n\n\t\t{\n\t\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\t\tm_impl->shader_meta_cache.emplace(shader.get(), std::move(meta));\n\t\t\tm_impl->shader_cache.emplace(hash, std::move(shader));\n\t\t}\n\t\treturn m_impl->shader_cache.at(hash).get();\n\t}\n\n\treturn nullptr;\n}\n\nShaderMeta ShaderBuilder::RequireShaderMeta(RHIShader *shader) const\n{\n\treturn m_impl->shader_meta_cache.at(shader);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Private/ShaderCompiler.cpp",
    "content": "#include \"ShaderCompiler.hpp\"\n#include \"SpirvReflection.hpp\"\n\n#include <glslang/Include/ResourceLimits.h>\n#include <glslang/SPIRV/GLSL.std.450.h>\n#include <glslang/SPIRV/GlslangToSpv.h>\n\n#include <spirv_cross/spirv_hlsl.hpp>\n\n#include <wrl.h>\n\n#include <dxcapi.h>\n\n#include <slang.h>\n\nusing Microsoft::WRL::ComPtr;\n\nnamespace glslang\n{\nconst TBuiltInResource DefaultTBuiltInResource = {\n    /* .MaxLights = */ 32,\n    /* .MaxClipPlanes = */ 6,\n    /* .MaxTextureUnits = */ 32,\n    /* .MaxTextureCoords = */ 32,\n    /* .MaxVertexAttribs = */ 64,\n    /* .MaxVertexUniformComponents = */ 4096,\n    /* .MaxVaryingFloats = */ 64,\n    /* .MaxVertexTextureImageUnits = */ 32,\n    /* .MaxCombinedTextureImageUnits = */ 80,\n    /* .MaxTextureImageUnits = */ 32,\n    /* .MaxFragmentUniformComponents = */ 4096,\n    /* .MaxDrawBuffers = */ 32,\n    /* .MaxVertexUniformVectors = */ 128,\n    /* .MaxVaryingVectors = */ 8,\n    /* .MaxFragmentUniformVectors = */ 16,\n    /* .MaxVertexOutputVectors = */ 16,\n    /* .MaxFragmentInputVectors = */ 15,\n    /* .MinProgramTexelOffset = */ -8,\n    /* .MaxProgramTexelOffset = */ 7,\n    /* .MaxClipDistances = */ 8,\n    /* .MaxComputeWorkGroupCountX = */ 65535,\n    /* .MaxComputeWorkGroupCountY = */ 65535,\n    /* .MaxComputeWorkGroupCountZ = */ 65535,\n    /* .MaxComputeWorkGroupSizeX = */ 1024,\n    /* .MaxComputeWorkGroupSizeY = */ 1024,\n    /* .MaxComputeWorkGroupSizeZ = */ 64,\n    /* .MaxComputeUniformComponents = */ 1024,\n    /* .MaxComputeTextureImageUnits = */ 16,\n    /* .MaxComputeImageUniforms = */ 8,\n    /* .MaxComputeAtomicCounters = */ 8,\n    /* .MaxComputeAtomicCounterBuffers = */ 1,\n    /* .MaxVaryingComponents = */ 60,\n    /* .MaxVertexOutputComponents = */ 64,\n    /* .MaxGeometryInputComponents = */ 64,\n    /* .MaxGeometryOutputComponents = */ 128,\n    /* .MaxFragmentInputComponents = */ 128,\n    /* .MaxImageUnits = */ 8,\n    /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,\n    /* .MaxCombinedShaderOutputResources = */ 8,\n    /* .MaxImageSamples = */ 0,\n    /* .MaxVertexImageUniforms = */ 0,\n    /* .MaxTessControlImageUniforms = */ 0,\n    /* .MaxTessEvaluationImageUniforms = */ 0,\n    /* .MaxGeometryImageUniforms = */ 0,\n    /* .MaxFragmentImageUniforms = */ 8,\n    /* .MaxCombinedImageUniforms = */ 8,\n    /* .MaxGeometryTextureImageUnits = */ 16,\n    /* .MaxGeometryOutputVertices = */ 256,\n    /* .MaxGeometryTotalOutputComponents = */ 1024,\n    /* .MaxGeometryUniformComponents = */ 1024,\n    /* .MaxGeometryVaryingComponents = */ 64,\n    /* .MaxTessControlInputComponents = */ 128,\n    /* .MaxTessControlOutputComponents = */ 128,\n    /* .MaxTessControlTextureImageUnits = */ 16,\n    /* .MaxTessControlUniformComponents = */ 1024,\n    /* .MaxTessControlTotalOutputComponents = */ 4096,\n    /* .MaxTessEvaluationInputComponents = */ 128,\n    /* .MaxTessEvaluationOutputComponents = */ 128,\n    /* .MaxTessEvaluationTextureImageUnits = */ 16,\n    /* .MaxTessEvaluationUniformComponents = */ 1024,\n    /* .MaxTessPatchComponents = */ 120,\n    /* .MaxPatchVertices = */ 32,\n    /* .MaxTessGenLevel = */ 64,\n    /* .MaxViewports = */ 16,\n    /* .MaxVertexAtomicCounters = */ 0,\n    /* .MaxTessControlAtomicCounters = */ 0,\n    /* .MaxTessEvaluationAtomicCounters = */ 0,\n    /* .MaxGeometryAtomicCounters = */ 0,\n    /* .MaxFragmentAtomicCounters = */ 8,\n    /* .MaxCombinedAtomicCounters = */ 8,\n    /* .MaxAtomicCounterBindings = */ 1,\n    /* .MaxVertexAtomicCounterBuffers = */ 0,\n    /* .MaxTessControlAtomicCounterBuffers = */ 0,\n    /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,\n    /* .MaxGeometryAtomicCounterBuffers = */ 0,\n    /* .MaxFragmentAtomicCounterBuffers = */ 1,\n    /* .MaxCombinedAtomicCounterBuffers = */ 1,\n    /* .MaxAtomicCounterBufferSize = */ 16384,\n    /* .MaxTransformFeedbackBuffers = */ 4,\n    /* .MaxTransformFeedbackInterleavedComponents = */ 64,\n    /* .MaxCullDistances = */ 8,\n    /* .MaxCombinedClipAndCullDistances = */ 8,\n    /* .MaxSamples = */ 4,\n    /* .maxMeshOutputVerticesNV= */ 256,\n    /* .maxMeshOutputPrimitivesNV= */ 512,\n    /* .maxMeshWorkGroupSizeX_NV= */ 32,\n    /* .maxMeshWorkGroupSizeY_NV= */ 1,\n    /* .maxMeshWorkGroupSizeZ_NV= */ 1,\n    /* .maxTaskWorkGroupSizeX_NV= */ 32,\n    /* .maxTaskWorkGroupSizeY_NV= */ 1,\n    /* .maxTaskWorkGroupSizeZ_NV= */ 1,\n    /* .maxMeshViewCountNV= */ 4,\n    /* .maxMeshOutputVerticesEXT= */ 256,\n    /* .maxMeshOutputPrimitivesEXT= */ 512,\n    /* .maxMeshWorkGroupSizeX_EXT= */ 32,\n    /* .maxMeshWorkGroupSizeY_EXT= */ 32,\n    /* .maxMeshWorkGroupSizeZ_EXT= */ 32,\n    /* .maxTaskWorkGroupSizeX_EXT= */ 32,\n    /* .maxTaskWorkGroupSizeY_EXT= */ 32,\n    /* .maxTaskWorkGroupSizeZ_EXT= */ 32,\n    /* .maxMeshViewCountEXT= */ 4,\n    /* .maxDualSourceDrawBuffersEXT= */ 1,\n\n    /* .limits = */ {\n        /* .nonInductiveForLoops = */ true,\n        /* .whileLoops = */ true,\n        /* .doWhileLoops = */ 1,\n        /* .generalUniformIndexing = */ 1,\n        /* .generalAttributeMatrixVectorIndexing = */ 1,\n        /* .generalVaryingIndexing = */ 1,\n        /* .generalSamplerIndexing = */ 1,\n        /* .generalVariableIndexing = */ 1,\n        /* .generalConstantMatrixVectorIndexing = */ 1,\n    }};\n}\n\nnamespace Ilum\n{\nstruct ShaderCompiler::Impl\n{\n\tComPtr<IDxcCompiler3>      DXCCompiler           = nullptr;\n\tComPtr<IDxcUtils>          DXCUtils              = nullptr;\n\tComPtr<IDxcIncludeHandler> DefaultIncludeHandler = nullptr;\n\tSlangSession              *Session               = nullptr;\n};\n\nstd::wstring to_wstring(const std::string &str)\n{\n\tconst auto slength = static_cast<int>(str.length()) + 1;\n\tconst auto len     = MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, nullptr, 0);\n\tconst auto buf     = new wchar_t[len];\n\tMultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, buf, len);\n\tstd::wstring result(buf);\n\tdelete[] buf;\n\treturn result;\n}\n\ninline std::string GetTargetProfile(RHIShaderStage stage)\n{\n\tswitch (stage)\n\t{\n\t\tcase RHIShaderStage::Vertex:\n\t\t\treturn \"vs_6_7\";\n\t\tcase RHIShaderStage::Fragment:\n\t\t\treturn \"ps_6_7\";\n\t\tcase RHIShaderStage::TessellationControl:\n\t\t\treturn \"hs_6_7\";\n\t\tcase RHIShaderStage::TessellationEvaluation:\n\t\t\treturn \"ds_6_7\";\n\t\tcase RHIShaderStage::Geometry:\n\t\t\treturn \"gs_6_7\";\n\t\tcase RHIShaderStage::Compute:\n\t\t\treturn \"cs_6_7\";\n\t\tcase RHIShaderStage::RayGen:\n\t\tcase RHIShaderStage::AnyHit:\n\t\tcase RHIShaderStage::ClosestHit:\n\t\tcase RHIShaderStage::Miss:\n\t\tcase RHIShaderStage::Intersection:\n\t\tcase RHIShaderStage::Callable:\n\t\t\treturn \"lib_6_7\";\n\t\tcase RHIShaderStage::Mesh:\n\t\t\treturn \"ms_6_7\";\n\t\tcase RHIShaderStage::Task:\n\t\t\treturn \"as_6_7\";\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn \"\";\n}\n\ninline EShLanguage GetShaderLanguage(RHIShaderStage stage)\n{\n\tswitch (stage)\n\t{\n\t\tcase RHIShaderStage::Vertex:\n\t\t\treturn EShLangVertex;\n\t\tcase RHIShaderStage::Fragment:\n\t\t\treturn EShLangFragment;\n\t\tcase RHIShaderStage::TessellationControl:\n\t\t\treturn EShLangTessControl;\n\t\tcase RHIShaderStage::TessellationEvaluation:\n\t\t\treturn EShLangTessEvaluation;\n\t\tcase RHIShaderStage::Geometry:\n\t\t\treturn EShLangGeometry;\n\t\tcase RHIShaderStage::Compute:\n\t\t\treturn EShLangCompute;\n\t\tcase RHIShaderStage::RayGen:\n\t\t\treturn EShLangRayGen;\n\t\tcase RHIShaderStage::AnyHit:\n\t\t\treturn EShLangAnyHit;\n\t\tcase RHIShaderStage::ClosestHit:\n\t\t\treturn EShLangClosestHit;\n\t\tcase RHIShaderStage::Miss:\n\t\t\treturn EShLangMiss;\n\t\tcase RHIShaderStage::Intersection:\n\t\t\treturn EShLangIntersect;\n\t\tcase RHIShaderStage::Callable:\n\t\t\treturn EShLangCallable;\n\t\tcase RHIShaderStage::Mesh:\n\t\t\treturn EShLangMesh;\n\t\tcase RHIShaderStage::Task:\n\t\t\treturn EShLangTask;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn EShLangCount;\n}\n\ntemplate <ShaderSource Src, ShaderTarget Tar>\ninline std::vector<uint8_t> CompileShader(ShaderCompiler::Impl *impl, const ShaderDesc &desc)\n{\n\treturn {};\n}\n\ntemplate <>\nstd::vector<uint8_t> CompileShader<ShaderSource::GLSL, ShaderTarget::SPIRV>(ShaderCompiler::Impl *impl, const ShaderDesc &desc)\n{\n\tEShMessages msgs = static_cast<EShMessages>(EShMsgDefault | EShMsgVulkanRules | EShMsgSpvRules);\n\n\tEShLanguage lang = GetShaderLanguage(desc.stage);\n\n\tstd::string info_log = \"\";\n\n\tconst char *file_name_list[1] = {\"\"};\n\tconst char *shader_source     = reinterpret_cast<const char *>(desc.code.data());\n\n\tglslang::TShader shader(lang);\n\tshader.setStringsWithLengthsAndNames(&shader_source, nullptr, file_name_list, 1);\n\tshader.setEntryPoint(desc.entry_point.c_str());\n\tshader.setSourceEntryPoint(desc.entry_point.c_str());\n\tshader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_5);\n\tshader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_3);\n\tfor (const auto &macro : desc.macros)\n\t{\n\t\tshader.setPreamble(macro.c_str());\n\t}\n\n\tif (!shader.parse(&glslang::DefaultTBuiltInResource, 100, false, msgs))\n\t{\n\t\tinfo_log = std::string(shader.getInfoLog()) + \"\\n\" + std::string(shader.getInfoDebugLog());\n\t\tLOG_ERROR(info_log);\n\t\treturn {};\n\t}\n\n\t// Add shader to a new program\n\tglslang::TProgram program;\n\tprogram.addShader(&shader);\n\n\t// Link program\n\tif (!program.link(msgs))\n\t{\n\t\tinfo_log = std::string(program.getInfoLog()) + \"\\n\" + std::string(program.getInfoDebugLog());\n\t\tLOG_ERROR(info_log);\n\t\treturn {};\n\t}\n\n\t// Save info log\n\tif (shader.getInfoLog())\n\t{\n\t\tinfo_log = std::string(shader.getInfoLog()) + \"\\n\" + std::string(shader.getInfoDebugLog());\n\t}\n\n\tif (program.getInfoLog())\n\t{\n\t\tinfo_log = std::string(program.getInfoLog()) + \"\\n\" + std::string(program.getInfoDebugLog());\n\t}\n\n\tglslang::TIntermediate *intermediate = program.getIntermediate(lang);\n\n\tif (!intermediate)\n\t{\n\t\tinfo_log += \"Failed to get shared intermediate code!\\n\";\n\t\tLOG_ERROR(info_log);\n\t\treturn {};\n\t}\n\n\tspv::SpvBuildLogger logger;\n\n\tstd::vector<uint32_t> spirv;\n\tstd::vector<uint8_t>  result;\n\n\tglslang::GlslangToSpv(*intermediate, spirv, &logger);\n\tresult.resize(spirv.size() * 4);\n\tstd::memcpy(result.data(), spirv.data(), result.size());\n\n\treturn result;\n}\n\ntemplate <>\nstd::vector<uint8_t> CompileShader<ShaderSource::HLSL, ShaderTarget::SPIRV>(ShaderCompiler::Impl *impl, const ShaderDesc &desc)\n{\n\tDxcBuffer                dxc_buffer    = {};\n\tComPtr<IDxcBlobEncoding> blob_encoding = nullptr;\n\n\tstd::string shader_code = std::string(desc.code.c_str());\n\n\t{\n\t\tif (FAILED(impl->DXCUtils->CreateBlobFromPinned(shader_code.data(), static_cast<uint32_t>(shader_code.size()), CP_UTF8, &blob_encoding)))\n\t\t{\n\t\t\tLOG_ERROR(\"Failed to load shader source.\");\n\t\t\treturn {};\n\t\t}\n\n\t\tdxc_buffer.Ptr      = blob_encoding->GetBufferPointer();\n\t\tdxc_buffer.Size     = blob_encoding->GetBufferSize();\n\t\tdxc_buffer.Encoding = DXC_CP_ACP;\n\t}\n\n\tstd::vector<std::wstring> arguments;\n\n\t// Compile arguments\n\targuments.emplace_back(L\"-E\");\n\targuments.emplace_back(to_wstring(desc.entry_point));\n\targuments.emplace_back(L\"-T\");\n\targuments.emplace_back(to_wstring(GetTargetProfile(desc.stage)));\n\targuments.emplace_back(L\"-I\");\n\targuments.emplace_back(to_wstring(Path::GetInstance().GetCurrent() + \"/Source/Shaders\"));\n\targuments.emplace_back(L\"-I\");\n\targuments.emplace_back(to_wstring(Path::GetInstance().GetCurrent() + \"/Asset/Material\"));\n\targuments.emplace_back(L\"-I\");\n\targuments.emplace_back(to_wstring(Path::GetInstance().GetCurrent()));\n\targuments.emplace_back(L\"-I\");\n\targuments.emplace_back(to_wstring(Path::GetInstance().GetCurrent() + \"/\" + Path::GetInstance().GetFileDirectory(desc.path)));\n\targuments.emplace_back(L\"-HV 2021\");\n\targuments.emplace_back(to_wstring(\"-DRUNTIME\"));\n\targuments.emplace_back(L\"-spirv\");\n\targuments.emplace_back(L\"-fspv-target-env=vulkan1.3\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_KHR_ray_tracing\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_KHR_ray_query\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_KHR_shader_draw_parameters\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_EXT_descriptor_indexing\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_EXT_shader_viewport_index_layer\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_EXT_mesh_shader\");\n\targuments.emplace_back(L\"-fspv-extension=SPV_AMD_shader_explicit_vertex_parameter\");\n\targuments.emplace_back(L\"-disable-payload-qualifiers\");\n\n\tfor (const auto &macro : desc.macros)\n\t{\n\t\targuments.emplace_back(to_wstring(std::string(\"-D\") + macro));\n\t}\n\n\t// Convert arguments to LPCWSTR\n\tstd::vector<LPCWSTR> arguments_lpcwstr;\n\targuments_lpcwstr.reserve(arguments.size());\n\tfor (const std::wstring &wstr : arguments)\n\t{\n\t\targuments_lpcwstr.emplace_back(wstr.c_str());\n\t}\n\n\t// Compile\n\tIDxcResult *dxc_result = nullptr;\n\timpl->DXCCompiler->Compile(\n\t    &dxc_buffer,\n\t    arguments_lpcwstr.data(),\n\t    static_cast<uint32_t>(arguments_lpcwstr.size()),\n\t    impl->DefaultIncludeHandler.Get(),\n\t    IID_PPV_ARGS(&dxc_result));\n\n\t// Get error buffer\n\tIDxcBlobEncoding *error_buffer = nullptr;\n\tHRESULT           result       = dxc_result->GetErrorBuffer(&error_buffer);\n\tif (SUCCEEDED(result))\n\t{\n\t\t// Log info, warnings and errors\n\t\tstd::stringstream ss(std::string(static_cast<char *>(error_buffer->GetBufferPointer()), error_buffer->GetBufferSize()));\n\t\tstd::string       line;\n\t\twhile (getline(ss, line, '\\n'))\n\t\t{\n\t\t\tif (line.find(\"error\") != std::string::npos)\n\t\t\t{\n\t\t\t\tLOG_ERROR(\"{}\", line);\n\t\t\t}\n\t\t\telse if (line.find(\"warning\") != std::string::npos)\n\t\t\t{\n\t\t\t\tLOG_WARN(\"{}\", line);\n\t\t\t}\n\t\t\telse if (!line.empty())\n\t\t\t{\n\t\t\t\tLOG_INFO(\"{}\", line);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tLOG_ERROR(\"Failed to get error buffer\");\n\t}\n\n\t// Release error buffer\n\tif (error_buffer)\n\t{\n\t\terror_buffer->Release();\n\t\terror_buffer = nullptr;\n\t}\n\n\t// Return status\n\tdxc_result->GetStatus(&result);\n\n\t// Check for errors\n\tif (result != S_OK)\n\t{\n\t\tLOG_ERROR(\"Failed to compile\");\n\n\t\tif (dxc_result)\n\t\t{\n\t\t\tdxc_result->Release();\n\t\t\tdxc_result = nullptr;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn {};\n\t\t}\n\t}\n\n\tIDxcBlob *shader_buffer = nullptr;\n\tdxc_result->GetResult(&shader_buffer);\n\n\tstd::vector<uint8_t> spirv(shader_buffer->GetBufferSize());\n\tstd::memcpy(spirv.data(), shader_buffer->GetBufferPointer(), shader_buffer->GetBufferSize());\n\n\treturn spirv;\n}\n\ntemplate <>\nstd::vector<uint8_t> CompileShader<ShaderSource::HLSL, ShaderTarget::DXIL>(ShaderCompiler::Impl *impl, const ShaderDesc &desc)\n{\n\tDxcBuffer                dxc_buffer    = {};\n\tComPtr<IDxcBlobEncoding> blob_encoding = nullptr;\n\n\tstd::string shader_code = std::string(desc.code.c_str());\n\n\t{\n\t\tif (FAILED(impl->DXCUtils->CreateBlobFromPinned(shader_code.c_str(), static_cast<uint32_t>(shader_code.size()), CP_UTF8, &blob_encoding)))\n\t\t{\n\t\t\tLOG_ERROR(\"Failed to load shader source.\");\n\t\t\treturn {};\n\t\t}\n\n\t\tdxc_buffer.Ptr      = blob_encoding->GetBufferPointer();\n\t\tdxc_buffer.Size     = blob_encoding->GetBufferSize();\n\t\tdxc_buffer.Encoding = DXC_CP_ACP;\n\t}\n\n\tstd::vector<std::wstring> arguments;\n\n\t// Compile arguments\n\targuments.emplace_back(L\"-E\");\n\targuments.emplace_back(to_wstring(desc.entry_point));\n\targuments.emplace_back(L\"-T\");\n\targuments.emplace_back(to_wstring(GetTargetProfile(desc.stage)));\n\targuments.emplace_back(L\"-I\");\n\targuments.emplace_back(to_wstring(Path::GetInstance().GetCurrent() + \"/Source/Shaders\"));\n\n\tfor (const auto &macro : desc.macros)\n\t{\n\t\targuments.emplace_back(to_wstring(std::string(\"-D\") + macro));\n\t}\n\n\t// Convert arguments to LPCWSTR\n\tstd::vector<LPCWSTR> arguments_lpcwstr;\n\targuments_lpcwstr.reserve(arguments.size());\n\tfor (const std::wstring &wstr : arguments)\n\t{\n\t\targuments_lpcwstr.emplace_back(wstr.c_str());\n\t}\n\n\t// Compile\n\tIDxcResult *dxc_result = nullptr;\n\timpl->DXCCompiler->Compile(\n\t    &dxc_buffer,\n\t    arguments_lpcwstr.data(),\n\t    static_cast<uint32_t>(arguments_lpcwstr.size()),\n\t    impl->DefaultIncludeHandler.Get(),\n\t    IID_PPV_ARGS(&dxc_result));\n\n\t// Get error buffer\n\tIDxcBlobEncoding *error_buffer = nullptr;\n\tHRESULT           result       = dxc_result->GetErrorBuffer(&error_buffer);\n\tif (SUCCEEDED(result))\n\t{\n\t\t// Log info, warnings and errors\n\t\tstd::stringstream ss(std::string(static_cast<char *>(error_buffer->GetBufferPointer()), error_buffer->GetBufferSize()));\n\t\tstd::string       line;\n\t\twhile (getline(ss, line, '\\n'))\n\t\t{\n\t\t\tif (line.find(\"error\") != std::string::npos)\n\t\t\t{\n\t\t\t\tLOG_ERROR(\"{}\", line);\n\t\t\t}\n\t\t\telse if (line.find(\"warning\") != std::string::npos)\n\t\t\t{\n\t\t\t\tLOG_WARN(\"{}\", line);\n\t\t\t}\n\t\t\telse if (!line.empty())\n\t\t\t{\n\t\t\t\tLOG_INFO(\"{}\", line);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tLOG_ERROR(\"Failed to get error buffer\");\n\t}\n\n\t// Release error buffer\n\tif (error_buffer)\n\t{\n\t\terror_buffer->Release();\n\t\terror_buffer = nullptr;\n\t}\n\n\t// Return status\n\tdxc_result->GetStatus(&result);\n\n\t// Check for errors\n\tif (result != S_OK)\n\t{\n\t\tLOG_ERROR(\"Failed to compile\");\n\n\t\tif (dxc_result)\n\t\t{\n\t\t\tdxc_result->Release();\n\t\t\tdxc_result = nullptr;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn {};\n\t\t}\n\t}\n\n\tIDxcBlob *shader_buffer = nullptr;\n\tdxc_result->GetResult(&shader_buffer);\n\n\tstd::vector<uint8_t> dxil(shader_buffer->GetBufferSize());\n\tstd::memcpy(dxil.data(), shader_buffer->GetBufferPointer(), shader_buffer->GetBufferSize());\n\n\treturn dxil;\n}\n\ntemplate <>\nstd::vector<uint8_t> CompileShader<ShaderSource::HLSL, ShaderTarget::PTX>(ShaderCompiler::Impl *impl, const ShaderDesc &desc)\n{\n\tSlangCompileRequest *request = spCreateCompileRequest(impl->Session);\n\n\tspSetCodeGenTarget(request, SLANG_PTX);\n\n\tint translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, \"\");\n\tspAddTranslationUnitSourceString(request, translationUnitIndex, nullptr, std::string(desc.code.c_str()).c_str());\n\tint entryPointIndex = spAddEntryPoint(request, translationUnitIndex, desc.entry_point.c_str(), SLANG_STAGE_COMPUTE);\n\n\tint anyErrors = spCompile(request);\n\n\tif (anyErrors != 0)\n\t{\n\t\tchar const *diagnostics = spGetDiagnosticOutput(request);\n\t\tLOG_INFO(\"Shader Compile Error: {}\", diagnostics);\n\t\treturn {};\n\t}\n\n\tstd::string ptx_str = spGetEntryPointSource(request, entryPointIndex);\n\n\tspDestroyCompileRequest(request);\n\n\tstd::vector<uint8_t> ptx(ptx_str.size());\n\tstd::memcpy(ptx.data(), ptx_str.data(), ptx_str.size());\n\n\treturn ptx;\n}\n\ninline std::string SpirvCrossToHLSL(const std::vector<uint8_t> &spirv)\n{\n\tstd::vector<uint32_t> spirv32;\n\tspirv32.resize(spirv.size() / 4);\n\tstd::memcpy(spirv32.data(), spirv.data(), spirv.size());\n\n\tspirv_cross::CompilerHLSL hlsl_compiler(spirv32);\n\n\tspirv_cross::CompilerHLSL::Options options;\n\toptions.shader_model         = 66;\n\toptions.use_entry_point_name = true;\n\n\thlsl_compiler.set_hlsl_options(options);\n\n\treturn hlsl_compiler.compile();\n}\n\nShaderCompiler::ShaderCompiler()\n{\n\tm_impl = new Impl;\n\n\t// Init glslang\n\tglslang::InitializeProcess();\n\n\t// Init dxc\n\tPluginManager::GetInstance().Call(\"Source/External/dxc/bin/x64/dxcompiler.dll\", \"DxcCreateInstance\", CLSID_DxcUtils, IID_PPV_ARGS(&m_impl->DXCUtils));\n\tPluginManager::GetInstance().Call(\"Source/External/dxc/bin/x64/dxcompiler.dll\", \"DxcCreateInstance\", CLSID_DxcCompiler, IID_PPV_ARGS(&m_impl->DXCCompiler));\n\t// DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&m_impl->DXCUtils));\n\t// DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&m_impl->DXCCompiler));\n\n\tm_impl->DXCUtils->CreateDefaultIncludeHandler(&m_impl->DefaultIncludeHandler);\n\n\t// Init slang\n\tm_impl->Session = spCreateSession(NULL);\n}\n\nShaderCompiler::~ShaderCompiler()\n{\n\tglslang::FinalizeProcess();\n\n\t// It's weird\n\tm_impl->DXCUtils.Detach();\n\tm_impl->DXCCompiler.Detach();\n\tm_impl->DefaultIncludeHandler.Detach();\n\n\tspDestroySession(m_impl->Session);\n\tm_impl->Session = nullptr;\n\n\tdelete m_impl;\n\tm_impl = nullptr;\n}\n\nShaderCompiler &ShaderCompiler::GetInstance()\n{\n\tstatic ShaderCompiler shader_compiler;\n\treturn shader_compiler;\n}\n\nstd::vector<uint8_t> ShaderCompiler::Compile(const ShaderDesc &desc, ShaderMeta &meta)\n{\n\t// Compile to SPIRV\n\tstd::vector<uint8_t> spirv;\n\n\tif (desc.source == ShaderSource::GLSL)\n\t{\n\t\tspirv = CompileShader<ShaderSource::GLSL, ShaderTarget::SPIRV>(m_impl, desc);\n\t}\n\telse if (desc.source == ShaderSource::HLSL)\n\t{\n\t\tspirv = CompileShader<ShaderSource::HLSL, ShaderTarget::SPIRV>(m_impl, desc);\n\t}\n\n\tmeta = SpirvReflection::GetInstance().Reflect(spirv);\n\n\tif (desc.target == ShaderTarget::SPIRV)\n\t{\n\t\treturn spirv;\n\t}\n\telse if (desc.target == ShaderTarget::DXIL)\n\t{\n\t\tif (desc.source == ShaderSource::GLSL)\n\t\t{\n\t\t\treturn CompileShader<ShaderSource::GLSL, ShaderTarget::DXIL>(m_impl, desc);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn CompileShader<ShaderSource::HLSL, ShaderTarget::DXIL>(m_impl, desc);\n\t\t}\n\t}\n\telse if (desc.target == ShaderTarget::PTX)\n\t{\n\t\tif (desc.source == ShaderSource::GLSL)\n\t\t{\n\t\t\treturn CompileShader<ShaderSource::GLSL, ShaderTarget::PTX>(m_impl, desc);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstd::string hlsl = SpirvCrossToHLSL(spirv);\n\n\t\t\t{\n\t\t\t\t// Remove \"packoffset\"\n\t\t\t\thlsl = std::regex_replace(hlsl, std::regex(\": +packoffset*.+;\"), \";\");\n\n\t\t\t\t// Remove input parameter\n\t\t\t\tsize_t pos   = hlsl.find(\"struct SPIRV_Cross_Input\");\n\t\t\t\tsize_t left  = hlsl.find_first_of(\"{\", pos) + 1;\n\t\t\t\tsize_t right = hlsl.find_first_of(\"}\", left);\n\n\t\t\t\tstd::string input_struct = hlsl.substr(left, right - left);\n\n\t\t\t\tright        = input_struct.find_last_of(\";\");\n\t\t\t\tinput_struct = input_struct.substr(0, right);\n\n\t\t\t\tstd::replace(input_struct.begin(), input_struct.end(), ';', ',');\n\t\t\t\tinput_struct = std::regex_replace(input_struct, std::regex(\"gl_\"), \"glx\");\n\n\t\t\t\thlsl = std::regex_replace(hlsl, std::regex(\"SPIRV_Cross_Input stage_input\"), input_struct);\n\t\t\t\thlsl = std::regex_replace(hlsl, std::regex(\"stage_input.gl_\"), \"glx\");\n\n\t\t\t\t// Order may change, so re-reflect it\n\t\t\t\tShaderMeta before_meta = std::move(meta);\n\n\t\t\t\tShaderDesc hlsl_desc = desc;\n\t\t\t\thlsl_desc.code       = hlsl;\n\t\t\t\tmeta                 = SpirvReflection::GetInstance().Reflect(CompileShader<ShaderSource::HLSL, ShaderTarget::SPIRV>(m_impl, hlsl_desc));\n\n\t\t\t\t// Fix name\n\t\t\t\tfor (auto &descriptor : meta.descriptors)\n\t\t\t\t{\n\t\t\t\t\tfor (auto &before_descriptor : before_meta.descriptors)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (descriptor == before_descriptor)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescriptor.name = before_descriptor.name;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tShaderDesc hlsl_desc = desc;\n\t\t\thlsl_desc.code       = hlsl;\n\t\t\treturn CompileShader<ShaderSource::HLSL, ShaderTarget::PTX>(m_impl, hlsl_desc);\n\t\t}\n\t}\n\n\treturn {};\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Private/SpirvReflection.cpp",
    "content": "#include \"SpirvReflection.hpp\"\n\n#include <spirv_reflect.h>\n\nnamespace Ilum\n{\ninline static std::unordered_map<SpvReflectShaderStageFlagBits, RHIShaderStage> ShaderStageMap = {\n    {SPV_REFLECT_SHADER_STAGE_VERTEX_BIT, RHIShaderStage::Vertex},\n    {SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT, RHIShaderStage::TessellationControl},\n    {SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, RHIShaderStage::TessellationEvaluation},\n    {SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT, RHIShaderStage::Geometry},\n    {SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT, RHIShaderStage::Fragment},\n    {SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT, RHIShaderStage::Compute},\n    {SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV, RHIShaderStage::Task},\n    {SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV, RHIShaderStage::Mesh},\n    {SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR, RHIShaderStage::RayGen},\n    {SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR, RHIShaderStage::AnyHit},\n    {SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, RHIShaderStage::ClosestHit},\n    {SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR, RHIShaderStage::Miss},\n    {SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR, RHIShaderStage::Intersection},\n    {SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR, RHIShaderStage::Callable},\n};\n\ninline static std::unordered_map<SpvReflectDescriptorType, DescriptorType> DescriptorTypeMap = {\n    {SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER, DescriptorType::Sampler},\n    {SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE, DescriptorType::TextureSRV},\n    {SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE, DescriptorType::TextureUAV},\n    {SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER, DescriptorType::ConstantBuffer},\n    {SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorType::StructuredBuffer},\n    {SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, DescriptorType::AccelerationStructure},\n};\n\ninline static std::unordered_map<SpvReflectFormat, RHIFormat> FormatMap = {\n    {SPV_REFLECT_FORMAT_UNDEFINED, RHIFormat::Undefined},\n    {SPV_REFLECT_FORMAT_R32_UINT, RHIFormat::R32_UINT},\n    {SPV_REFLECT_FORMAT_R32_SINT, RHIFormat::R32_SINT},\n    {SPV_REFLECT_FORMAT_R32_SFLOAT, RHIFormat::R32_FLOAT},\n    {SPV_REFLECT_FORMAT_R32G32_UINT, RHIFormat::R32G32_UINT},\n    {SPV_REFLECT_FORMAT_R32G32_SINT, RHIFormat::R32G32_SINT},\n    {SPV_REFLECT_FORMAT_R32G32_SFLOAT, RHIFormat::R32G32_FLOAT},\n    {SPV_REFLECT_FORMAT_R32G32B32_UINT, RHIFormat::R32G32B32_UINT},\n    {SPV_REFLECT_FORMAT_R32G32B32_SINT, RHIFormat::R32G32B32_SINT},\n    {SPV_REFLECT_FORMAT_R32G32B32_SFLOAT, RHIFormat::R32G32B32_FLOAT},\n    {SPV_REFLECT_FORMAT_R32G32B32A32_UINT, RHIFormat::R32G32B32A32_UINT},\n    {SPV_REFLECT_FORMAT_R32G32B32A32_SINT, RHIFormat::R32G32B32A32_SINT},\n    {SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT, RHIFormat::R32G32B32A32_FLOAT},\n};\n\nSpirvReflection &SpirvReflection::GetInstance()\n{\n\tstatic SpirvReflection spirv_reflection;\n\treturn spirv_reflection;\n}\n\nShaderMeta SpirvReflection::Reflect(const std::vector<uint8_t> &spirv)\n{\n\tSpvReflectShaderModule shader_module;\n\tspvReflectCreateShaderModule(spirv.size(), spirv.data(), &shader_module);\n\n\tShaderMeta meta_info = {};\n\n\t// Descriptor\n\tfor (uint32_t i = 0; i < shader_module.descriptor_binding_count; i++)\n\t{\n\t\tconst auto &descriptor_binding = shader_module.descriptor_bindings[i];\n\n\t\tmeta_info.descriptors.push_back(ShaderMeta::Descriptor{\n\t\t\tdescriptor_binding.spirv_id,\n\t\t    descriptor_binding.name,\n\t\t    descriptor_binding.count,\n\t\t    descriptor_binding.set,\n\t\t    descriptor_binding.binding,\n\t\t    DescriptorTypeMap[descriptor_binding.descriptor_type],\n\t\t    ShaderStageMap[shader_module.shader_stage]});\n\n\t\tHashCombine(meta_info.hash,\n\t\t            descriptor_binding.name,\n\t\t            descriptor_binding.count,\n\t\t            descriptor_binding.set,\n\t\t            descriptor_binding.binding,\n\t\t            DescriptorTypeMap[descriptor_binding.descriptor_type],\n\t\t            ShaderStageMap[shader_module.shader_stage]);\n\t}\n\n\t// Constant\n\tfor (uint32_t i = 0; i < shader_module.push_constant_block_count; i++)\n\t{\n\t\tfor (uint32_t j = 0; j < shader_module.push_constant_blocks[i].member_count; j++)\n\t\t{\n\t\t\tauto member = shader_module.push_constant_blocks[i].members[j];\n\n\t\t\tmeta_info.constants.push_back(ShaderMeta::Constant{\n\t\t\t\tmember.spirv_id,\n\t\t\t    member.name,\n\t\t\t    member.size,\n\t\t\t    member.absolute_offset,\n\t\t\t    ShaderStageMap[shader_module.shader_stage]});\n\n\t\t\tHashCombine(\n\t\t\t    meta_info.hash,\n\t\t\t    member.name,\n\t\t\t    member.size,\n\t\t\t    member.absolute_offset,\n\t\t\t    ShaderStageMap[shader_module.shader_stage]);\n\t\t}\n\t}\n\n\t// Variable\n\tif (shader_module.shader_stage & SPV_REFLECT_SHADER_STAGE_VERTEX_BIT)\n\t{\n\t\tfor (uint32_t i = 0; i < shader_module.input_variable_count; i++)\n\t\t{\n\t\t\tmeta_info.inputs.push_back(ShaderMeta::Variable{\n\t\t\t    shader_module.input_variables[i]->spirv_id,\n\t\t\t    shader_module.input_variables[i]->location,\n\t\t\t    FormatMap[shader_module.input_variables[i]->format]\n\t\t\t});\n\t\t}\n\t}\n\telse if (shader_module.shader_stage & SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT)\n\t{\n\t\tfor (uint32_t i = 0; i < shader_module.output_variable_count; i++)\n\t\t{\n\t\t\tmeta_info.outputs.push_back(ShaderMeta::Variable{\n\t\t\t    shader_module.output_variables[i]->spirv_id,\n\t\t\t    shader_module.output_variables[i]->location,\n\t\t\t    FormatMap[shader_module.output_variables[i]->format]});\n\t\t}\n\t}\n\n\tspvReflectDestroyShaderModule(&shader_module);\n\n\treturn meta_info;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Public/ShaderCompiler/Precompile.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Public/ShaderCompiler/ShaderBuilder.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass  ShaderBuilder\n{\n  public:\n\tShaderBuilder(RHIContext *context);\n\n\t~ShaderBuilder();\n\n\tRHIShader *RequireShader(const std::string &filename, const std::string &entry_point, RHIShaderStage stage, std::vector<std::string> &&macros = {}, std::vector<std::string> &&includes = {}, bool cuda = false, bool force_recompile = false);\n\n\tShaderMeta RequireShaderMeta(RHIShader *shader) const;\n\n  private:\n\tRHIContext *p_rhi_context = nullptr;\n\n\tstruct Impl;\n\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Public/ShaderCompiler/ShaderCompiler.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <RHI/RHIDefinitions.hpp>\n#include <RHI/RHIShader.hpp>\n\nnamespace Ilum\n{\nenum class ShaderSource\n{\n\tHLSL,\n\tGLSL\n};\n\nenum class ShaderTarget\n{\n\tSPIRV,\n\tDXIL,\n\tPTX\n};\n\nstruct ShaderDesc\n{\n\tstd::string    code;\n\tstd::string    path;\n\tShaderSource   source;\n\tShaderTarget   target;\n\tRHIShaderStage stage;\n\tstd::string    entry_point;\n\n\tstd::vector<std::string> macros = {};\n};\n\nclass ShaderCompiler\n{\n  public:\n\tShaderCompiler();\n\n\t~ShaderCompiler();\n\n\tstatic ShaderCompiler &GetInstance();\n\n\tstd::vector<uint8_t> Compile(const ShaderDesc &desc, ShaderMeta &meta);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/ShaderCompiler/Public/ShaderCompiler/SpirvReflection.hpp",
    "content": "#pragma once\n\n#include \"Precompile.hpp\"\n\n#include <RHI/RHIShader.hpp>\n\nnamespace Ilum\n{\nclass  SpirvReflection\n{\n  public:\n\tstatic SpirvReflection &GetInstance();\n\n\tShaderMeta Reflect(const std::vector<uint8_t> &spirv);\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Render/xmake.lua",
    "content": "add_runtime_moulde(\n    \"ShaderCompiler\",\n    \"Runtime/Render\",\n    false, \n    {\"Core\", \"RHI\"}, \n    {\"glslang\", \"spirv-cross\", \"directxshadercompiler\", \"slang\", \"spirv-reflect\"}\n)\n\nadd_runtime_moulde(\n    \"RenderGraph\",\n    \"Runtime/Render\",\n    false, \n    {\"Core\", \"RHI\", \"ShaderCompiler\"}, \n    {}\n)\n\nadd_runtime_moulde(\n    \"Material\",\n    \"Runtime/Render\",\n    false, \n    {\"Core\", \"RHI\"}, \n    {}\n)\n\nadd_runtime_moulde(\n    \"Renderer\",\n    \"Runtime/Render\",\n    false, \n    {\"Core\", \"RHI\", \"ShaderCompiler\", \"RenderGraph\", \"Scene\", \"Geometry\", \"Resource\", \"Material\"}, \n    {}\n)\n"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Importer.cpp",
    "content": "#include \"Importer.hpp\"\n#include \"Resource/Prefab.hpp\"\n#include \"Resource/Texture2D.hpp\"\n#include \"Resource/Animation.hpp\"\n\n#include <Core/Plugin.hpp>\n\nnamespace Ilum\n{\nconst std::map<ResourceType, std::map<std::string, std::string>> PluginMap = {\n    {ResourceType::Texture2D,\n     {\n         {\".png\", \"STB\"},\n         {\".jpg\", \"STB\"},\n         {\".jpeg\", \"STB\"},\n         {\".bmp\", \"STB\"},\n         {\".dds\", \"DDS\"},\n     }},\n    {ResourceType::TextureCube,\n     {\n         {\".hdr\", \"STB\"},\n     }},\n    {ResourceType::Prefab,\n     {\n         {\".obj\", \"Assimp\"},\n         {\".gltf\", \"Assimp\"},\n         {\".glb\", \"Assimp\"},\n         {\".dae\", \"Assimp\"},\n         {\".fbx\", \"Assimp\"},\n         {\".ply\", \"Assimp\"},\n         {\".blend\", \"Assimp\"},\n     }},\n};\n\ntemplate <ResourceType Type>\nstd::unique_ptr<Importer<Type>> &Importer<Type>::GetInstance(const std::string &plugin)\n{\n\tstatic std::unique_ptr<Importer<Type>> importer = std::unique_ptr<Importer<Type>>(PluginManager::GetInstance().Call<Importer<Type> *>(fmt::format(\"shared/Importer/Importer.{}.dll\", plugin), \"Create\"));\n\treturn importer;\n}\n\ntemplate <ResourceType Type>\nvoid Importer<Type>::Import(ResourceManager *manager, const std::string &path, RHIContext *rhi_context)\n{\n\treturn GetInstance(PluginMap.at(Type).at(Path::GetInstance().GetFileExtension(path)))->Import_(manager, path, rhi_context);\n}\n\ntemplate class Importer<ResourceType::Prefab>;\ntemplate class Importer<ResourceType::Texture2D>;\ntemplate class Importer<ResourceType::TextureCube>;\ntemplate class Importer<ResourceType::Mesh>;\ntemplate class Importer<ResourceType::SkinnedMesh>;\ntemplate class Importer<ResourceType::Material>;\ntemplate class Importer<ResourceType::Animation>;\ntemplate class Importer<ResourceType::RenderPipeline>;\ntemplate class Importer<ResourceType::Scene>;\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/Animation.cpp",
    "content": "#include \"Resource/Animation.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::Animation>::Impl\n{\n\tstd::vector<Bone> bones;\n\n\tstd::unique_ptr<RHITexture> skinned_matrics = nullptr;\n\tstd::unique_ptr<RHIBuffer>  bone_matrics    = nullptr;\n\n\tHierarchyNode hierarchy;\n\n\tfloat m_max_timestamp = 0.f;\n\n\tuint32_t m_bone_count = 0;\n\n\tuint32_t frame_count = 0;\n};\n\nBone::Bone(\n    const std::string         &name,\n    uint32_t                   id,\n    glm::mat4                  offset,\n    std::vector<KeyPosition> &&positions,\n    std::vector<KeyRotation> &&rotations,\n    std::vector<KeyScale>    &&scales)\n{\n\tm_name            = name;\n\tm_id              = id;\n\tm_offset          = offset;\n\tm_positions       = std::move(positions);\n\tm_rotations       = std::move(rotations);\n\tm_scales          = std::move(scales);\n\tm_local_transfrom = glm::mat4(1.f);\n\n\tif (!m_positions.empty())\n\t{\n\t\tm_max_timestamp = glm::max(m_max_timestamp, m_positions.back().time_stamp);\n\t}\n\n\tif (!m_rotations.empty())\n\t{\n\t\tm_max_timestamp = glm::max(m_max_timestamp, m_rotations.back().time_stamp);\n\t}\n\n\tif (!m_scales.empty())\n\t{\n\t\tm_max_timestamp = glm::max(m_max_timestamp, m_scales.back().time_stamp);\n\t}\n}\n\nvoid Bone::Update(float time)\n{\n\tm_local_transfrom =\n\t    InterpolatePosition(time) *\n\t    InterpolateRotation(time) *\n\t    InterpolateScaling(time);\n}\n\nglm::mat4 Bone::GetLocalTransform() const\n{\n\treturn m_local_transfrom;\n}\n\nstd::string Bone::GetBoneName() const\n{\n\treturn m_name;\n}\n\nuint32_t Bone::GetBoneID() const\n{\n\treturn m_id;\n}\n\nglm::mat4 Bone::GetBoneOffset() const\n{\n\treturn m_offset;\n}\n\nsize_t Bone::GetPositionIndex(float time) const\n{\n\tfor (size_t index = 0; index < m_positions.size() - 1; index++)\n\t{\n\t\tif (time < m_positions[index + 1].time_stamp)\n\t\t{\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn m_positions.size() - 2;\n}\n\nsize_t Bone::GetRotationIndex(float time) const\n{\n\tfor (size_t index = 0; index < m_rotations.size() - 1; index++)\n\t{\n\t\tif (time < m_rotations[index + 1].time_stamp)\n\t\t{\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn m_rotations.size() - 2;\n}\n\nsize_t Bone::GetScaleIndex(float time) const\n{\n\tfor (size_t index = 0; index < m_scales.size() - 1; index++)\n\t{\n\t\tif (time < m_scales[index + 1].time_stamp)\n\t\t{\n\t\t\treturn index;\n\t\t}\n\t}\n\treturn m_scales.size() - 2;\n}\n\nglm::mat4 Bone::GetLocalTransform(float time) const\n{\n\tglm::mat4 translation = InterpolatePosition(time);\n\tglm::mat4 rotation    = InterpolateRotation(time);\n\tglm::mat4 scale       = InterpolateScaling(time);\n\treturn translation * rotation * scale;\n}\n\nglm::mat4 Bone::GetTransformedOffset(float time) const\n{\n\treturn GetLocalTransform() * m_offset;\n}\n\nfloat Bone::GetMaxTimeStamp() const\n{\n\treturn m_max_timestamp;\n}\n\nfloat Bone::GetScaleFactor(float last, float next, float time) const\n{\n\treturn (time - last) / (next - last);\n}\n\nglm::mat4 Bone::InterpolatePosition(float time) const\n{\n\tif (m_positions.empty())\n\t{\n\t\treturn glm::mat4(1.f);\n\t}\n\n\tif (m_positions.size() == 1)\n\t{\n\t\treturn glm::translate(glm::mat4(1.f), m_positions[0].position);\n\t}\n\n\tsize_t    p0             = GetPositionIndex(time);\n\tsize_t    p1             = p0 + 1;\n\tfloat     scale_factor   = GetScaleFactor(m_positions[p0].time_stamp, m_positions[p1].time_stamp, glm::clamp(time, 0.f, m_positions.back().time_stamp));\n\tglm::vec3 final_position = glm::mix(m_positions[p0].position, m_positions[p1].position, scale_factor);\n\n\treturn glm::translate(glm::mat4(1.f), final_position);\n}\n\nglm::mat4 Bone::InterpolateRotation(float time) const\n{\n\tif (m_rotations.empty())\n\t{\n\t\treturn glm::mat4(1.f);\n\t}\n\n\tif (m_rotations.size() == 1)\n\t{\n\t\tauto rotation = glm::normalize(m_rotations[0].orientation);\n\t\treturn glm::toMat4(rotation);\n\t}\n\n\tsize_t    p0             = GetRotationIndex(time);\n\tsize_t    p1             = p0 + 1;\n\tfloat     scale_factor   = GetScaleFactor(m_rotations[p0].time_stamp, m_rotations[p1].time_stamp, glm::clamp(time, 0.f, m_rotations.back().time_stamp));\n\tglm::quat final_rotation = glm::slerp(m_rotations[p0].orientation, m_rotations[p1].orientation, scale_factor);\n\tfinal_rotation           = glm::normalize(final_rotation);\n\n\treturn glm::toMat4(final_rotation);\n}\n\nglm::mat4 Bone::InterpolateScaling(float time) const\n{\n\tif (m_scales.empty())\n\t{\n\t\treturn glm::mat4(1.f);\n\t}\n\n\tif (m_scales.size() == 1)\n\t{\n\t\treturn glm::scale(glm::mat4(1.f), m_scales[0].scale);\n\t}\n\n\tsize_t    p0           = GetScaleIndex(time);\n\tsize_t    p1           = p0 + 1;\n\tfloat     scale_factor = GetScaleFactor(m_scales[p0].time_stamp, m_scales[p1].time_stamp, glm::clamp(time, 0.f, m_scales.back().time_stamp));\n\tglm::vec3 final_scale  = glm::mix(m_scales[p0].scale, m_scales[p1].scale, scale_factor);\n\n\treturn glm::scale(glm::mat4(1.f), final_scale);\n}\n\nResource<ResourceType::Animation>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::Animation)\n{\n}\n\nResource<ResourceType::Animation>::Resource(RHIContext *rhi_context, const std::string &name, std::vector<Bone> &&bones, HierarchyNode &&hierarchy) :\n    IResource(name)\n{\n\tm_impl = new Impl;\n\n\tm_impl->bones     = std::move(bones);\n\tm_impl->hierarchy = std::move(hierarchy);\n\n\tfor (auto &bone : m_impl->bones)\n\t{\n\t\tm_impl->m_max_timestamp = glm::max(m_impl->m_max_timestamp, bone.GetMaxTimeStamp());\n\t}\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(\"Asset/BuildIn/animation.icon.asset\", thumbnail_data);\n\tUpdateThumbnail(rhi_context, thumbnail_data);\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Animation), thumbnail_data, m_impl->bones, m_impl->hierarchy, m_impl->m_max_timestamp);\n\n\tBake(rhi_context);\n}\n\nconst std::vector<Bone> &Resource<ResourceType::Animation>::GetBones() const\n{\n\treturn m_impl->bones;\n}\n\nBone *Resource<ResourceType::Animation>::GetBone(const std::string &name)\n{\n\tauto iter = std::find_if(m_impl->bones.begin(), m_impl->bones.end(), [&](const Bone &bone) { return bone.GetBoneName() == name; });\n\treturn iter == m_impl->bones.end() ? nullptr : &(*iter);\n}\n\nuint32_t Resource<ResourceType::Animation>::GetBoneCount() const\n{\n\treturn m_impl->m_bone_count;\n}\n\nuint32_t Resource<ResourceType::Animation>::GetMaxBoneIndex() const\n{\n\tuint32_t idx = 0;\n\tfor (auto &bone : m_impl->bones)\n\t{\n\t\tidx = std::max(idx, bone.GetBoneID());\n\t}\n\treturn idx;\n}\n\nfloat Resource<ResourceType::Animation>::GetMaxTimeStamp() const\n{\n\treturn m_impl->m_max_timestamp;\n}\n\nuint32_t Resource<ResourceType::Animation>::GetFrameCount() const\n{\n\treturn static_cast<uint32_t>(m_impl->m_max_timestamp * 30.f);\n}\n\nconst HierarchyNode &Resource<ResourceType::Animation>::GetHierarchyNode() const\n{\n\treturn m_impl->hierarchy;\n}\n\nvoid Resource<ResourceType::Animation>::Bake(RHIContext *rhi_context)\n{\n\tstd::function<void(const HierarchyNode &, float time, std::vector<glm::mat4> &, glm::mat4, bool)> calculate_bone_transform = [&](const HierarchyNode &node, float time, std::vector<glm::mat4> &skinned_matrics, glm::mat4 parent, bool outside) {\n\t\tBone *bone = GetBone(node.name);\n\n\t\tglm::mat4 global_transformation = outside ? glm::mat4(1.f) : parent * node.transform;\n\n\t\tif (bone)\n\t\t{\n\t\t\tglobal_transformation    = parent * bone->GetLocalTransform(time);\n\t\t\tuint32_t  bone_id        = bone->GetBoneID();\n\t\t\tglm::mat4 offset         = bone->GetBoneOffset();\n\t\t\tskinned_matrics[bone_id] = global_transformation * offset;\n\n\t\t\toutside = false;\n\t\t}\n\n\t\tfor (auto &child : node.children)\n\t\t{\n\t\t\tcalculate_bone_transform(child, time, skinned_matrics, global_transformation, outside);\n\t\t}\n\t};\n\n\tm_impl->m_bone_count = 0;\n\tfor (auto &bone : m_impl->bones)\n\t{\n\t\tm_impl->m_bone_count = glm::max(m_impl->m_bone_count, bone.GetBoneID());\n\t}\n\tm_impl->m_bone_count++;\n\n\t// Bone matrics\n\tm_impl->bone_matrics = rhi_context->CreateBuffer(sizeof(glm::mat4) * m_impl->m_bone_count, RHIBufferUsage::ConstantBuffer | RHIBufferUsage::UnorderedAccess, RHIMemoryUsage::CPU_TO_GPU);\n\n\t// Skinned Matrics\n\t// X - bone id\n\t// Y - frame transform float4x3\n\tsize_t frame_count      = static_cast<size_t>(m_impl->m_max_timestamp * 30.f);\n\tm_impl->skinned_matrics = rhi_context->CreateTexture2D((uint32_t) m_impl->m_bone_count * 3, (uint32_t) frame_count, RHIFormat::R32G32B32A32_FLOAT, RHITextureUsage::Transfer | RHITextureUsage::ShaderResource, false);\n\n\tstd::vector<float> skinned_matrics(frame_count * 4ull * 3ull * m_impl->m_bone_count);\n\n\tfor (size_t i = 0; i < frame_count; i++)\n\t{\n\t\tfloat time = static_cast<float>(i) / 30.f;\n\n\t\tstd::vector<glm::mat4> frame_skinned_matrics(m_impl->m_bone_count);\n\t\tcalculate_bone_transform(m_impl->hierarchy, time, frame_skinned_matrics, glm::mat4(1.f), true);\n\n\t\tif (i == 0)\n\t\t{\n\t\t\tm_impl->bone_matrics->CopyToDevice(frame_skinned_matrics.data(), frame_skinned_matrics.size() * sizeof(glm::mat4));\n\t\t}\n\n\t\tsize_t offset = 4ull * 3ull * m_impl->m_bone_count * i;\n\n\t\tfor (size_t j = 0; j < m_impl->m_bone_count; j++)\n\t\t{\n\t\t\tglm::mat4 transform = glm::transpose(frame_skinned_matrics[j]);\n\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j]      = transform[0][0];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 1]  = transform[0][1];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 2]  = transform[0][2];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 3]  = transform[0][3];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 4]  = transform[1][0];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 5]  = transform[1][1];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 6]  = transform[1][2];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 7]  = transform[1][3];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 8]  = transform[2][0];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 9]  = transform[2][1];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 10] = transform[2][2];\n\t\t\tskinned_matrics[offset + 4ull * 3ull * j + 11] = transform[2][3];\n\t\t}\n\t}\n\n\t{\n\t\tauto staging_buffer = rhi_context->CreateBuffer(skinned_matrics.size() * sizeof(float), RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\t\tstaging_buffer->CopyToDevice(skinned_matrics.data(), skinned_matrics.size() * sizeof(float));\n\t\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\t\tcmd_buffer->Begin();\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_impl->skinned_matrics.get(), RHIResourceState::Undefined, RHIResourceState::TransferDest}}, {});\n\t\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), m_impl->skinned_matrics.get(), 0, 0, 1);\n\t\tcmd_buffer->ResourceStateTransition({TextureStateTransition{m_impl->skinned_matrics.get(), RHIResourceState::TransferDest, RHIResourceState::ShaderResource}}, {});\n\t\tcmd_buffer->End();\n\t\trhi_context->Execute(cmd_buffer);\n\t}\n}\n\nRHITexture *Resource<ResourceType::Animation>::GetSkinnedMatrics() const\n{\n\treturn m_impl->skinned_matrics.get();\n}\n\nRHIBuffer *Resource<ResourceType::Animation>::GetBoneMatrics() const\n{\n\treturn m_impl->bone_matrics.get();\n}\n\nResource<ResourceType::Animation>::~Resource()\n{\n\tdelete m_impl;\n}\n\nbool Resource<ResourceType::Animation>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::Animation>::Load(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Animation), thumbnail_data, m_impl->bones, m_impl->hierarchy, m_impl->m_max_timestamp);\n\n\tBake(rhi_context);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/Material.cpp",
    "content": "#include \"Resource/Material.hpp\"\n#include \"Resource/Mesh.hpp\"\n#include \"Resource/Texture2D.hpp\"\n#include \"ResourceManager.hpp\"\n\n#include <Material/MaterialCompiler.hpp>\n#include <Material/MaterialData.hpp>\n#include <ShaderCompiler/ShaderCompiler.hpp>\n\n#include <mustache.hpp>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::Material>::Impl\n{\n\tMaterialGraphDesc desc;\n\n\tMaterialCompilationContext context;\n\n\tstd::string layout;\n\n\tMaterialData data;\n\n\tbool valid = false;\n\n\tbool dirty = false;\n};\n\nResource<ResourceType::Material>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::Material)\n{\n}\n\nResource<ResourceType::Material>::Resource(RHIContext *rhi_context, const std::string &name, MaterialGraphDesc &&desc) :\n    IResource(name)\n{\n\tm_impl = new Impl;\n\n\tm_impl->desc = std::move(desc);\n\n\tstd::vector<uint8_t> thumbnail_data;\n\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Material), thumbnail_data, m_impl->desc, m_impl->layout, m_impl->context, m_impl->data);\n\n\tm_impl->dirty = true;\n\tm_impl->valid = false;\n}\n\nResource<ResourceType::Material>::~Resource()\n{\n\tdelete m_impl;\n}\n\nbool Resource<ResourceType::Material>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::Material>::Load(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Material), thumbnail_data, m_impl->desc, m_impl->layout, m_impl->context, m_impl->data);\n\n\tm_impl->valid = Path::GetInstance().IsExist(fmt::format(\"Asset/Material/{}\", m_impl->data.shader));\n}\n\nvoid Resource<ResourceType::Material>::Compile(RHIContext *rhi_context, ResourceManager *manager, RHITexture *dummy_texture, const std::string &layout)\n{\n\tif (!layout.empty())\n\t{\n\t\tm_impl->layout = layout;\n\t}\n\n\tm_impl->valid = false;\n\n\tm_impl->context.Reset();\n\tm_impl->data.Reset();\n\n\tfor (auto &[node_handle, node] : m_impl->desc.GetNodes())\n\t{\n\t\tnode.EmitHLSL(m_impl->desc, manager, &m_impl->context);\n\t}\n\n\tif (!m_impl->context.output.bsdf.empty())\n\t{\n\t\tstd::vector<uint8_t> shader_data;\n\t\tPath::GetInstance().Read(\"Source/Shaders/Material.hlsli\", shader_data);\n\t\tstd::string shader(shader_data.begin(), shader_data.end());\n\n\t\tkainjow::mustache::mustache mustache = {shader};\n\t\tkainjow::mustache::data     mustache_data{kainjow::mustache::data::type::object};\n\n\t\t{\n\t\t\tkainjow::mustache::data headers{kainjow::mustache::data::type::list};\n\t\t\tkainjow::mustache::data initializations{kainjow::mustache::data::type::list};\n\t\t\tkainjow::mustache::data textures{kainjow::mustache::data::type::list};\n\t\t\tkainjow::mustache::data samplers{kainjow::mustache::data::type::list};\n\t\t\tfor (auto &variable : m_impl->context.variables)\n\t\t\t{\n\t\t\t\tinitializations << kainjow::mustache::data{\"Initialization\", variable};\n\t\t\t}\n\t\t\tfor (auto &[texture, texture_name] : m_impl->context.textures)\n\t\t\t{\n\t\t\t\ttextures << kainjow::mustache::data{\"Texture\", texture};\n\t\t\t}\n\t\t\tfor (auto &[sampler, desc] : m_impl->context.samplers)\n\t\t\t{\n\t\t\t\tsamplers << kainjow::mustache::data{\"Sampler\", sampler};\n\t\t\t}\n\t\t\tstd::unordered_set<std::string> bsdf_types;\n\t\t\tfor (auto &bsdf : m_impl->context.bsdfs)\n\t\t\t{\n\t\t\t\tif (bsdf.name != m_impl->context.output.bsdf)\n\t\t\t\t{\n\t\t\t\t\tinitializations << kainjow::mustache::data{\"Initialization\", fmt::format(\"{} {};\", bsdf.type, bsdf.name)};\n\t\t\t\t\tinitializations << kainjow::mustache::data{\"Initialization\", fmt::format(\"{}\", bsdf.initialization)};\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tmustache_data.set(\"BxDFType\", bsdf.type);\n\t\t\t\t\tmustache_data.set(\"BxDFName\", bsdf.name);\n\t\t\t\t}\n\t\t\t\tbsdf_types.insert(bsdf.type.substr(0, std::min(bsdf.type.find_first_of('<'), bsdf.type.find_first_of(' '))));\n\t\t\t}\n\t\t\tinitializations << kainjow::mustache::data{\"Initialization\", m_impl->context.bsdfs.back().initialization};\n\n\t\t\tfor (auto &bsdf_type : bsdf_types)\n\t\t\t{\n\t\t\t\theaders << kainjow::mustache::data{\"MaterialHeader\", fmt::format(\"#include \\\"Material/Material/{}.hlsli\\\"\", bsdf_type)};\n\t\t\t}\n\n\t\t\tmustache_data.set(\"MaterialHeaders\", headers);\n\t\t\tmustache_data.set(\"Initializations\", initializations);\n\t\t\tmustache_data.set(\"Textures\", textures);\n\t\t\tmustache_data.set(\"Samplers\", samplers);\n\t\t}\n\n\t\tshader = mustache.render(mustache_data);\n\t\tshader = std::string(shader.c_str());\n\n\t\tm_impl->data.signature = fmt::format(\"Signature_{}\", Hash(shader));\n\n\t\tshader_data.resize(shader.length());\n\t\tstd::memcpy(shader_data.data(), shader.data(), shader_data.size());\n\n\t\tm_impl->data.shader = fmt::format(\"{}.material.hlsli\", m_impl->desc.GetName());\n\n\t\tPath::GetInstance().Save(fmt::format(\"Asset/Material/{}\", m_impl->data.shader), shader_data);\n\t}\n\n\tm_impl->valid = true;\n\tm_impl->dirty = true;\n\n\tUpdate(rhi_context, manager, dummy_texture);\n}\n\nvoid Resource<ResourceType::Material>::Update(RHIContext *rhi_context, ResourceManager *manager, RHITexture *dummy_texture)\n{\n\tif (!m_impl->valid)\n\t{\n\t\tCompile(rhi_context, manager, dummy_texture);\n\t}\n\telse\n\t{\n\t\tmanager->SetDirty<ResourceType::Material>();\n\n\t\tm_impl->data.textures.clear();\n\t\tfor (auto &[texture, texture_name] : m_impl->context.textures)\n\t\t{\n\t\t\tm_impl->data.textures.push_back(static_cast<uint32_t>(manager->Index<ResourceType::Texture2D>(texture_name)));\n\t\t}\n\n\t\tm_impl->data.samplers.clear();\n\t\tfor (auto &[sampler, desc] : m_impl->context.samplers)\n\t\t{\n\t\t\tm_impl->data.samplers.push_back(rhi_context->GetSamplerIndex(desc));\n\t\t}\n\t}\n}\n\nvoid Resource<ResourceType::Material>::PostUpdate(RHIContext *rhi_context, uint32_t material_id, const std::vector<RHITexture *> &scene_texture_2d, const std::vector<RHISampler *> &samplers, RHIBuffer *material_buffers, RHIBuffer *material_offsets)\n{\n\tif (m_impl->dirty)\n\t{\n\t\tstd::vector<uint8_t> thumbnail_data = RenderPreview(rhi_context, material_id, scene_texture_2d, samplers, material_buffers, material_offsets);\n\t\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Material), thumbnail_data, m_impl->desc, m_impl->layout, m_impl->context, m_impl->data);\n\t\tm_impl->dirty = false;\n\t}\n}\n\nconst MaterialData &Resource<ResourceType::Material>::GetMaterialData() const\n{\n\treturn m_impl->data;\n}\n\nconst MaterialCompilationContext &Resource<ResourceType::Material>::GetCompilationContext() const\n{\n\treturn m_impl->context;\n}\n\nconst std::string &Resource<ResourceType::Material>::GetLayout() const\n{\n\treturn m_impl->layout;\n}\n\nMaterialGraphDesc &Resource<ResourceType::Material>::GetDesc()\n{\n\treturn m_impl->desc;\n}\n\nbool Resource<ResourceType::Material>::IsValid() const\n{\n\treturn m_impl->valid;\n}\n\nstd::vector<uint8_t> Resource<ResourceType::Material>::RenderPreview(RHIContext *rhi_context, uint32_t material_id, const std::vector<RHITexture *> &scene_texture_2d, const std::vector<RHISampler *> &samplers, RHIBuffer *material_buffers, RHIBuffer *material_offsets)\n{\n\tstd::vector<Resource<ResourceType::Mesh>::Vertex> vertices;\n\n\tstd::vector<uint32_t> indices;\n\n\tDESERIALIZE(\"Asset/BuildIn/MaterialBall.asset\", vertices, indices);\n\n\tauto vertex_buffer = rhi_context->CreateBuffer<Resource<ResourceType::Mesh>::Vertex>(vertices.size(), RHIBufferUsage::Vertex, RHIMemoryUsage::CPU_TO_GPU);\n\tauto index_buffer  = rhi_context->CreateBuffer<uint32_t>(indices.size(), RHIBufferUsage::Index, RHIMemoryUsage::CPU_TO_GPU);\n\n\tvertex_buffer->CopyToDevice(vertices.data(), vertices.size() * sizeof(Resource<ResourceType::Mesh>::Vertex));\n\tindex_buffer->CopyToDevice(indices.data(), indices.size() * sizeof(uint32_t));\n\n\tstd::vector<uint8_t> raw_shader;\n\tPath::GetInstance().Read(\"./Source/Shaders/Editor/Preview/Material.hlsl\", raw_shader);\n\n\tstd::string shader_source;\n\tshader_source.resize(raw_shader.size());\n\tstd::memcpy(shader_source.data(), raw_shader.data(), raw_shader.size());\n\tshader_source += \"\\n\";\n\n\tShaderDesc vertex_shader_desc  = {};\n\tvertex_shader_desc.path        = \"./Source/Shaders/Editor/Preview/Material.hlsl\";\n\tvertex_shader_desc.entry_point = \"VSmain\";\n\tvertex_shader_desc.stage       = RHIShaderStage::Vertex;\n\tvertex_shader_desc.source      = ShaderSource::HLSL;\n\tvertex_shader_desc.target      = ShaderTarget::SPIRV;\n\tvertex_shader_desc.code        = fmt::format(\"#include \\\"{}\\\"\\n\", m_impl->data.shader) + shader_source;\n\tvertex_shader_desc.macros      = {\"USE_MATERIAL\", m_impl->data.signature, \"MATERIAL_ID = \" + std::to_string(material_id)};\n\n\tShaderDesc fragment_shader_desc  = {};\n\tfragment_shader_desc.path        = \"./Source/Shaders/Editor/Preview/Material.hlsl\";\n\tfragment_shader_desc.entry_point = \"PSmain\";\n\tfragment_shader_desc.stage       = RHIShaderStage::Fragment;\n\tfragment_shader_desc.source      = ShaderSource::HLSL;\n\tfragment_shader_desc.target      = ShaderTarget::SPIRV;\n\tfragment_shader_desc.code        = fmt::format(\"#include \\\"{}\\\"\\n\", m_impl->data.shader) + shader_source;\n\tfragment_shader_desc.macros      = {\"USE_MATERIAL\", m_impl->data.signature, \"MATERIAL_ID = \" + std::to_string(material_id)};\n\n\tShaderMeta vertex_meta   = {};\n\tShaderMeta fragment_meta = {};\n\n\tauto vertex_shader_spirv   = ShaderCompiler::GetInstance().Compile(vertex_shader_desc, vertex_meta);\n\tauto fragment_shader_spirv = ShaderCompiler::GetInstance().Compile(fragment_shader_desc, fragment_meta);\n\n\tauto vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\tauto fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\tShaderMeta shader_meta = vertex_meta;\n\tshader_meta += fragment_meta;\n\n\tBlendState blend_state = {};\n\tblend_state.attachment_states.resize(1);\n\n\tDepthStencilState depth_stencil_state  = {};\n\tdepth_stencil_state.depth_test_enable  = true;\n\tdepth_stencil_state.depth_write_enable = true;\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\n\tif (!m_thumbnail)\n\t{\n\t\tm_thumbnail = rhi_context->CreateTexture2D(128, 128, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer | RHITextureUsage::RenderTarget, false);\n\t\tcmd_buffer->ResourceStateTransition({\n\t\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::Undefined, RHIResourceState::RenderTarget},\n\t\t                                    },\n\t\t                                    {});\n\t}\n\telse\n\t{\n\t\tcmd_buffer->ResourceStateTransition({\n\t\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::ShaderResource, RHIResourceState::RenderTarget},\n\t\t                                    },\n\t\t                                    {});\n\t}\n\n\tauto depth_buffer   = rhi_context->CreateTexture2D(128, 128, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget, false);\n\tauto uniform_buffer = rhi_context->CreateBuffer<glm::mat4>(2, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\tauto staging_buffer = rhi_context->CreateBuffer(128ull * 128ull * 4ull * sizeof(uint8_t), RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_TO_CPU);\n\tauto render_target  = rhi_context->CreateRenderTarget();\n\tauto pipeline_state = rhi_context->CreatePipelineState();\n\n\tpipeline_state->SetBlendState(blend_state);\n\tpipeline_state->SetDepthStencilState(depth_stencil_state);\n\tpipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader.get());\n\tpipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader.get());\n\tpipeline_state->SetVertexInputState(VertexInputState{\n\t    {\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, position)},\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Normal, 1, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, normal)},\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Tangent, 2, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, tangent)},\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Texcoord, 3, 0, RHIFormat::R32G32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, texcoord0)},\n\t    },\n\t    {\n\t        VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::Mesh>::Vertex), RHIVertexInputRate::Vertex},\n\t    }});\n\n\t{\n\t\tglm::vec3 center = glm::vec3(0.f);\n\n\t\tfloat radius = 4.f;\n\t\tfloat theta  = 0.f;\n\t\tfloat phi    = 60.f;\n\n\t\tglm::vec3 position  = center + radius * glm::vec3(glm::sin(glm::radians(phi)) * glm::sin(glm::radians(theta)), glm::cos(glm::radians(phi)), glm::sin(glm::radians(phi)) * glm::cos(glm::radians(theta)));\n\t\tglm::vec3 direction = glm::normalize(center - position);\n\t\tglm::vec3 right     = glm::normalize(glm::cross(direction, glm::vec3{0.f, 1.f, 0.f}));\n\t\tglm::vec3 up        = glm::normalize(glm::cross(right, direction));\n\t\tglm::mat4 transform = glm::perspective(glm::radians(45.f), 1.f, 0.01f, 1000.f) * glm::lookAt(position, center, up);\n\t\tglm::mat4 model     = glm::mat4_cast(glm::qua<float>(glm::radians(glm::vec3(135.f, 0.f, 180.f))));\n\n\t\tuniform_buffer->CopyToDevice(glm::value_ptr(transform), sizeof(transform));\n\t\tuniform_buffer->CopyToDevice(glm::value_ptr(model), sizeof(model), sizeof(glm::mat4));\n\t}\n\n\tauto descriptor = rhi_context->CreateDescriptor(shader_meta);\n\tdescriptor->BindBuffer(\"UniformBuffer\", uniform_buffer.get())\n\t    .BindTexture(\"Textures\", scene_texture_2d, RHITextureDimension::Texture2D)\n\t    .BindSampler(\"Samplers\", samplers)\n\t    .BindBuffer(\"MaterialOffsets\", material_offsets)\n\t    .BindBuffer(\"MaterialBuffer\", material_buffers);\n\n\trender_target->Set(0, m_thumbnail.get(), TextureRange{}, ColorAttachment{RHILoadAction::Clear, RHIStoreAction::Store, {0.1f, 0.1f, 0.1f, 1.f}});\n\trender_target->Set(depth_buffer.get(), TextureRange{}, DepthStencilAttachment{});\n\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{depth_buffer.get(), RHIResourceState::Undefined, RHIResourceState::DepthWrite},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->BeginRenderPass(render_target.get());\n\tcmd_buffer->SetViewport(128, 128);\n\tcmd_buffer->SetScissor(128, 128);\n\tcmd_buffer->BindDescriptor(descriptor);\n\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\tcmd_buffer->BindVertexBuffer(0, vertex_buffer.get());\n\tcmd_buffer->BindIndexBuffer(index_buffer.get());\n\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(indices.size()));\n\tcmd_buffer->EndRenderPass();\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::RenderTarget, RHIResourceState::TransferSource},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->CopyTextureToBuffer(m_thumbnail.get(), staging_buffer.get(), 0, 0, 1);\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::TransferSource, RHIResourceState::ShaderResource},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->End();\n\trhi_context->Execute(cmd_buffer);\n\n\tstd::vector<uint8_t> staging_data(staging_buffer->GetDesc().size);\n\tstaging_buffer->CopyToHost(staging_data.data(), staging_buffer->GetDesc().size);\n\n\treturn staging_data;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/Mesh.cpp",
    "content": "#include \"Resource/Mesh.hpp\"\n\n#include <RHI/RHIContext.hpp>\n#include <ShaderCompiler/ShaderCompiler.hpp>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::Mesh>::Impl\n{\n\tsize_t vertex_count  = 0;\n\tsize_t index_count   = 0;\n\tsize_t meshlet_count = 0;\n\n\tstd::unique_ptr<RHIBuffer> vertex_buffer       = nullptr;\n\tstd::unique_ptr<RHIBuffer> index_buffer        = nullptr;\n\tstd::unique_ptr<RHIBuffer> meshlet_data_buffer = nullptr;\n\tstd::unique_ptr<RHIBuffer> meshlet_buffer      = nullptr;\n\n\tstd::unique_ptr<RHIAccelerationStructure> blas = nullptr;\n};\n\nResource<ResourceType::Mesh>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::Mesh)\n{\n}\n\nResource<ResourceType::Mesh>::Resource(RHIContext *rhi_context, const std::string &name, std::vector<Vertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshlet_data) :\n    IResource(name)\n{\n\tm_impl = new Impl;\n\tUpdate(rhi_context, std::move(vertices), std::move(indices), std::move(meshlets), std::move(meshlet_data));\n}\n\nResource<ResourceType::Mesh>::~Resource()\n{\n\tdelete m_impl;\n}\n\nbool Resource<ResourceType::Mesh>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::Mesh>::Load(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\n\tstd::vector<uint8_t>  thumbnail_data;\n\tstd::vector<Vertex>   vertices;\n\tstd::vector<uint32_t> indices;\n\tstd::vector<Meshlet>  meshlets;\n\tstd::vector<uint32_t> meshlet_data;\n\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Mesh), thumbnail_data, vertices, indices, meshlets, meshlet_data);\n\n\tUpdate(rhi_context, std::move(vertices), std::move(indices), std::move(meshlets), std::move(meshlet_data));\n}\n\nRHIBuffer *Resource<ResourceType::Mesh>::GetVertexBuffer() const\n{\n\treturn m_impl->vertex_buffer.get();\n}\n\nRHIBuffer *Resource<ResourceType::Mesh>::GetIndexBuffer() const\n{\n\treturn m_impl->index_buffer.get();\n}\n\nRHIBuffer *Resource<ResourceType::Mesh>::GetMeshletDataBuffer() const\n{\n\treturn m_impl->meshlet_data_buffer.get();\n}\n\nRHIBuffer *Resource<ResourceType::Mesh>::GetMeshletBuffer() const\n{\n\treturn m_impl->meshlet_buffer.get();\n}\n\nRHIAccelerationStructure *Resource<ResourceType::Mesh>::GetBLAS() const\n{\n\treturn m_impl->blas.get();\n}\n\nsize_t Resource<ResourceType::Mesh>::GetVertexCount() const\n{\n\treturn m_impl->vertex_count;\n}\n\nsize_t Resource<ResourceType::Mesh>::GetIndexCount() const\n{\n\treturn m_impl->index_count;\n}\n\nsize_t Resource<ResourceType::Mesh>::GetMeshletCount() const\n{\n\treturn m_impl->meshlet_count;\n}\n\nvoid Resource<ResourceType::Mesh>::Update(RHIContext *rhi_context, std::vector<Vertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshlet_data)\n{\n\tm_impl->vertex_count  = vertices.size();\n\tm_impl->index_count   = indices.size();\n\tm_impl->meshlet_count = meshlets.size();\n\n\tm_impl->vertex_buffer       = rhi_context->CreateBuffer<Vertex>(vertices.size(), RHIBufferUsage::Vertex | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\tm_impl->index_buffer        = rhi_context->CreateBuffer<uint32_t>(indices.size(), RHIBufferUsage::Index | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\tm_impl->meshlet_data_buffer = rhi_context->CreateBuffer<uint32_t>(meshlet_data.size(), RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\tm_impl->meshlet_buffer      = rhi_context->CreateBuffer<Meshlet>(meshlets.size(), RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\n\tm_impl->vertex_buffer->CopyToDevice(vertices.data(), vertices.size() * sizeof(Vertex));\n\tm_impl->index_buffer->CopyToDevice(indices.data(), indices.size() * sizeof(uint32_t));\n\tm_impl->meshlet_data_buffer->CopyToDevice(meshlet_data.data(), meshlet_data.size() * sizeof(uint32_t));\n\tm_impl->meshlet_buffer->CopyToDevice(meshlets.data(), meshlets.size() * sizeof(Meshlet));\n\n\tm_impl->blas = rhi_context->CreateAcccelerationStructure();\n\n\tBLASDesc desc        = {};\n\tdesc.name            = m_name;\n\tdesc.vertex_buffer   = m_impl->vertex_buffer.get();\n\tdesc.index_buffer    = m_impl->index_buffer.get();\n\tdesc.vertices_count  = static_cast<uint32_t>(vertices.size());\n\tdesc.vertices_offset = 0;\n\tdesc.indices_count   = static_cast<uint32_t>(indices.size());\n\tdesc.indices_offset  = 0;\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Compute);\n\tcmd_buffer->Begin();\n\tm_impl->blas->Update(cmd_buffer, desc);\n\tcmd_buffer->End();\n\trhi_context->Execute(cmd_buffer);\n\n\tglm::vec3 min_bound = glm::vec3(std::numeric_limits<float>::max());\n\tglm::vec3 max_bound = glm::vec3(-std::numeric_limits<float>::max());\n\tfor (const auto &v : vertices)\n\t{\n\t\tmin_bound = glm::min(min_bound, v.position);\n\t\tmax_bound = glm::max(max_bound, v.position);\n\t}\n\n\tglm::vec3 center = (max_bound + min_bound) * 0.5f;\n\tfloat     radius = glm::length(max_bound - min_bound);\n\n\tstd::vector<uint8_t> thumbnail_data = RenderPreview(rhi_context, center, radius);\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Mesh), thumbnail_data, vertices, indices, meshlets, meshlet_data);\n}\n\nstd::vector<uint8_t> Resource<ResourceType::Mesh>::RenderPreview(RHIContext *rhi_context, const glm::vec3 &center, float radius)\n{\n\t/*{\n\t    std::vector<uint8_t> raw_shader;\n\t    Path::GetInstance().Read(\"./Source/Shaders/Preview/Editor/Mesh.hlsl\", raw_shader);\n\n\t    std::string shader_source;\n\t    shader_source.resize(raw_shader.size());\n\t    std::memcpy(shader_source.data(), raw_shader.data(), raw_shader.size());\n\t    shader_source += \"\\n\";\n\n\t    ShaderDesc vertex_shader_desc  = {};\n\t    vertex_shader_desc.path = \"./Source/Shaders/Preview/Editor/Mesh.hlsl\";\n\t    vertex_shader_desc.entry_point = \"VSmain\";\n\t    vertex_shader_desc.stage       = RHIShaderStage::Vertex;\n\t    vertex_shader_desc.source      = ShaderSource::HLSL;\n\t    vertex_shader_desc.target      = ShaderTarget::SPIRV;\n\t    vertex_shader_desc.code        = shader_source;\n\n\t    ShaderDesc fragment_shader_desc  = {};\n\t    fragment_shader_desc.path = \"./Source/Shaders/Preview/Editor/Mesh.hlsl\";\n\t    fragment_shader_desc.entry_point = \"PSmain\";\n\t    fragment_shader_desc.stage       = RHIShaderStage::Fragment;\n\t    fragment_shader_desc.source      = ShaderSource::HLSL;\n\t    fragment_shader_desc.target      = ShaderTarget::SPIRV;\n\t    fragment_shader_desc.code        = shader_source;\n\n\t    ShaderMeta vertex_meta   = {};\n\t    ShaderMeta fragment_meta = {};\n\n\t    auto vertex_shader_spirv   = ShaderCompiler::GetInstance().Compile(vertex_shader_desc, vertex_meta);\n\t    auto fragment_shader_spirv = ShaderCompiler::GetInstance().Compile(fragment_shader_desc, fragment_meta);\n\n\t    auto m_vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\t    auto m_fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\t    ShaderMeta shader_meta = vertex_meta;\n\t    shader_meta += fragment_meta;\n\n\t    SERIALIZE(\"Asset/BuildIn/mesh.preview.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\t}*/\n\tbool has_thumbnail = (m_thumbnail != nullptr);\n\tif (!m_thumbnail)\n\t{\n\t\tm_thumbnail = rhi_context->CreateTexture2D(128, 128, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer | RHITextureUsage::RenderTarget, false);\n\t}\n\n\tShaderMeta           shader_meta;\n\tstd::vector<uint8_t> vertex_shader_spirv;\n\tstd::vector<uint8_t> fragment_shader_spirv;\n\tDESERIALIZE(\"Asset/BuildIn/mesh.preview.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\n\tBlendState blend_state = {};\n\tblend_state.attachment_states.resize(1);\n\n\tDepthStencilState depth_stencil_state  = {};\n\tdepth_stencil_state.depth_test_enable  = true;\n\tdepth_stencil_state.depth_write_enable = true;\n\n\tauto depth_buffer    = rhi_context->CreateTexture2D(128, 128, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget, false);\n\tauto uniform_buffer  = rhi_context->CreateBuffer<glm::mat4>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\tauto staging_buffer  = rhi_context->CreateBuffer(128ull * 128ull * 4ull * sizeof(uint8_t), RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_TO_CPU);\n\tauto render_target   = rhi_context->CreateRenderTarget();\n\tauto pipeline_state  = rhi_context->CreatePipelineState();\n\tauto vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\tauto fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\tpipeline_state->SetBlendState(blend_state);\n\tpipeline_state->SetDepthStencilState(depth_stencil_state);\n\tpipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader.get());\n\tpipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader.get());\n\tpipeline_state->SetVertexInputState(VertexInputState{\n\t    {\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, position)},\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Normal, 1, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::Mesh>::Vertex, normal)},\n\t    },\n\t    {\n\t        VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::Mesh>::Vertex), RHIVertexInputRate::Vertex},\n\t    }});\n\n\t{\n\t\tglm::vec3 position  = center + radius * glm::vec3(0.f, 0.f, 1.f);\n\t\tglm::vec3 direction = glm::normalize(center - position);\n\t\tglm::vec3 right     = glm::normalize(glm::cross(direction, glm::vec3{0.f, 1.f, 0.f}));\n\t\tglm::vec3 up        = glm::normalize(glm::cross(right, direction));\n\t\tglm::mat4 transform = glm::perspective(glm::radians(45.f), 1.f, 0.01f, 1000.f) * glm::lookAt(position, center, up);\n\t\tuniform_buffer->CopyToDevice(glm::value_ptr(transform), sizeof(transform));\n\t}\n\n\tauto descriptor = rhi_context->CreateDescriptor(shader_meta);\n\tdescriptor->BindBuffer(\"UniformBuffer\", uniform_buffer.get());\n\n\trender_target->Set(0, m_thumbnail.get(), TextureRange{}, ColorAttachment{RHILoadAction::Clear, RHIStoreAction::Store, {0.1f, 0.1f, 0.1f, 1.f}});\n\trender_target->Set(depth_buffer.get(), TextureRange{}, DepthStencilAttachment{});\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{m_thumbnail.get(), has_thumbnail ? RHIResourceState::ShaderResource : RHIResourceState::Undefined, RHIResourceState::RenderTarget},\n\t                                        TextureStateTransition{depth_buffer.get(), RHIResourceState::Undefined, RHIResourceState::DepthWrite},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->BeginRenderPass(render_target.get());\n\tcmd_buffer->SetViewport(128, 128);\n\tcmd_buffer->SetScissor(128, 128);\n\tcmd_buffer->BindDescriptor(descriptor);\n\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\tcmd_buffer->BindVertexBuffer(0, m_impl->vertex_buffer.get());\n\tcmd_buffer->BindIndexBuffer(m_impl->index_buffer.get());\n\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(m_impl->index_count));\n\tcmd_buffer->EndRenderPass();\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::RenderTarget, RHIResourceState::TransferSource},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->CopyTextureToBuffer(m_thumbnail.get(), staging_buffer.get(), 0, 0, 1);\n\tcmd_buffer->End();\n\trhi_context->Execute(cmd_buffer);\n\n\tstd::vector<uint8_t> staging_data(staging_buffer->GetDesc().size);\n\tstaging_buffer->CopyToHost(staging_data.data(), staging_buffer->GetDesc().size);\n\n\treturn staging_data;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/Prefab.cpp",
    "content": "#include \"Resource/Prefab.hpp\"\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::Prefab>::Impl\n{\n\tNode root;\n};\n\nResource<ResourceType::Prefab>::Resource(RHIContext *rhi_context, const std::string &name):\n    IResource(rhi_context, name, ResourceType::Prefab)\n{\n}\n\nResource<ResourceType::Prefab>::Resource(RHIContext *rhi_context, const std::string &name, Node &&root) :\n    IResource(name)\n{\n\tm_impl       = new Impl;\n\tm_impl->root = std::move(root);\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(\"Asset/BuildIn/prefab.icon.asset\", thumbnail_data);\n\tUpdateThumbnail(rhi_context, thumbnail_data);\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Prefab), thumbnail_data, m_impl->root);\n}\n\nResource<ResourceType::Prefab>::~Resource()\n{\n\tdelete m_impl;\n}\n\nbool Resource<ResourceType::Prefab>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::Prefab>::Load(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Prefab), thumbnail_data, m_impl->root);\n}\n\nconst Resource<ResourceType::Prefab>::Node &Resource<ResourceType::Prefab>::GetRoot() const\n{\n\treturn m_impl->root;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/RenderPipeline.cpp",
    "content": "#include \"Resource/RenderPipeline.hpp\"\n\n#include <RenderGraph/RenderGraph.hpp>\n#include <RenderGraph/RenderGraphBuilder.hpp>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::RenderPipeline>::Impl\n{\n\tRenderGraphDesc desc;\n\tstd::string     layout;\n};\n\nResource<ResourceType::RenderPipeline>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::RenderPipeline)\n{\n}\n\nResource<ResourceType::RenderPipeline>::Resource(RHIContext *rhi_context, const std::string &name, RenderGraphDesc &&desc) :\n    IResource(name)\n{\n\tm_impl       = new Impl;\n\tm_impl->desc = std::move(desc);\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(\"Asset/BuildIn/pipeline.icon.asset\", thumbnail_data);\n\tUpdateThumbnail(rhi_context, thumbnail_data);\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", name, (uint32_t) ResourceType::RenderPipeline), thumbnail_data, m_impl->desc, m_impl->layout);\n}\n\nResource<ResourceType::RenderPipeline>::~Resource()\n{\n\tdelete m_impl;\n}\n\nbool Resource<ResourceType::RenderPipeline>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::RenderPipeline>::Load(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::RenderPipeline), thumbnail_data, m_impl->desc, m_impl->layout);\n}\n\nstd::unique_ptr<RenderGraph> Resource<ResourceType::RenderPipeline>::Compile(RHIContext *rhi_context, Renderer *renderer, glm::vec2 viewport, const std::string &layout)\n{\n\tif (!layout.empty())\n\t{\n\t\tm_impl->layout = layout;\n\t}\n\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::RenderPipeline), thumbnail_data);\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::RenderPipeline), thumbnail_data, m_impl->desc, m_impl->layout);\n\n\tRenderGraphDesc desc = m_impl->desc;\n\n\tfor (auto &[pass_handle, pass] : desc.GetPasses())\n\t{\n\t\tfor (auto &[pin_handle, pin] : pass.GetPins())\n\t\t{\n\t\t\tif (pin.attribute == RenderPassPin::Attribute::Output &&\n\t\t\t    pin.type == RenderPassPin::Type::Texture &&\n\t\t\t    (pin.texture.width == 0 || pin.texture.height == 0))\n\t\t\t{\n\t\t\t\tif (viewport.x <= 0 || viewport.y <= 0)\n\t\t\t\t{\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\t\t\t\tpin.texture.width  = static_cast<uint32_t>(viewport.x);\n\t\t\t\tpin.texture.height = static_cast<uint32_t>(viewport.y);\n\t\t\t}\n\t\t}\n\t}\n\n\tRenderGraphBuilder builder(rhi_context);\n\n\tauto render_graph = builder.Compile(desc, renderer);\n\n\treturn render_graph;\n}\n\nconst std::string &Resource<ResourceType::RenderPipeline>::GetLayout() const\n{\n\treturn m_impl->layout;\n}\n\nRenderGraphDesc &Resource<ResourceType::RenderPipeline>::GetDesc()\n{\n\treturn m_impl->desc;\n}\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/Scene.cpp",
    "content": "#include \"Resource/Scene.hpp\"\n\n#include <Scene/Scene.hpp>\n\nnamespace Ilum\n{\nResource<ResourceType::Scene>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::Scene)\n{\n}\n\nResource<ResourceType::Scene>::Resource(RHIContext *rhi_context, const std::string &name, Scene *scene) :\n    IResource(name)\n{\n\tSave(rhi_context, scene);\n}\n\nvoid Resource<ResourceType::Scene>::Update(Scene *scene)\n{\n\tstd::vector<uint8_t> thumbnail_data;\n\n\tscene->Clear();\n\n\t{\n\t\tstd::ifstream is(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Scene), std::ios::binary);\n\t\tInputArchive input_archive(is);\n\t\tinput_archive(thumbnail_data);\n\t\tscene->Load(input_archive);\n\t}\n}\n\nvoid Resource<ResourceType::Scene>::Save(RHIContext *rhi_context, Scene *scene)\n{\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(\"Asset/BuildIn/scene.icon.asset\", thumbnail_data);\n\tif (!m_thumbnail)\n\t{\n\t\tUpdateThumbnail(rhi_context, thumbnail_data);\n\t}\n\n\t{\n\t\tstd::ofstream os(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Scene), std::ios::binary);\n\t\tOutputArchive output_archive(os);\n\t\toutput_archive(thumbnail_data);\n\t\tscene->Save(output_archive);\n\t}\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/SkinnedMesh.cpp",
    "content": "#include \"Resource/SkinnedMesh.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::SkinnedMesh>::Impl\n{\n\tsize_t vertex_count  = 0;\n\tsize_t index_count   = 0;\n\tsize_t meshlet_count = 0;\n\tsize_t bone_count    = 0;\n\n\tstd::unique_ptr<RHIBuffer> vertex_buffer       = nullptr;\n\tstd::unique_ptr<RHIBuffer> index_buffer        = nullptr;\n\tstd::unique_ptr<RHIBuffer> meshlet_buffer      = nullptr;\n\tstd::unique_ptr<RHIBuffer> meshlet_data_buffer = nullptr;\n};\n\nResource<ResourceType::SkinnedMesh>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::SkinnedMesh)\n{\n}\n\nResource<ResourceType::SkinnedMesh>::Resource(RHIContext *rhi_context, const std::string &name, std::vector<SkinnedVertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshletdata) :\n    IResource(name)\n{\n\tm_impl = new Impl;\n\tUpdate(rhi_context, std::move(vertices), std::move(indices), std::move(meshlets), std::move(meshletdata));\n}\n\nResource<ResourceType::SkinnedMesh>::~Resource()\n{\n\tdelete m_impl;\n}\n\nbool Resource<ResourceType::SkinnedMesh>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::SkinnedMesh>::Load(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\n\tstd::vector<uint8_t>       thumbnail_data;\n\tstd::vector<SkinnedVertex> vertices;\n\tstd::vector<uint32_t>      indices;\n\tstd::vector<Meshlet>       meshlets;\n\tstd::vector<uint32_t>      meshlet_data;\n\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::SkinnedMesh), thumbnail_data, vertices, indices, meshlets, meshlet_data);\n\n\tUpdate(rhi_context, std::move(vertices), std::move(indices), std::move(meshlets), std::move(meshlet_data));\n}\n\nRHIBuffer *Resource<ResourceType::SkinnedMesh>::GetVertexBuffer() const\n{\n\treturn m_impl->vertex_buffer.get();\n}\n\nRHIBuffer *Resource<ResourceType::SkinnedMesh>::GetIndexBuffer() const\n{\n\treturn m_impl->index_buffer.get();\n}\n\nRHIBuffer *Resource<ResourceType::SkinnedMesh>::GetMeshletBuffer() const\n{\n\treturn m_impl->meshlet_buffer.get();\n}\n\nRHIBuffer *Resource<ResourceType::SkinnedMesh>::GetMeshletDataBuffer() const\n{\n\treturn m_impl->meshlet_data_buffer.get();\n}\n\nsize_t Resource<ResourceType::SkinnedMesh>::GetVertexCount() const\n{\n\treturn m_impl->vertex_count;\n}\n\nsize_t Resource<ResourceType::SkinnedMesh>::GetIndexCount() const\n{\n\treturn m_impl->index_count;\n}\n\nsize_t Resource<ResourceType::SkinnedMesh>::GetMeshletCount() const\n{\n\treturn m_impl->meshlet_count;\n}\n\nsize_t Resource<ResourceType::SkinnedMesh>::GetBoneCount() const\n{\n\treturn m_impl->bone_count;\n}\n\nvoid Resource<ResourceType::SkinnedMesh>::Update(RHIContext *rhi_context, std::vector<Resource<ResourceType::SkinnedMesh>::SkinnedVertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshletdata)\n{\n\tm_impl->vertex_count  = vertices.size();\n\tm_impl->index_count   = indices.size();\n\tm_impl->meshlet_count = meshlets.size();\n\n\tstd::unordered_set<int32_t> bone_set;\n\tfor (auto &v : vertices)\n\t{\n\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t{\n\t\t\tif (v.bones[i] != -1)\n\t\t\t{\n\t\t\t\tbone_set.insert(v.bones[i]);\n\t\t\t}\n\t\t}\n\t}\n\tm_impl->bone_count = bone_set.size();\n\n\tm_impl->vertex_buffer       = rhi_context->CreateBuffer<SkinnedVertex>(vertices.size(), RHIBufferUsage::Vertex | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\tm_impl->index_buffer        = rhi_context->CreateBuffer<uint32_t>(indices.size(), RHIBufferUsage::Index | RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\tm_impl->meshlet_data_buffer = rhi_context->CreateBuffer<uint32_t>(meshletdata.size(), RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\tm_impl->meshlet_buffer      = rhi_context->CreateBuffer<Meshlet>(meshlets.size(), RHIBufferUsage::UnorderedAccess | RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_Only);\n\n\tm_impl->vertex_buffer->CopyToDevice(vertices.data(), vertices.size() * sizeof(SkinnedVertex));\n\tm_impl->index_buffer->CopyToDevice(indices.data(), indices.size() * sizeof(uint32_t));\n\tm_impl->meshlet_data_buffer->CopyToDevice(meshletdata.data(), meshletdata.size() * sizeof(uint32_t));\n\tm_impl->meshlet_buffer->CopyToDevice(meshlets.data(), meshlets.size() * sizeof(Meshlet));\n\n\tglm::vec3 min_bound = glm::vec3(std::numeric_limits<float>::max());\n\tglm::vec3 max_bound = glm::vec3(-std::numeric_limits<float>::max());\n\tfor (const auto &v : vertices)\n\t{\n\t\tmin_bound = glm::min(min_bound, v.position);\n\t\tmax_bound = glm::max(max_bound, v.position);\n\t}\n\n\tglm::vec3 center = (max_bound + min_bound) * 0.5f;\n\tfloat     radius = glm::length(max_bound - min_bound);\n\n\tstd::vector<uint8_t> thumbnail_data = RenderPreview(rhi_context, center, radius);\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::SkinnedMesh), thumbnail_data, vertices, indices, meshlets, meshletdata);\n}\n\nstd::vector<uint8_t> Resource<ResourceType::SkinnedMesh>::RenderPreview(RHIContext *rhi_context, const glm::vec3 &center, float radius)\n{\n\t/*{\n\t    std::vector<uint8_t> raw_shader;\n\t    Path::GetInstance().Read(\"./Source/Shaders/Preview/Mesh.hlsl\", raw_shader);\n\n\t    std::string shader_source;\n\t    shader_source.resize(raw_shader.size());\n\t    std::memcpy(shader_source.data(), raw_shader.data(), raw_shader.size());\n\t    shader_source += \"\\n\";\n\n\t    ShaderDesc vertex_shader_desc  = {};\n\t\tvertex_shader_desc.path=\"./Source/Shaders/Preview/Mesh.hlsl\";\n\t    vertex_shader_desc.entry_point = \"VSmain\";\n\t    vertex_shader_desc.stage       = RHIShaderStage::Vertex;\n\t    vertex_shader_desc.source      = ShaderSource::HLSL;\n\t    vertex_shader_desc.target      = ShaderTarget::SPIRV;\n\t    vertex_shader_desc.code        = shader_source;\n\n\t    ShaderDesc fragment_shader_desc  = {};\n\t    fragment_shader_desc.path=\"./Source/Shaders/Preview/Mesh.hlsl\";\n\t    fragment_shader_desc.entry_point = \"PSmain\";\n\t    fragment_shader_desc.stage       = RHIShaderStage::Fragment;\n\t    fragment_shader_desc.source      = ShaderSource::HLSL;\n\t    fragment_shader_desc.target      = ShaderTarget::SPIRV;\n\t    fragment_shader_desc.code        = shader_source;\n\n\t    ShaderMeta vertex_meta   = {};\n\t    ShaderMeta fragment_meta = {};\n\n\t    auto vertex_shader_spirv   = ShaderCompiler::GetInstance().Compile(vertex_shader_desc, vertex_meta);\n\t    auto fragment_shader_spirv = ShaderCompiler::GetInstance().Compile(fragment_shader_desc, fragment_meta);\n\n\t    auto m_vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\t    auto m_fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\t    ShaderMeta shader_meta = vertex_meta;\n\t    shader_meta += fragment_meta;\n\n\t    SERIALIZE(\"Asset/BuildIn/mesh.preview.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\t}*/\n\n\tShaderMeta           shader_meta;\n\tstd::vector<uint8_t> vertex_shader_spirv;\n\tstd::vector<uint8_t> fragment_shader_spirv;\n\tDESERIALIZE(\"Asset/BuildIn/mesh.preview.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\n\tBlendState blend_state = {};\n\tblend_state.attachment_states.resize(1);\n\n\tDepthStencilState depth_stencil_state  = {};\n\tdepth_stencil_state.depth_test_enable  = true;\n\tdepth_stencil_state.depth_write_enable = true;\n\n\tif (!m_thumbnail)\n\t{\n\t\tm_thumbnail = rhi_context->CreateTexture2D(128, 128, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer | RHITextureUsage::RenderTarget, false);\n\t}\n\n\tauto depth_buffer    = rhi_context->CreateTexture2D(128, 128, RHIFormat::D32_FLOAT, RHITextureUsage::RenderTarget, false);\n\tauto uniform_buffer  = rhi_context->CreateBuffer<glm::mat4>(1, RHIBufferUsage::ConstantBuffer, RHIMemoryUsage::CPU_TO_GPU);\n\tauto staging_buffer  = rhi_context->CreateBuffer(128ull * 128ull * 4ull * sizeof(uint8_t), RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_TO_CPU);\n\tauto render_target   = rhi_context->CreateRenderTarget();\n\tauto pipeline_state  = rhi_context->CreatePipelineState();\n\tauto vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\tauto fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\tpipeline_state->SetBlendState(blend_state);\n\tpipeline_state->SetDepthStencilState(depth_stencil_state);\n\tpipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader.get());\n\tpipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader.get());\n\tpipeline_state->SetVertexInputState(VertexInputState{\n\t    {\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Position, 0, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, position)},\n\t        VertexInputState::InputAttribute{RHIVertexSemantics::Normal, 1, 0, RHIFormat::R32G32B32_FLOAT, offsetof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex, normal)},\n\t    },\n\t    {\n\t        VertexInputState::InputBinding{0, sizeof(Resource<ResourceType::SkinnedMesh>::SkinnedVertex), RHIVertexInputRate::Vertex},\n\t    }});\n\n\t{\n\t\tglm::vec3 position  = center + radius * glm::vec3(0.f, 0.f, 1.f);\n\t\tglm::vec3 direction = glm::normalize(center - position);\n\t\tglm::vec3 right     = glm::normalize(glm::cross(direction, glm::vec3{0.f, 1.f, 0.f}));\n\t\tglm::vec3 up        = glm::normalize(glm::cross(right, direction));\n\t\tglm::mat4 transform = glm::perspective(glm::radians(45.f), 1.f, 0.01f, 1000.f) * glm::lookAt(position, center, up);\n\t\tuniform_buffer->CopyToDevice(glm::value_ptr(transform), sizeof(transform));\n\t}\n\n\tauto descriptor = rhi_context->CreateDescriptor(shader_meta);\n\tdescriptor->BindBuffer(\"UniformBuffer\", uniform_buffer.get());\n\n\trender_target->Set(0, m_thumbnail.get(), TextureRange{}, ColorAttachment{RHILoadAction::Clear, RHIStoreAction::Store, {0.1f, 0.1f, 0.1f, 1.f}});\n\trender_target->Set(depth_buffer.get(), TextureRange{}, DepthStencilAttachment{});\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::Undefined, RHIResourceState::RenderTarget},\n\t                                        TextureStateTransition{depth_buffer.get(), RHIResourceState::Undefined, RHIResourceState::DepthWrite},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->BeginRenderPass(render_target.get());\n\tcmd_buffer->SetViewport(128, 128);\n\tcmd_buffer->SetScissor(128, 128);\n\tcmd_buffer->BindDescriptor(descriptor);\n\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\tcmd_buffer->BindVertexBuffer(0, m_impl->vertex_buffer.get());\n\tcmd_buffer->BindIndexBuffer(m_impl->index_buffer.get());\n\tcmd_buffer->DrawIndexed(static_cast<uint32_t>(m_impl->index_count));\n\tcmd_buffer->EndRenderPass();\n\tcmd_buffer->ResourceStateTransition({\n\t                                        TextureStateTransition{m_thumbnail.get(), RHIResourceState::RenderTarget, RHIResourceState::TransferSource},\n\t                                    },\n\t                                    {});\n\tcmd_buffer->CopyTextureToBuffer(m_thumbnail.get(), staging_buffer.get(), 0, 0, 1);\n\tcmd_buffer->End();\n\trhi_context->Execute(cmd_buffer);\n\n\tstd::vector<uint8_t> staging_data(staging_buffer->GetDesc().size);\n\tstaging_buffer->CopyToHost(staging_data.data(), staging_buffer->GetDesc().size);\n\n\treturn staging_data;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/Texture2D.cpp",
    "content": "#include \"Resource/Texture2D.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\n#include <fstream>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::Texture2D>::Impl\n{\n\tstd::unique_ptr<RHITexture> texture = nullptr;\n};\n\nResource<ResourceType::Texture2D>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::Texture2D)\n{\n}\n\nResource<ResourceType::Texture2D>::Resource(RHIContext *rhi_context, std::vector<uint8_t> &&data, const TextureDesc &desc) :\n    IResource(desc.name)\n{\n\tm_impl = std::make_unique<Impl>();\n\n\tm_impl->texture = rhi_context->CreateTexture(desc);\n\tm_thumbnail     = rhi_context->CreateTexture2D(128, 128, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer, false);\n\n\tBufferDesc buffer_desc = {};\n\tbuffer_desc.size       = glm::max(data.size(), 4ull * 128ull * 128ull);\n\tbuffer_desc.usage      = RHIBufferUsage::Transfer;\n\tbuffer_desc.memory     = RHIMemoryUsage::CPU_TO_GPU;\n\n\tauto staging_buffer = rhi_context->CreateBuffer(buffer_desc);\n\tstd::memcpy(staging_buffer->Map(), data.data(), data.size());\n\tstaging_buffer->Unmap();\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t         m_impl->texture.get(),\n\t         RHIResourceState::Undefined,\n\t         RHIResourceState::TransferDest,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, m_impl->texture.get()->GetDesc().mips, 0, 1}},\n\t     TextureStateTransition{\n\t         m_thumbnail.get(),\n\t         RHIResourceState::Undefined,\n\t         RHIResourceState::TransferDest,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t    {});\n\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), m_impl->texture.get(), 0, 0, 1);\n\tcmd_buffer->GenerateMipmaps(m_impl->texture.get(), RHIResourceState::TransferDest, RHIFilter::Linear);\n\tcmd_buffer->BlitTexture(m_impl->texture.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, RHIResourceState::TransferDest,\n\t                        m_thumbnail.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, RHIResourceState::TransferDest);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t         m_impl->texture.get(),\n\t         RHIResourceState::TransferDest,\n\t         RHIResourceState::ShaderResource,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, m_impl->texture.get()->GetDesc().mips, 0, 1}},\n\t     TextureStateTransition{\n\t         m_thumbnail.get(),\n\t         RHIResourceState::TransferDest,\n\t         RHIResourceState::TransferSource,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t    {});\n\tcmd_buffer->CopyTextureToBuffer(m_thumbnail.get(), staging_buffer.get(), 0, 0, 1);\n\tcmd_buffer->End();\n\n\trhi_context->Execute(cmd_buffer);\n\n\tstd::vector<uint8_t> thumbnail_data(4 * 128 * 128);\n\tstd::memcpy(thumbnail_data.data(), staging_buffer->Map(), thumbnail_data.size());\n\tstaging_buffer->Unmap();\n\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Texture2D), thumbnail_data, desc, data);\n}\n\nResource<ResourceType::Texture2D>::~Resource()\n{\n\tm_impl.reset();\n}\n\nbool Resource<ResourceType::Texture2D>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::Texture2D>::Load(RHIContext *rhi_context)\n{\n\tstd::vector<uint8_t> thumbnail_data, data;\n\tTextureDesc          desc;\n\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::Texture2D), thumbnail_data, desc, data);\n\n\tm_impl = std::make_unique<Impl>();\n\n\tm_impl->texture = rhi_context->CreateTexture(desc);\n\n\tBufferDesc buffer_desc = {};\n\tbuffer_desc.size       = data.size();\n\tbuffer_desc.usage      = RHIBufferUsage::Transfer;\n\tbuffer_desc.memory     = RHIMemoryUsage::CPU_TO_GPU;\n\n\tauto staging_buffer = rhi_context->CreateBuffer(buffer_desc);\n\tstd::memcpy(staging_buffer->Map(), data.data(), buffer_desc.size);\n\tstaging_buffer->Unmap();\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_impl->texture.get(),\n\t        RHIResourceState::Undefined,\n\t        RHIResourceState::TransferDest,\n\t        TextureRange{RHITextureDimension::Texture2D, 0, m_impl->texture.get()->GetDesc().mips, 0, 1}}},\n\t    {});\n\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), m_impl->texture.get(), 0, 0, 1);\n\tcmd_buffer->GenerateMipmaps(m_impl->texture.get(), RHIResourceState::TransferDest, RHIFilter::Linear);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_impl->texture.get(),\n\t        RHIResourceState::TransferDest,\n\t        RHIResourceState::ShaderResource,\n\t        TextureRange{RHITextureDimension::Texture2D, 0, m_impl->texture.get()->GetDesc().mips, 0, 1}}},\n\t    {});\n\tcmd_buffer->End();\n\n\trhi_context->Execute(cmd_buffer);\n}\n\nRHITexture *Resource<ResourceType::Texture2D>::GetTexture() const\n{\n\treturn m_impl->texture.get();\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource/TextureCube.cpp",
    "content": "#include \"Resource/TextureCube.hpp\"\n\n#include <RHI/RHIContext.hpp>\n#include <ShaderCompiler/ShaderCompiler.hpp>\n\n#include <fstream>\n\nnamespace Ilum\n{\nstruct Resource<ResourceType::TextureCube>::Impl\n{\n\tstd::unique_ptr<RHITexture> texture = nullptr;\n};\n\nResource<ResourceType::TextureCube>::Resource(RHIContext *rhi_context, const std::string &name) :\n    IResource(rhi_context, name, ResourceType::TextureCube)\n{\n}\n\nResource<ResourceType::TextureCube>::Resource(RHIContext *rhi_context, std::vector<uint8_t> &&data, const TextureDesc &desc) :\n    IResource(desc.name)\n{\n\tm_impl = std::make_unique<Impl>();\n\n\tauto cubemap2d = rhi_context->CreateTexture(desc);\n\n\tTextureDesc cubemap_desc = desc;\n\tcubemap_desc.width       = 512;\n\tcubemap_desc.height      = 512;\n\tcubemap_desc.depth       = 1;\n\tcubemap_desc.mips        = 5;\n\tcubemap_desc.layers      = 6;\n\tcubemap_desc.format      = RHIFormat::R32G32B32A32_FLOAT;\n\tcubemap_desc.usage |= RHITextureUsage::RenderTarget;\n\n\tm_impl->texture = rhi_context->CreateTexture(cubemap_desc);\n\tm_thumbnail     = rhi_context->CreateTextureCube(128, 128, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer, false);\n\n\tauto cubemap_buffer = rhi_context->CreateBuffer(4ull * 1024ull * 1024ull * 4ull * 6ull, RHIBufferUsage::Transfer, RHIMemoryUsage::GPU_TO_CPU);\n\tauto staging_buffer = rhi_context->CreateBuffer(glm::max(data.size(), 4ull * 128ull * 128ull), RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\tstaging_buffer->CopyToDevice(data.data(), staging_buffer->GetDesc().size);\n\n\t// Convert equirectangular to cubemap\n\t// std::vector<uint8_t> raw_shader;\n\t// Path::GetInstance().Read(\"./Source/Shaders/PreProcess/EquirectangularToCubemap.hlsl\", raw_shader);\n\n\t// std::string shader_source;\n\t// shader_source.resize(raw_shader.size());\n\t// std::memcpy(shader_source.data(), raw_shader.data(), raw_shader.size());\n\t// shader_source += \"\\n\";\n\n\t// ShaderDesc vertex_shader_desc  = {};\n\t// vertex_shader_desc.path = \"./Source/Shaders/PreProcess/EquirectangularToCubemap.hlsl\";\n\t// vertex_shader_desc.entry_point = \"VSmain\";\n\t// vertex_shader_desc.stage       = RHIShaderStage::Vertex;\n\t// vertex_shader_desc.source      = ShaderSource::HLSL;\n\t// vertex_shader_desc.target      = ShaderTarget::SPIRV;\n\t// vertex_shader_desc.code        = shader_source;\n\n\t// ShaderDesc fragment_shader_desc  = {};\n\t// fragment_shader_desc.path = \"./Source/Shaders/PreProcess/EquirectangularToCubemap.hlsl\";\n\t// fragment_shader_desc.entry_point = \"PSmain\";\n\t// fragment_shader_desc.stage       = RHIShaderStage::Fragment;\n\t// fragment_shader_desc.source      = ShaderSource::HLSL;\n\t// fragment_shader_desc.target      = ShaderTarget::SPIRV;\n\t// fragment_shader_desc.code        = shader_source;\n\n\t// ShaderMeta vertex_meta   = {};\n\t// ShaderMeta fragment_meta = {};\n\n\t// auto vertex_shader_spirv   = ShaderCompiler::GetInstance().Compile(vertex_shader_desc, vertex_meta);\n\t// auto fragment_shader_spirv = ShaderCompiler::GetInstance().Compile(fragment_shader_desc, fragment_meta);\n\n\t// auto vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\t// auto fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\t// ShaderMeta shader_meta = vertex_meta;\n\t// shader_meta += fragment_meta;\n\n\t// SERIALIZE(\"Asset/BuildIn/equirectangular_to_cubemap.shader.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\n\tstd::vector<uint8_t> vertex_shader_spirv, fragment_shader_spirv;\n\tShaderMeta           shader_meta;\n\n\tDESERIALIZE(\"Asset/BuildIn/equirectangular_to_cubemap.shader.asset\", vertex_shader_spirv, fragment_shader_spirv, shader_meta);\n\n\tauto vertex_shader   = rhi_context->CreateShader(\"VSmain\", vertex_shader_spirv);\n\tauto fragment_shader = rhi_context->CreateShader(\"PSmain\", fragment_shader_spirv);\n\n\tBlendState blend_state = {};\n\tblend_state.attachment_states.resize(1);\n\n\tDepthStencilState depth_stencil_state  = {};\n\tdepth_stencil_state.depth_test_enable  = false;\n\tdepth_stencil_state.depth_write_enable = false;\n\n\tauto pipeline_state = rhi_context->CreatePipelineState();\n\tauto descriptor     = rhi_context->CreateDescriptor(shader_meta);\n\tauto render_target  = rhi_context->CreateRenderTarget();\n\n\trender_target->Set(0, m_impl->texture.get(), TextureRange{RHITextureDimension::Texture2DArray, 0, 1, 0, 6}, ColorAttachment{});\n\n\tpipeline_state->SetShader(RHIShaderStage::Vertex, vertex_shader.get());\n\tpipeline_state->SetShader(RHIShaderStage::Fragment, fragment_shader.get());\n\tpipeline_state->SetBlendState(blend_state);\n\tpipeline_state->SetDepthStencilState(depth_stencil_state);\n\n\tdescriptor->BindTexture(\"InputTexture\", cubemap2d.get(), RHITextureDimension::Texture2D)\n\t    .BindSampler(\"TexSampler\", rhi_context->CreateSampler(SamplerDesc::LinearClamp()));\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t         cubemap2d.get(),\n\t         RHIResourceState::Undefined,\n\t         RHIResourceState::TransferDest,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, cubemap2d.get()->GetDesc().mips, 0, 1}},\n\t     TextureStateTransition{\n\t         m_thumbnail.get(),\n\t         RHIResourceState::Undefined,\n\t         RHIResourceState::TransferDest,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t    {});\n\t// Copy to thumbail\n\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), cubemap2d.get(), 0, 0, 1);\n\tcmd_buffer->BlitTexture(cubemap2d.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, RHIResourceState::TransferDest,\n\t                        m_thumbnail.get(), TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}, RHIResourceState::TransferDest);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t         cubemap2d.get(),\n\t         RHIResourceState::TransferDest,\n\t         RHIResourceState::ShaderResource,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, cubemap2d.get()->GetDesc().mips, 0, 1}},\n\t     TextureStateTransition{\n\t         m_thumbnail.get(),\n\t         RHIResourceState::TransferDest,\n\t         RHIResourceState::TransferSource,\n\t         TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}},\n\t     TextureStateTransition{\n\t         m_impl->texture.get(),\n\t         RHIResourceState::Undefined,\n\t         RHIResourceState::RenderTarget,\n\t         TextureRange{RHITextureDimension::Texture2DArray, 0, 5, 0, 6}}},\n\t    {});\n\n\t// Generate cubemap\n\tcmd_buffer->BeginRenderPass(render_target.get());\n\tcmd_buffer->SetViewport(512.f, 512.f);\n\tcmd_buffer->SetScissor(512, 512);\n\tcmd_buffer->BindDescriptor(descriptor);\n\tcmd_buffer->BindPipelineState(pipeline_state.get());\n\tcmd_buffer->Draw(3, 6);\n\tcmd_buffer->EndRenderPass();\n\n\t// Generate mipmap\n\tcmd_buffer->GenerateMipmaps(m_impl->texture.get(), RHIResourceState::RenderTarget, RHIFilter::Linear);\n\n\tcmd_buffer->CopyTextureToBuffer(m_thumbnail.get(), staging_buffer.get(), 0, 0, 1);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_impl->texture.get(),\n\t        RHIResourceState::TransferDest,\n\t        RHIResourceState::TransferSource,\n\t        TextureRange{RHITextureDimension::TextureCube, 0, 5, 0, 6}}},\n\t    {});\n\tcmd_buffer->CopyTextureToBuffer(m_impl->texture.get(), cubemap_buffer.get(), 0, 0, 6);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_impl->texture.get(),\n\t        RHIResourceState::TransferSource,\n\t        RHIResourceState::ShaderResource,\n\t        TextureRange{RHITextureDimension::TextureCube, 0, 5, 0, 6}}},\n\t    {});\n\tcmd_buffer->End();\n\n\trhi_context->Execute(cmd_buffer);\n\n\tstd::vector<uint8_t> thumbnail_data(4 * 128 * 128);\n\tstaging_buffer->CopyToHost(thumbnail_data.data(), thumbnail_data.size());\n\n\tstd::vector<uint8_t> cubemap_data(cubemap_buffer->GetDesc().size);\n\tcubemap_buffer->CopyToHost(cubemap_data.data(), cubemap_data.size());\n\n\tSERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::TextureCube), thumbnail_data, cubemap_desc, cubemap_data);\n}\n\nResource<ResourceType::TextureCube>::~Resource()\n{\n\tm_impl.reset();\n}\n\nbool Resource<ResourceType::TextureCube>::Validate() const\n{\n\treturn m_impl != nullptr;\n}\n\nvoid Resource<ResourceType::TextureCube>::Load(RHIContext *rhi_context)\n{\n\tstd::vector<uint8_t> thumbnail_data, cubemap_data;\n\tTextureDesc          desc;\n\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) ResourceType::TextureCube), thumbnail_data, desc, cubemap_data);\n\n\tm_impl = std::make_unique<Impl>();\n\n\tm_impl->texture = rhi_context->CreateTexture(desc);\n\n\tauto staging_buffer = rhi_context->CreateBuffer(cubemap_data.size(), RHIBufferUsage::Transfer, RHIMemoryUsage::CPU_TO_GPU);\n\tstaging_buffer->CopyToDevice(cubemap_data.data(), cubemap_data.size());\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_impl->texture.get(),\n\t        RHIResourceState::Undefined,\n\t        RHIResourceState::TransferDest,\n\t        TextureRange{RHITextureDimension::TextureCube, 0, m_impl->texture.get()->GetDesc().mips, 0, m_impl->texture.get()->GetDesc().layers}}},\n\t    {});\n\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), m_impl->texture.get(), 0, 0, m_impl->texture.get()->GetDesc().layers);\n\tcmd_buffer->GenerateMipmaps(m_impl->texture.get(), RHIResourceState::TransferDest, RHIFilter::Linear);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_impl->texture.get(),\n\t        RHIResourceState::TransferDest,\n\t        RHIResourceState::ShaderResource,\n\t        TextureRange{RHITextureDimension::TextureCube, 0, m_impl->texture.get()->GetDesc().mips, 0, m_impl->texture.get()->GetDesc().layers}}},\n\t    {});\n\tcmd_buffer->End();\n\n\trhi_context->Execute(cmd_buffer);\n}\n\nRHITexture *Resource<ResourceType::TextureCube>::GetTexture() const\n{\n\treturn m_impl->texture.get();\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/Resource.cpp",
    "content": "#include \"Resource.hpp\"\n#include \"Resource/Animation.hpp\"\n#include \"Resource/Material.hpp\"\n#include \"Resource/Mesh.hpp\"\n#include \"Resource/Prefab.hpp\"\n#include \"Resource/RenderPipeline.hpp\"\n#include \"Resource/SkinnedMesh.hpp\"\n#include \"Resource/Texture2D.hpp\"\n#include \"Resource/TextureCube.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nIResource::IResource(const std::string &name) :\n    m_name(name)\n{\n}\n\nIResource::IResource(RHIContext *rhi_context, const std::string &name, ResourceType type) :\n    m_name(name)\n{\n\tstd::vector<uint8_t> thumbnail_data;\n\tDESERIALIZE(fmt::format(\"Asset/Meta/{}.{}.asset\", m_name, (uint32_t) type), thumbnail_data);\n\n\tif (thumbnail_data.empty())\n\t{\n\t\treturn;\n\t}\n\n\tUpdateThumbnail(rhi_context, thumbnail_data);\n}\n\nconst std::string &IResource::GetName() const\n{\n\treturn m_name;\n}\n\nsize_t IResource::GetUUID() const\n{\n\treturn Hash(m_name);\n}\n\nRHITexture *IResource::GetThumbnail() const\n{\n\treturn m_thumbnail ? m_thumbnail.get() : nullptr;\n}\n\nvoid IResource::UpdateThumbnail(RHIContext *rhi_context, const std::vector<uint8_t> &thumbnail_data)\n{\n\tm_thumbnail = rhi_context->CreateTexture2D(128, 128, RHIFormat::R8G8B8A8_UNORM, RHITextureUsage::ShaderResource | RHITextureUsage::Transfer | RHITextureUsage::RenderTarget, false);\n\n\tBufferDesc buffer_desc = {};\n\tbuffer_desc.size       = thumbnail_data.size();\n\tbuffer_desc.usage      = RHIBufferUsage::Transfer;\n\tbuffer_desc.memory     = RHIMemoryUsage::CPU_TO_GPU;\n\n\tauto staging_buffer = rhi_context->CreateBuffer(buffer_desc);\n\tstd::memcpy(staging_buffer->Map(), thumbnail_data.data(), buffer_desc.size);\n\tstaging_buffer->Unmap();\n\n\tauto *cmd_buffer = rhi_context->CreateCommand(RHIQueueFamily::Graphics);\n\tcmd_buffer->Begin();\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_thumbnail.get(),\n\t        RHIResourceState::Undefined,\n\t        RHIResourceState::TransferDest,\n\t        TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t    {});\n\tcmd_buffer->CopyBufferToTexture(staging_buffer.get(), m_thumbnail.get(), 0, 0, 1);\n\tcmd_buffer->GenerateMipmaps(m_thumbnail.get(), RHIResourceState::TransferDest, RHIFilter::Linear);\n\tcmd_buffer->ResourceStateTransition(\n\t    {TextureStateTransition{\n\t        m_thumbnail.get(),\n\t        RHIResourceState::TransferDest,\n\t        RHIResourceState::ShaderResource,\n\t        TextureRange{RHITextureDimension::Texture2D, 0, 1, 0, 1}}},\n\t    {});\n\tcmd_buffer->End();\n\n\trhi_context->Execute(cmd_buffer);\n}\n\ntemplate class Resource<ResourceType::Mesh>;\ntemplate class Resource<ResourceType::SkinnedMesh>;\ntemplate class Resource<ResourceType::Material>;\ntemplate class Resource<ResourceType::Texture2D>;\ntemplate class Resource<ResourceType::TextureCube>;\ntemplate class Resource<ResourceType::Prefab>;\ntemplate class Resource<ResourceType::Animation>;\ntemplate class Resource<ResourceType::RenderPipeline>;\ntemplate class Resource<ResourceType::Scene>;\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Private/Resource/ResourceManager.cpp",
    "content": "#include \"ResourceManager.hpp\"\n#include \"Importer.hpp\"\n#include \"Resource.hpp\"\n#include \"Resource/Animation.hpp\"\n#include \"Resource/Material.hpp\"\n#include \"Resource/Mesh.hpp\"\n#include \"Resource/Prefab.hpp\"\n#include \"Resource/RenderPipeline.hpp\"\n#include \"Resource/Scene.hpp\"\n#include \"Resource/SkinnedMesh.hpp\"\n#include \"Resource/Texture2D.hpp\"\n#include \"Resource/TextureCube.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nstruct IResourceManager\n{\n\tIResourceManager(RHIContext *rhi_context) :\n\t    rhi_context(rhi_context)\n\t{\n\t}\n\n\tvirtual ~IResourceManager() = default;\n\n\tvirtual void Tick() = 0;\n\n\tvirtual IResource *Get(size_t uuid) = 0;\n\n\tvirtual size_t GetValidResourceCount() = 0;\n\n\tvirtual const std::string GetName(size_t uuid) = 0;\n\n\tvirtual RHITexture *GetThumbnail(size_t uuid) = 0;\n\n\tvirtual bool Valid(size_t uuid) = 0;\n\n\tvirtual bool Has(size_t uuid) = 0;\n\n\tvirtual size_t Index(size_t uuid) = 0;\n\n\tvirtual void Erase(size_t uuid) = 0;\n\n\tvirtual void Import(ResourceManager *manager, const std::string &path) = 0;\n\n\tvirtual void Add(std::unique_ptr<IResource> &&resource, size_t uuid) = 0;\n\n\tvirtual const std::vector<std::string> GetResources(bool only_valid) const = 0;\n\n\tvirtual bool Update() const = 0;\n\n\tvirtual void SetDirty() = 0;\n\n\tRHIContext *rhi_context = nullptr;\n};\n\ntemplate <ResourceType _Ty>\nstruct TResourceManager : public IResourceManager\n{\n\tTResourceManager(RHIContext *rhi_context) :\n\t    IResourceManager(rhi_context)\n\t{\n\t}\n\n\tvirtual ~TResourceManager() = default;\n\n\tvirtual void Tick() override\n\t{\n\t\tdeprecates.clear();\n\t\tupdate = false;\n\t}\n\n\tvirtual Resource<_Ty> *Get(size_t uuid) override\n\t{\n\t\tif (valid_lookup.find(uuid) != valid_lookup.end())\n\t\t{\n\t\t\tauto *resource = valid_resources.at(valid_lookup.at(uuid));\n\t\t\treturn resource;\n\t\t}\n\t\telse if (resource_lookup.find(uuid) != resource_lookup.end())\n\t\t{\n\t\t\tauto &resource = resources[resource_lookup[uuid]];\n\t\t\tresource->Load(rhi_context);\n\t\t\tvalid_lookup.emplace(uuid, valid_resources.size());\n\t\t\tvalid_resources.push_back(resource.get());\n\t\t\tupdate = true;\n\t\t\treturn resource.get();\n\t\t}\n\t\treturn nullptr;\n\t}\n\n\tvirtual size_t GetValidResourceCount() override\n\t{\n\t\treturn valid_resources.size();\n\t}\n\n\tvirtual const std::string GetName(size_t uuid) override\n\t{\n\t\treturn Has(uuid) ? resources[resource_lookup[uuid]]->GetName() : \"\";\n\t}\n\n\tvirtual RHITexture *GetThumbnail(size_t uuid) override\n\t{\n\t\treturn Has(uuid) ? resources.at(resource_lookup.at(uuid))->GetThumbnail() : nullptr;\n\t}\n\n\tvirtual bool Valid(size_t uuid) override\n\t{\n\t\treturn valid_lookup.find(uuid) != valid_lookup.end();\n\t}\n\n\tvirtual bool Has(size_t uuid) override\n\t{\n\t\treturn resource_lookup.find(uuid) != resource_lookup.end();\n\t}\n\n\tvirtual size_t Index(size_t uuid) override\n\t{\n\t\treturn (Valid(uuid) || Get(uuid)) ? valid_lookup.at(uuid) : ~0U;\n\t}\n\n\tvirtual void Erase(size_t uuid) override\n\t{\n\t\tif (valid_lookup.find(uuid) != valid_lookup.end())\n\t\t{\n\t\t\tsize_t last_uuid = ~0U;\n\t\t\tif (valid_resources.size() > 1)\n\t\t\t{\n\t\t\t\tfor (auto &[uuid_, index] : valid_lookup)\n\t\t\t\t{\n\t\t\t\t\tif (index + 1 == valid_lookup.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tlast_uuid = uuid_;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvalid_lookup[last_uuid] = valid_lookup[uuid];\n\t\t\t\tstd::swap(valid_resources.back(), valid_resources[valid_lookup[uuid]]);\n\t\t\t}\n\n\t\t\tvalid_resources.pop_back();\n\t\t\tvalid_lookup.erase(uuid);\n\t\t\tupdate = true;\n\t\t}\n\n\t\tif (resource_lookup.find(uuid) != resource_lookup.end())\n\t\t{\n\t\t\tsize_t last_uuid = ~0U;\n\t\t\tif (resources.size() > 1)\n\t\t\t{\n\t\t\t\tfor (auto &[uuid_, index] : resource_lookup)\n\t\t\t\t{\n\t\t\t\t\tif (index + 1 == resource_lookup.size())\n\t\t\t\t\t{\n\t\t\t\t\t\tlast_uuid = uuid_;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresource_lookup[last_uuid] = resource_lookup[uuid];\n\t\t\t\tstd::swap(resources.back(), resources[resource_lookup[uuid]]);\n\t\t\t}\n\n\t\t\tdeprecates.emplace_back(std::move(resources.back()));\n\t\t\tresources.pop_back();\n\t\t\tresource_lookup.erase(uuid);\n\t\t\tupdate = true;\n\t\t}\n\t}\n\n\tvirtual void Import(ResourceManager *manager, const std::string &path) override\n\t{\n\t\tImporter<_Ty>::Import(manager, path, rhi_context);\n\t}\n\n\tvirtual void Add(std::unique_ptr<IResource> &&resource, size_t uuid) override\n\t{\n\t\tif (resource_lookup.find(uuid) == resource_lookup.end())\n\t\t{\n\t\t\tresource_lookup.emplace(uuid, resources.size());\n\t\t\tresources.emplace_back(std::unique_ptr<Resource<_Ty>>(dynamic_cast<Resource<_Ty> *>(resource.release())));\n\n\t\t\tif (resources.back()->Validate())\n\t\t\t{\n\t\t\t\tvalid_lookup.emplace(uuid, valid_resources.size());\n\t\t\t\tvalid_resources.push_back(resources.back().get());\n\t\t\t}\n\n\t\t\tupdate = true;\n\t\t}\n\t}\n\n\tvirtual const std::vector<std::string> GetResources(bool only_valid) const override\n\t{\n\t\tstd::vector<std::string> handles;\n\t\tif (only_valid)\n\t\t{\n\t\t\thandles.resize(valid_resources.size());\n\t\t\tstd::transform(valid_resources.begin(), valid_resources.end(), handles.begin(), [](const auto &resource) {\n\t\t\t\treturn resource->GetName();\n\t\t\t});\n\t\t}\n\t\telse\n\t\t{\n\t\t\thandles.resize(resources.size());\n\t\t\tstd::transform(resources.begin(), resources.end(), handles.begin(), [](const auto &resource) {\n\t\t\t\treturn resource->GetName();\n\t\t\t});\n\t\t}\n\n\t\treturn handles;\n\t}\n\n\tvirtual bool Update() const override\n\t{\n\t\treturn update;\n\t}\n\n\tvirtual void SetDirty() override\n\t{\n\t\tupdate = true;\n\t}\n\n\tstd::vector<std::unique_ptr<Resource<_Ty>>> resources;\n\tstd::unordered_map<size_t, size_t>          resource_lookup;\n\n\tstd::vector<Resource<_Ty> *>       valid_resources;\n\tstd::unordered_map<size_t, size_t> valid_lookup;        // uuid - index\n\n\tstd::vector<std::unique_ptr<Resource<_Ty>>> deprecates;\n\n\tbool update = false;\n};\n\nstruct ResourceManager::Impl\n{\n\tstd::map<ResourceType, std::unique_ptr<IResourceManager>> managers;\n};\n\nResourceManager::ResourceManager(RHIContext *rhi_context)\n{\n\tm_impl = new Impl;\n\tm_impl->managers.emplace(ResourceType::Texture2D, std::make_unique<TResourceManager<ResourceType::Texture2D>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::TextureCube, std::make_unique<TResourceManager<ResourceType::TextureCube>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::Mesh, std::make_unique<TResourceManager<ResourceType::Mesh>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::SkinnedMesh, std::make_unique<TResourceManager<ResourceType::SkinnedMesh>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::Material, std::make_unique<TResourceManager<ResourceType::Material>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::Animation, std::make_unique<TResourceManager<ResourceType::Animation>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::Prefab, std::make_unique<TResourceManager<ResourceType::Prefab>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::RenderPipeline, std::make_unique<TResourceManager<ResourceType::RenderPipeline>>(rhi_context));\n\tm_impl->managers.emplace(ResourceType::Scene, std::make_unique<TResourceManager<ResourceType::Scene>>(rhi_context));\n\n\tstd::unordered_map<ResourceType, std::function<void(RHIContext *, const std::string &)>> loading_meta = {\n#define LOADING_META(RESOURCE_TYPE)                                                                                     \\\n\t{                                                                                                                   \\\n\t\tRESOURCE_TYPE, [&](RHIContext *rhi_context, const std::string &name) { Add<RESOURCE_TYPE>(rhi_context, name); } \\\n\t}\n\n\t    LOADING_META(ResourceType::Texture2D),\n\t    LOADING_META(ResourceType::TextureCube),\n\t    LOADING_META(ResourceType::Mesh),\n\t    LOADING_META(ResourceType::SkinnedMesh),\n\t    LOADING_META(ResourceType::Texture2D),\n\t    LOADING_META(ResourceType::Material),\n\t    LOADING_META(ResourceType::Animation),\n\t    LOADING_META(ResourceType::Prefab),\n\t    LOADING_META(ResourceType::RenderPipeline),\n\t    LOADING_META(ResourceType::Scene),\n\t};\n\n\tfor (const auto &file : std::filesystem::directory_iterator(\"Asset/Meta/\"))\n\t{\n\t\tstd::string filename = file.path().filename().string();\n\t\tif (Path::GetInstance().GetFileExtension(filename) == \".asset\")\n\t\t{\n\t\t\tstd::string  resource_name = \"\";\n\t\t\tResourceType resource_type = ResourceType::Unknown;\n\n\t\t\tsize_t last_pos        = filename.find_last_of('.');\n\t\t\tsize_t second_last_pos = filename.substr(0, last_pos).find_last_of('.');\n\n\t\t\tresource_name = filename.substr(0, second_last_pos);\n\t\t\tresource_type = (ResourceType) (std::atoi(filename.substr(second_last_pos + 1, last_pos - second_last_pos).c_str()));\n\n\t\t\tloading_meta.at(resource_type)(rhi_context, resource_name);\n\t\t}\n\t}\n}\n\nResourceManager::~ResourceManager()\n{\n\tdelete m_impl;\n}\n\nvoid ResourceManager::Tick()\n{\n\tfor (auto &[type, manager] : m_impl->managers)\n\t{\n\t\tmanager->Tick();\n\t}\n}\n\nIResource *ResourceManager::Get(ResourceType type, size_t uuid)\n{\n\treturn m_impl->managers.at(type)->Get(uuid);\n}\n\nsize_t ResourceManager::GetValidResourceCount(ResourceType type) const\n{\n\treturn m_impl->managers.at(type)->GetValidResourceCount();\n}\n\nRHITexture *ResourceManager::GetThumbnail(ResourceType type, size_t uuid)\n{\n\treturn m_impl->managers.at(type)->GetThumbnail(uuid);\n}\n\nbool ResourceManager::Valid(ResourceType type, size_t uuid)\n{\n\treturn m_impl->managers.at(type)->Valid(uuid);\n}\n\nbool ResourceManager::Has(ResourceType type, size_t uuid)\n{\n\treturn m_impl->managers.at(type)->Has(uuid);\n}\n\nsize_t ResourceManager::Index(ResourceType type, size_t uuid)\n{\n\treturn m_impl->managers.at(type)->Index(uuid);\n}\n\nvoid ResourceManager::Import(ResourceType type, const std::string &path)\n{\n\tm_impl->managers.at(type)->Import(this, path);\n}\n\nvoid ResourceManager::Erase(ResourceType type, size_t uuid)\n{\n\tstd::string asset_path = fmt::format(\"Asset/Meta/{}.{}.asset\", m_impl->managers.at(type)->GetName(uuid), (uint32_t) type);\n\tif (Path::GetInstance().IsExist(asset_path))\n\t{\n\t\tPath::GetInstance().DeletePath(asset_path);\n\t}\n\tm_impl->managers.at(type)->Erase(uuid);\n}\n\nvoid ResourceManager::Add(ResourceType type, std::unique_ptr<IResource> &&resource)\n{\n\tsize_t uuid = resource->GetUUID();\n\tm_impl->managers.at(type)->Add(std::move(resource), uuid);\n}\n\nconst std::vector<std::string> ResourceManager::GetResources(ResourceType type, bool only_valid) const\n{\n\treturn m_impl->managers.at(type)->GetResources(only_valid);\n}\n\nbool ResourceManager::Update(ResourceType type) const\n{\n\treturn m_impl->managers.at(type)->Update();\n}\n\nvoid ResourceManager::SetDirty(ResourceType type)\n{\n\treturn m_impl->managers.at(type)->SetDirty();\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Importer.hpp",
    "content": "#pragma once\n\n#include \"Resource.hpp\"\n\nnamespace Ilum\n{\nclass RHIContext;\nclass ResourceManager;\n\ntemplate <ResourceType Type>\nclass Importer\n{\n  public:\n\tImporter() = default;\n\n\tvirtual ~Importer() = default;\n\n\tstatic std::unique_ptr<Importer<Type>> &GetInstance(const std::string &plugin);\n\n\tstatic void Import(ResourceManager* manager, const std::string &path, RHIContext *rhi_context);\n\n  protected:\n\tvirtual void Import_(ResourceManager *manager, const std::string &path, RHIContext *rhi_context) = 0;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/Animation.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <glm/gtc/matrix_transform.hpp>\n#include <glm/gtx/quaternion.hpp>\n\nnamespace Ilum\n{\nclass Animation;\nclass RHIContext;\nclass RHIBuffer;\nclass RHITexture;\n\nclass Bone\n{\n  public:\n\tstruct KeyPosition\n\t{\n\t\tglm::vec3 position;\n\t\tfloat     time_stamp;\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(position, time_stamp);\n\t\t}\n\t};\n\n\tstruct KeyRotation\n\t{\n\t\tglm::quat orientation;\n\t\tfloat     time_stamp;\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(orientation, time_stamp);\n\t\t}\n\t};\n\n\tstruct KeyScale\n\t{\n\t\tglm::vec3 scale;\n\t\tfloat     time_stamp;\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(scale, time_stamp);\n\t\t}\n\t};\n\n\tstruct BoneMatrix\n\t{\n\t\tfloat     frame;\n\t\tglm::mat4 transform = glm::mat4(1.f);\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(frame, transform);\n\t\t}\n\t};\n\n  public:\n\tBone() = default;\n\n\tBone(\n\t    const std::string         &name,\n\t    uint32_t                   id,\n\t    glm::mat4                  offset,\n\t    std::vector<KeyPosition> &&positions,\n\t    std::vector<KeyRotation> &&rotations,\n\t    std::vector<KeyScale>    &&scales);\n\n\t~Bone() = default;\n\n\tvoid Update(float time);\n\n\tglm::mat4 GetLocalTransform() const;\n\n\tstd::string GetBoneName() const;\n\n\tuint32_t GetBoneID() const;\n\n\tglm::mat4 GetBoneOffset() const;\n\n\tsize_t GetPositionIndex(float time) const;\n\n\tsize_t GetRotationIndex(float time) const;\n\n\tsize_t GetScaleIndex(float time) const;\n\n\tglm::mat4 GetLocalTransform(float time) const;\n\n\tglm::mat4 GetTransformedOffset(float time) const;\n\n\tfloat GetMaxTimeStamp() const;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(m_name, m_id, m_offset, m_positions, m_rotations, m_scales, m_max_timestamp, m_local_transfrom);\n\t}\n\n  private:\n\tfloat GetScaleFactor(float last, float next, float time) const;\n\n\tglm::mat4 InterpolatePosition(float time) const;\n\n\tglm::mat4 InterpolateRotation(float time) const;\n\n\tglm::mat4 InterpolateScaling(float time) const;\n\n  private:\n\tstd::string m_name;\n\tuint32_t    m_id;\n\tglm::mat4   m_offset;\n\n\tstd::vector<KeyPosition> m_positions;\n\tstd::vector<KeyRotation> m_rotations;\n\tstd::vector<KeyScale>    m_scales;\n\n\tfloat m_max_timestamp = 0.f;\n\n\tglm::mat4 m_local_transfrom;\n};\n\nstruct HierarchyNode\n{\n\tstd::string name;\n\tglm::mat4   transform;\n\n\tstd::vector<HierarchyNode> children;\n\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive)\n\t{\n\t\tarchive(name, transform, children);\n\t}\n};\n\ntemplate <>\nclass Resource<ResourceType::Animation> final : public IResource\n{\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, std::vector<Bone> &&bones, HierarchyNode &&hierarchy);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tconst std::vector<Bone> &GetBones() const;\n\n\tBone *GetBone(const std::string &name);\n\n\tuint32_t GetBoneCount() const;\n\n\tuint32_t GetMaxBoneIndex() const;\n\n\tfloat GetMaxTimeStamp() const;\n\n\tuint32_t GetFrameCount() const;\n\n\tconst HierarchyNode &GetHierarchyNode() const;\n\n\tvoid Bake(RHIContext *rhi_context);\n\n\tRHITexture *GetSkinnedMatrics() const;\n\n\tRHIBuffer *GetBoneMatrics() const;\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/Material.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass MaterialGraphDesc;\nclass ResourceManager;\nstruct MaterialData;\nstruct MaterialCompilationContext;\n\ntemplate <>\nclass Resource<ResourceType::Material> final : public IResource\n{\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, MaterialGraphDesc &&desc);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tvoid Compile(RHIContext *rhi_context, ResourceManager *manager, RHITexture *dummy_texture, const std::string &layout = \"\");\n\n\tvoid Update(RHIContext *rhi_context, ResourceManager *manager, RHITexture *dummy_texture);\n\n\tvoid PostUpdate(RHIContext *rhi_context, uint32_t material_id, const std::vector<RHITexture *> &scene_texture_2d, const std::vector<RHISampler *> &samplers, RHIBuffer *material_buffers, RHIBuffer *material_offsets);\n\n\tconst MaterialData &GetMaterialData() const;\n\n\tconst MaterialCompilationContext &GetCompilationContext() const;\n\n\tconst std::string &GetLayout() const;\n\n\tMaterialGraphDesc &GetDesc();\n\n\tbool IsValid() const;\n\n  private:\n\tstd::vector<uint8_t> RenderPreview(RHIContext *rhi_context, uint32_t material_id, const std::vector<RHITexture *> &scene_texture_2d, const std::vector<RHISampler *> &samplers, RHIBuffer *material_buffers, RHIBuffer *material_offsets);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/Mesh.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <Geometry/Meshlet.hpp>\n\nnamespace Ilum\n{\nclass RHIContext;\nclass RHIBuffer;\nclass RHIAccelerationStructure;\n\ntemplate <>\nclass Resource<ResourceType::Mesh> final : public IResource\n{\n  public:\n\tstruct Vertex\n\t{\n\t\talignas(16) glm::vec3 position;\n\t\talignas(16) glm::vec3 normal;\n\t\talignas(16) glm::vec3 tangent;\n\n\t\talignas(16) glm::vec2 texcoord0;\n\t\tglm::vec2 texcoord1;\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(position, normal, tangent, texcoord0, texcoord1);\n\t\t}\n\t};\n\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, std::vector<Vertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshlet_data);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tRHIBuffer *GetVertexBuffer() const;\n\n\tRHIBuffer *GetIndexBuffer() const;\n\n\tRHIBuffer *GetMeshletDataBuffer() const;\n\n\tRHIBuffer *GetMeshletBuffer() const;\n\n\tRHIAccelerationStructure *GetBLAS() const;\n\n\tsize_t GetVertexCount() const;\n\n\tsize_t GetIndexCount() const;\n\n\tsize_t GetMeshletCount() const;\n\n\tvoid Update(RHIContext *rhi_context, std::vector<Vertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshlet_data);\n\n  private:\n\tstd::vector<uint8_t> RenderPreview(RHIContext *rhi_context, const glm::vec3& center, float radius);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/Prefab.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\ntemplate <>\nclass Resource<ResourceType::Prefab> final : public IResource\n{\n  public:\n\ttemplate <typename Archive>\n\tvoid serialize(Archive &archive, std::pair<ResourceType, std::string> &m)\n\t{\n\t\tarchive(m.first, m.second);\n\t}\n\n\tstruct Node\n\t{\n\t\tstd::string name      = \"\";\n\t\tglm::mat4   transform = glm::mat4(1.f);\n\n\t\tstd::vector<Node> children;\n\n\t\tstd::vector<std::pair<ResourceType, std::string>> resources;\n\n\t\ttemplate <typename Archive>\n\t\tvoid save(Archive &archive) const\n\t\t{\n\t\t\tarchive(name, transform, children);\n\t\t\tarchive(resources.size());\n\t\t\tfor (auto &[type, name] : resources)\n\t\t\t{\n\t\t\t\tarchive(type, name);\n\t\t\t}\n\t\t}\n\n\t\ttemplate <typename Archive>\n\t\tvoid load(Archive &archive)\n\t\t{\n\t\t\tarchive(name, transform, children);\n\t\t\tsize_t count = 0;\n\t\t\tarchive(count);\n\t\t\tfor (size_t i = 0; i < count; i++)\n\t\t\t{\n\t\t\t\tResourceType type = ResourceType::Unknown;\n\t\t\t\tstd::string  name;\n\t\t\t\tarchive(type, name);\n\t\t\t\tresources.emplace_back(std::make_pair(type, name));\n\t\t\t}\n\t\t}\n\t};\n\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, Node &&root);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tconst Node &GetRoot() const;\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/RenderPipeline.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass RenderGraphDesc;\nclass RenderGraph;\nclass Renderer;\n\ntemplate <>\nclass Resource<ResourceType::RenderPipeline> final : public IResource\n{\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, RenderGraphDesc &&desc);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tstd::unique_ptr<RenderGraph> Compile(RHIContext *rhi_context, Renderer* renderer, glm::vec2 viewport, const std::string &layout = \"\");\n\n\tconst std::string &GetLayout() const;\n\n\tRenderGraphDesc &GetDesc();\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/Scene.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass Scene;\n\ntemplate <>\nclass Resource<ResourceType::Scene> final : public IResource\n{\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, Scene *scene);\n\n\tvirtual ~Resource() override = default;\n\n\tvoid Update(Scene *scene);\n\n\tvoid Save(RHIContext *rhi_context, Scene *scene);\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/SkinnedMesh.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <Geometry/Meshlet.hpp>\n\n#define MAX_BONE_INFLUENCE 8\n\nnamespace Ilum\n{\nclass RHIContext;\nclass RHIBuffer;\nclass RHIAccelerationStructure;\n\ntemplate <>\nclass Resource<ResourceType::SkinnedMesh> final : public IResource\n{\n  public:\n\tstruct SkinnedVertex\n\t{\n\t\talignas(16) glm::vec3 position;\n\t\talignas(16) glm::vec3 normal;\n\t\talignas(16) glm::vec3 tangent;\n\n\t\talignas(16) glm::vec2 texcoord0;\n\t\tglm::vec2 texcoord1;\n\n\t\tint32_t bones[8]   = {-1, -1, -1, -1, -1, -1, -1, -1};\n\t\tfloat   weights[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};\n\n\t\ttemplate <typename Archive>\n\t\tvoid serialize(Archive &archive)\n\t\t{\n\t\t\tarchive(position, normal, tangent, texcoord0, texcoord1, bones, weights);\n\t\t}\n\t};\n\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, const std::string &name, std::vector<SkinnedVertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshletdata);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tRHIBuffer *GetVertexBuffer() const;\n\n\tRHIBuffer *GetIndexBuffer() const;\n\n\tRHIBuffer *GetMeshletBuffer() const;\n\n\tRHIBuffer *GetMeshletDataBuffer() const;\n\n\tsize_t GetVertexCount() const;\n\n\tsize_t GetIndexCount() const;\n\n\tsize_t GetMeshletCount() const;\n\n\tsize_t GetBoneCount() const;\n\n\tvoid Update(RHIContext *rhi_context, std::vector<SkinnedVertex> &&vertices, std::vector<uint32_t> &&indices, std::vector<Meshlet> &&meshlets, std::vector<uint32_t> &&meshletdata);\n\n  private:\n\tstd::vector<uint8_t> RenderPreview(RHIContext *rhi_context, const glm::vec3 &center, float radius);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/Texture2D.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\ntemplate <>\nclass Resource<ResourceType::Texture2D> final : public IResource\n{\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, std::vector<uint8_t> &&data, const TextureDesc &desc);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tRHITexture *GetTexture() const;\n\n  private:\n\tstruct Impl;\n\tstd::unique_ptr<Impl> m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource/TextureCube.hpp",
    "content": "#pragma once\n\n#include \"../Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\ntemplate <>\nclass Resource<ResourceType::TextureCube> final : public IResource\n{\n  public:\n\tResource(RHIContext *rhi_context, const std::string &name);\n\n\tResource(RHIContext *rhi_context, std::vector<uint8_t> &&data, const TextureDesc &desc);\n\n\tvirtual ~Resource() override;\n\n\tvirtual bool Validate() const override;\n\n\tvirtual void Load(RHIContext *rhi_context) override;\n\n\tRHITexture *GetTexture() const;\n\n  private:\n\tstruct Impl;\n\tstd::unique_ptr<Impl> m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/Resource.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\nnamespace Ilum\n{\nclass RHITexture;\nclass RHIContext;\n\nenum class ResourceType\n{\n\tUnknown,\n\tPrefab,\n\tMesh,\n\tSkinnedMesh,\n\tTexture2D,\n\tAnimation,\n\tMaterial,\n\tRenderPipeline,\n\tScene,\n\tTextureCube,\n};\n\nclass IResource\n{\n  public:\n\texplicit IResource(const std::string &name);\n\n\texplicit IResource(RHIContext *rhi_context, const std::string &name, ResourceType type);\n\n\tvirtual ~IResource() = default;\n\n\tconst std::string &GetName() const;\n\n\tvirtual bool Validate() const\n\t{\n\t\treturn true;\n\t}\n\n\tvirtual void Load(RHIContext *rhi_context)\n\t{\n\t}\n\n\tsize_t GetUUID() const;\n\n\tRHITexture *GetThumbnail() const;\n\n  protected:\n\tvoid UpdateThumbnail(RHIContext *rhi_context, const std::vector<uint8_t> &thumbnail_data);\n\n  protected:\n\tstd::string m_name;\n\n\tstd::unique_ptr<RHITexture> m_thumbnail = nullptr;\n};\n\ntemplate <ResourceType Type>\nclass Resource : public IResource\n{\n  public:\n\tResource() = default;\n\n\tvirtual ~Resource() override = default;\n};\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Resource/Public/Resource/ResourceManager.hpp",
    "content": "#pragma once\n\n#include \"Resource.hpp\"\n\n#include <RHI/RHIContext.hpp>\n\nnamespace Ilum\n{\nclass ResourceManager\n{\n  public:\n\tResourceManager(RHIContext *rhi_context);\n\n\t~ResourceManager();\n\n\tvoid Tick();\n\n\ttemplate <ResourceType Type>\n\tResource<Type> *Get(const std::string &name)\n\t{\n\t\treturn static_cast<Resource<Type> *>(Get(Type, Hash(name)));\n\t}\n\n\ttemplate <ResourceType Type>\n\tsize_t GetValidResourceCount() const\n\t{\n\t\treturn GetValidResourceCount(Type);\n\t}\n\n\ttemplate <ResourceType Type>\n\tRHITexture *GetThumbnail(const std::string &name)\n\t{\n\t\treturn GetThumbnail(Type, Hash(name));\n\t}\n\n\ttemplate <ResourceType Type>\n\tbool Valid(const std::string &name)\n\t{\n\t\treturn Valid(Type, Hash(name));\n\t}\n\n\ttemplate <ResourceType Type>\n\tbool Has(const std::string &name)\n\t{\n\t\treturn Has(Type, Hash(name));\n\t}\n\n\ttemplate <ResourceType Type>\n\tsize_t Index(const std::string &name)\n\t{\n\t\treturn Index(Type, Hash(name));\n\t}\n\n\ttemplate <ResourceType Type>\n\tvoid Import(const std::string &path)\n\t{\n\t\tImport(Type, path);\n\t}\n\n\ttemplate <ResourceType Type>\n\tvoid Erase(const std::string &path)\n\t{\n\t\tErase(Type, Hash(path));\n\t}\n\n\ttemplate <ResourceType Type, typename... Args>\n\tvoid Add(Args &&...args)\n\t{\n\t\tAdd(Type, std::make_unique<Resource<Type>>(std::forward<Args>(args)...));\n\t}\n\n\ttemplate <ResourceType Type>\n\tconst std::vector<std::string> GetResources(bool only_valid = true) const\n\t{\n\t\treturn GetResources(Type, only_valid);\n\t}\n\n\ttemplate <ResourceType Type>\n\tbool Update() const\n\t{\n\t\treturn Update(Type);\n\t}\n\n\ttemplate <ResourceType Type>\n\tvoid SetDirty()\n\t{\n\t\tSetDirty(Type);\n\t}\n\n  private:\n\tIResource *Get(ResourceType type, size_t uuid);\n\n\tsize_t GetValidResourceCount(ResourceType type) const;\n\n\tRHITexture* GetThumbnail(ResourceType type, size_t uuid);\n\n\tbool Valid(ResourceType type, size_t uuid);\n\n\tbool Has(ResourceType type, size_t uuid);\n\n\tsize_t Index(ResourceType type, size_t uuid);\n\n\tvoid Import(ResourceType type, const std::string &path);\n\n\tvoid Erase(ResourceType type, size_t uuid);\n\n\tvoid Add(ResourceType type, std::unique_ptr<IResource> &&resource);\n\n\tconst std::vector<std::string> GetResources(ResourceType type, bool only_valid) const;\n\n\tbool Update(ResourceType type) const;\n\n\tvoid SetDirty(ResourceType type);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Component.cpp",
    "content": "#include \"Component.hpp\"\n#include \"Node.hpp\"\n\nnamespace Ilum\n{\nComponent::Component(const char *name, Node *node) :\n    m_name(name), p_node(node)\n{\n\tm_update = true;\n}\n\nComponent::~Component()\n{\n\tm_update = true;\n}\n\nconst char *Component::GetName() const\n{\n\treturn m_name;\n}\n\nNode *Component::GetNode() const\n{\n\treturn p_node;\n}\n\nbool Component::IsUpdate()\n{\n\treturn m_update;\n}\n\nvoid Component::SetUpdate(bool update)\n{\n\tm_update = update;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/AllComponents.cpp",
    "content": "#include \"Components/AllComponents.hpp\"\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nvoid SetImGuiContext(ImGuiContext *context)\n{\n\treturn ImGui::SetCurrentContext(context);\n}\n}        // namespace Cmpt\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Camera/Camera.cpp",
    "content": "#include \"Components/Camera/Camera.hpp\"\n#include \"Components/Transform.hpp\"\n\n#include <Scene/Node.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nCamera::Camera(const char *name, Node *node) :\n    Component(name, node)\n{\n}\n\nvoid Camera::SetAspect(float aspect)\n{\n\tm_update |= (m_aspect != aspect);\n\tm_aspect = aspect;\n}\n\nfloat Camera::GetAspect()\n{\n\treturn m_aspect;\n}\n\nvoid Camera::SetNearPlane(float near_plane)\n{\n\tm_update |= (near_plane != m_near);\n\tm_near   = near_plane;\n}\n\nvoid Camera::SetFarPlane(float far_plane)\n{\n\tm_update |= (far_plane != m_far);\n\tm_far    = far_plane;\n}\n\nfloat Camera::GetNearPlane() const\n{\n\treturn m_near;\n}\n\nfloat Camera::GetFarPlane() const\n{\n\treturn m_far;\n}\n\nglm::mat4 Camera::GetViewMatrix()\n{\n\tUpdateView();\n\treturn m_view;\n}\n\nglm::mat4 Camera::GetProjectionMatrix()\n{\n\tUpdateProjection();\n\treturn m_projection;\n}\n\nglm::mat4 Camera::GetViewProjectionMatrix()\n{\n\treturn GetProjectionMatrix() * GetViewMatrix();\n}\n\nglm::mat4 Camera::GetInvViewMatrix()\n{\n\tUpdateView();\n\treturn m_inv_view;\n}\n\nglm::mat4 Camera::GetInvProjectionMatrix()\n{\n\tUpdateProjection();\n\treturn m_inv_projection;\n}\n\nglm::mat4 Camera::GetInvViewProjectionMatrix()\n{\n\treturn GetInvViewMatrix() * GetInvProjectionMatrix();\n}\n\nconst std::array<glm::vec4, 6> &Camera::GetFrustumPlanes()\n{\n\tglm::mat4 view_projection = GetViewProjectionMatrix();\n\n\t// Left\n\tm_frustum_planes[0].x = view_projection[0].w + view_projection[0].x;\n\tm_frustum_planes[0].y = view_projection[1].w + view_projection[1].x;\n\tm_frustum_planes[0].z = view_projection[2].w + view_projection[2].x;\n\tm_frustum_planes[0].w = view_projection[3].w + view_projection[3].x;\n\n\t// Right\n\tm_frustum_planes[1].x = view_projection[0].w - view_projection[0].x;\n\tm_frustum_planes[1].y = view_projection[1].w - view_projection[1].x;\n\tm_frustum_planes[1].z = view_projection[2].w - view_projection[2].x;\n\tm_frustum_planes[1].w = view_projection[3].w - view_projection[3].x;\n\n\t// Top\n\tm_frustum_planes[2].x = view_projection[0].w - view_projection[0].y;\n\tm_frustum_planes[2].y = view_projection[1].w - view_projection[1].y;\n\tm_frustum_planes[2].z = view_projection[2].w - view_projection[2].y;\n\tm_frustum_planes[2].w = view_projection[3].w - view_projection[3].y;\n\n\t// Bottom\n\tm_frustum_planes[3].x = view_projection[0].w + view_projection[0].y;\n\tm_frustum_planes[3].y = view_projection[1].w + view_projection[1].y;\n\tm_frustum_planes[3].z = view_projection[2].w + view_projection[2].y;\n\tm_frustum_planes[3].w = view_projection[3].w + view_projection[3].y;\n\n\t// Near\n\tm_frustum_planes[4].x = view_projection[0].w + view_projection[0].z;\n\tm_frustum_planes[4].y = view_projection[1].w + view_projection[1].z;\n\tm_frustum_planes[4].z = view_projection[2].w + view_projection[2].z;\n\tm_frustum_planes[4].w = view_projection[3].w + view_projection[3].z;\n\n\t// Far\n\tm_frustum_planes[5].x = view_projection[0].w - view_projection[0].z;\n\tm_frustum_planes[5].y = view_projection[1].w - view_projection[1].z;\n\tm_frustum_planes[5].z = view_projection[2].w - view_projection[2].z;\n\tm_frustum_planes[5].w = view_projection[3].w - view_projection[3].z;\n\n\tfor (auto &plane : m_frustum_planes)\n\t{\n\t\tfloat length = glm::length(glm::vec3(plane.x, plane.y, plane.z));\n\t\tplane /= length;\n\t}\n\n\treturn m_frustum_planes;\n}\n\nvoid Camera::UpdateView()\n{\n\tif (m_inv_view != p_node->GetComponent<Cmpt::Transform>()->GetWorldTransform())\n\t{\n\t\tm_inv_view = p_node->GetComponent<Cmpt::Transform>()->GetWorldTransform();\n\t\tm_view     = glm::inverse(m_inv_view);\n\t}\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Camera/OrthographicCamera.cpp",
    "content": "#include \"Components/Camera/OrthographicCamera.hpp\"\n#include \"Components/Transform.hpp\"\n\n#include <Scene/Node.hpp>\n\n#include <glm/gtc/matrix_transform.hpp>\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nOrthographicCamera::OrthographicCamera(Node *node) :\n    Camera(\"Orthographic Camera\", node)\n{\n}\n\nbool OrthographicCamera::OnImGui()\n{\n\tm_update |= ImGui::DragFloat(\"Aspect\", &m_aspect, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Scale\", &m_scale, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Offset X\", &m_offset_x, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Offset Y\", &m_offset_y, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Near Plane\", &m_near, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Far Plane\", &m_far, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\t\n\treturn m_update;\n}\n\nstd::type_index OrthographicCamera::GetType() const\n{\n\treturn typeid(OrthographicCamera);\n}\n\nvoid OrthographicCamera::Save(OutputArchive &archive) const\n{\n\tarchive(m_aspect, m_near, m_far, m_view, m_inv_view, m_projection, m_inv_projection, m_view_projection, m_inv_view_projection, m_scale, m_offset_x, m_offset_y);\n}\n\nvoid OrthographicCamera::Load(InputArchive &archive)\n{\n\tarchive(m_aspect, m_near, m_far, m_view, m_inv_view, m_projection, m_inv_projection, m_view_projection, m_inv_view_projection, m_scale, m_offset_x, m_offset_y);\n\tm_update = true;\n}\n\nvoid OrthographicCamera::SetScale(float scale)\n{\n\tm_update = true;\n\tm_scale  = scale;\n}\n\nvoid OrthographicCamera::SetOffset(float x, float y)\n{\n\tm_update   = true;\n\tm_offset_x = x;\n\tm_offset_y = y;\n}\n\nfloat OrthographicCamera::GetScale() const\n{\n\treturn m_scale;\n}\n\nfloat OrthographicCamera::GetOffsetX() const\n{\n\treturn m_offset_x;\n}\n\nfloat OrthographicCamera::GetOffsetY() const\n{\n\treturn m_offset_y;\n}\n\nvoid OrthographicCamera::UpdateProjection()\n{\n\tif (!m_update)\n\t{\n\t\treturn;\n\t}\n\n\tfloat left   = m_offset_x - m_scale * m_aspect * 0.5f;\n\tfloat right  = m_offset_x + m_scale * m_aspect * 0.5f;\n\tfloat top    = m_offset_y + m_scale * 0.5f;\n\tfloat bottom = m_offset_y - m_scale * 0.5f;\n\n\tm_projection     = glm::ortho(left, right, bottom, top, m_near, m_far);\n\tm_inv_projection = glm::inverse(m_projection);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Camera/PerspectiveCamera.cpp",
    "content": "#include \"Components/Camera/PerspectiveCamera.hpp\"\n#include \"Components/Transform.hpp\"\n\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n\n#include <glm/gtc/matrix_transform.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nPerspectiveCamera::PerspectiveCamera(Node *node) :\n    Camera(\"Perspective Camera\", node)\n{\n}\n\nbool PerspectiveCamera::OnImGui()\n{\n\tm_update |= ImGui::DragFloat(\"Aspect\", &m_aspect, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Fov\", &m_fov, 0.01f, 0.f, 90.f, \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Near Plane\", &m_near, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\tm_update |= ImGui::DragFloat(\"Far Plane\", &m_far, 0.01f, 0.f, std::numeric_limits<float>::max(), \"%.3f\");\n\t\n\treturn m_update;\n}\n\nvoid PerspectiveCamera::Save(OutputArchive &archive) const\n{\n\tarchive(m_aspect, m_near, m_far, m_view, m_inv_view, m_projection, m_inv_projection, m_view_projection, m_inv_view_projection, m_fov);\n}\n\nvoid PerspectiveCamera::Load(InputArchive &archive)\n{\n\tarchive(m_aspect, m_near, m_far, m_view, m_inv_view, m_projection, m_inv_projection, m_view_projection, m_inv_view_projection, m_fov);\n\tm_update = true;\n}\n\nstd::type_index PerspectiveCamera::GetType() const\n{\n\treturn typeid(PerspectiveCamera);\n}\n\nvoid PerspectiveCamera::SetFov(float fov)\n{\n\tm_update = true;\n\tm_fov    = fov;\n}\n\nfloat PerspectiveCamera::GetFov() const\n{\n\treturn m_fov;\n}\n\nvoid PerspectiveCamera::UpdateProjection()\n{\n\tif (!m_update)\n\t{\n\t\treturn;\n\t}\n\n\tm_projection     = glm::perspective(glm::radians(m_fov), m_aspect, m_near, m_far);\n\tm_inv_projection = glm::inverse(m_projection);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Light/DirectionalLight.cpp",
    "content": "#include \"Components/Light/DirectionalLight.hpp\"\n#include \"Components/Camera/Camera.hpp\"\n#include \"Components/Transform.hpp\"\n#include \"Node.hpp\"\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nDirectionalLight::DirectionalLight(Node *node) :\n    Light(\"Directional Light\", node)\n{\n}\n\nbool DirectionalLight::OnImGui()\n{\n\tm_update |= ImGui::ColorEdit3(\"Color\", &m_data.color.x);\n\tm_update |= ImGui::DragFloat(\"Intensity\", &m_data.intensity, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tImGui::Text(\"Shadow Map Setting\");\n\tm_update |= ImGui::Checkbox(\"Cast Shadow\", reinterpret_cast<bool *>(&m_data.cast_shadow));\n\tm_update |= ImGui::SliderInt(\"Filter Sample\", reinterpret_cast<int32_t *>(&m_data.filter_sample), 1, 100);\n\tm_update |= ImGui::DragFloat(\"Filter Scale\", &m_data.filter_scale, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tm_update |= ImGui::DragFloat(\"Light Scale\", &m_data.light_scale, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\n\treturn m_update;\n}\n\nvoid DirectionalLight::Save(OutputArchive &archive) const\n{\n\tarchive(m_data.intensity, m_data.filter_sample, m_data.filter_scale, m_data.light_scale);\n}\n\nvoid DirectionalLight::Load(InputArchive &archive)\n{\n\tarchive(m_data.intensity, m_data.filter_sample, m_data.filter_scale, m_data.light_scale);\n\tm_update = true;\n}\n\nstd::type_index DirectionalLight::GetType() const\n{\n\treturn typeid(DirectionalLight);\n}\n\nbool DirectionalLight::CastShadow() const\n{\n\treturn m_data.cast_shadow;\n}\n\nvoid DirectionalLight::SetShadowID(uint32_t &shadow_id)\n{\n\tm_data.shadow_id = m_data.cast_shadow ? shadow_id++ : ~0u;\n}\n\nsize_t DirectionalLight::GetDataSize() const\n{\n\treturn sizeof(m_data);\n}\n\nvoid *DirectionalLight::GetData(Camera *camera)\n{\n\tauto *transform = p_node->GetComponent<Cmpt::Transform>();\n\n\tglm::vec3 scale;\n\tglm::quat rotation;\n\tglm::vec3 translation;\n\tglm::vec3 skew;\n\tglm::vec4 perspective;\n\tglm::decompose(transform->GetWorldTransform(), scale, rotation, translation, skew, perspective);\n\n\tm_data.direction = glm::mat3_cast(rotation) * glm::vec3(0.f, 0.f, -1.f);\n\n\tif (camera)\n\t{\n\t\tfloat cascade_splits[4] = {0.f};\n\n\t\tfloat near_clip  = camera->GetNearPlane();\n\t\tfloat far_clip   = camera->GetFarPlane();\n\t\tfloat clip_range = far_clip - near_clip;\n\t\tfloat ratio      = far_clip / near_clip;\n\n\t\t// Calculate split depths based on view camera frustum\n\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t{\n\t\t\tfloat p           = (static_cast<float>(i) + 1.f) / 4.f;\n\t\t\tfloat log         = near_clip * std::pow(ratio, p);\n\t\t\tfloat uniform     = near_clip + clip_range * p;\n\t\t\tfloat d           = 0.95f * (log - uniform) + uniform;\n\t\t\tcascade_splits[i] = (d - near_clip) / clip_range;\n\t\t}\n\n\t\t// Calculate orthographic projection matrix for each cascade\n\t\tfloat last_split_dist = 0.f;\n\t\tfor (uint32_t i = 0; i < 4; i++)\n\t\t{\n\t\t\tfloat split_dist = cascade_splits[i];\n\n\t\t\tglm::vec3 frustum_corners[8] = {\n\t\t\t    glm::vec3(-1.0f, 1.0f, 0.0f),\n\t\t\t    glm::vec3(1.0f, 1.0f, 0.0f),\n\t\t\t    glm::vec3(1.0f, -1.0f, 0.0f),\n\t\t\t    glm::vec3(-1.0f, -1.0f, 0.0f),\n\t\t\t    glm::vec3(-1.0f, 1.0f, 1.0f),\n\t\t\t    glm::vec3(1.0f, 1.0f, 1.0f),\n\t\t\t    glm::vec3(1.0f, -1.0f, 1.0f),\n\t\t\t    glm::vec3(-1.0f, -1.0f, 1.0f)};\n\n\t\t\t// Project frustum corners into world space\n\t\t\tglm::mat4 inv_cam = glm::inverse(camera->GetViewProjectionMatrix());\n\t\t\tfor (uint32_t j = 0; j < 8; j++)\n\t\t\t{\n\t\t\t\tglm::vec4 inv_corner = inv_cam * glm::vec4(frustum_corners[j], 1.f);\n\t\t\t\tfrustum_corners[j]   = glm::vec3(inv_corner / inv_corner.w);\n\t\t\t}\n\n\t\t\tfor (uint32_t j = 0; j < 4; j++)\n\t\t\t{\n\t\t\t\tglm::vec3 corner_ray   = frustum_corners[j + 4] - frustum_corners[j];\n\t\t\t\tfrustum_corners[j + 4] = frustum_corners[j] + corner_ray * split_dist;\n\t\t\t\tfrustum_corners[j]     = frustum_corners[j] + corner_ray * last_split_dist;\n\t\t\t}\n\n\t\t\t// Get frustum center\n\t\t\tglm::vec3 frustum_center = glm::vec3(0.0f);\n\t\t\tfor (uint32_t j = 0; j < 8; j++)\n\t\t\t{\n\t\t\t\tfrustum_center += frustum_corners[j];\n\t\t\t}\n\t\t\tfrustum_center /= 8.0f;\n\n\t\t\tfloat radius = 0.0f;\n\t\t\tfor (uint32_t j = 0; j < 8; j++)\n\t\t\t{\n\t\t\t\tfloat distance = glm::length(frustum_corners[j] - frustum_center);\n\t\t\t\tradius         = glm::max(radius, distance);\n\t\t\t}\n\t\t\tradius = std::ceil(radius * 16.0f) / 16.0f;\n\n\t\t\tglm::vec3 max_extents = glm::vec3(radius);\n\t\t\tglm::vec3 min_extents = -max_extents;\n\n\t\t\tmax_extents.z = 1000.f;\n\n\t\t\tglm::vec3 light_dir = glm::normalize(m_data.direction);\n\n\t\t\tm_data.shadow_cam_pos[i] = glm::vec4(frustum_center - light_dir * max_extents.z, 1.0);\n\n\t\t\tglm::mat4 light_view_matrix  = glm::lookAt(glm::vec3(m_data.shadow_cam_pos[i]), frustum_center, glm::vec3(0.0f, 1.0f, 0.0f));\n\t\t\tglm::mat4 light_ortho_matrix = glm::ortho(min_extents.x, max_extents.x, min_extents.y, max_extents.y, -2.f * (max_extents.z - min_extents.z), max_extents.z - min_extents.z);\n\n\t\t\t// Store split distance and matrix in cascade\n\t\t\tm_data.split_depth[i]     = -(near_clip + split_dist * clip_range);\n\t\t\tm_data.view_projection[i] = light_ortho_matrix * light_view_matrix;\n\n\t\t\t// Stablize\n\t\t\t// glm::vec3 shadow_origin = glm::vec3(0.0f);\n\t\t\t// shadow_origin           = (m_data.view_projection[i] * glm::vec4(shadow_origin, 1.0f));\n\t\t\t// shadow_origin *= 512.f;\n\n\t\t\t// glm::vec3 rounded_origin = glm::round(shadow_origin);\n\t\t\t// glm::vec3 round_offset   = rounded_origin - shadow_origin;\n\t\t\t// round_offset             = round_offset / 512.f;\n\t\t\t// round_offset.z           = 0.0f;\n\n\t\t\t// m_data.view_projection[i][3][0] += round_offset.x;\n\t\t\t// m_data.view_projection[i][3][1] += round_offset.y;\n\n\t\t\tlast_split_dist = cascade_splits[i];\n\t\t}\n\t}\n\n\treturn (void *) (&m_data);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Light/EnvironmentLight.cpp",
    "content": "#include \"Components/Light/EnvironmentLight.hpp\"\n\n#include <imgui.h>\n\nnamespace Ilum::Cmpt\n{\nEnvironmentLight::EnvironmentLight(Node *node) :\n    Light(\"Environment Light\", node)\n{\n}\n\nbool EnvironmentLight::OnImGui()\n{\n\tif (ImGui::Button(m_texture.c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8f, 30.f)))\n\t{\n\t\tm_texture = \"\";\n\t\tm_update  = true;\n\t}\n\n\tif (ImGui::BeginDragDropSource())\n\t{\n\t\tImGui::SetDragDropPayload(\"TextureCube\", m_texture.c_str(), m_texture.length() + 1);\n\t\tImGui::EndDragDropSource();\n\t}\n\n\tif (ImGui::BeginDragDropTarget())\n\t{\n\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"TextureCube\"))\n\t\t{\n\t\t\tm_texture = static_cast<const char *>(pay_load->Data);\n\t\t\tm_update = true;\n\t\t}\n\t}\n\n\treturn m_update;\n}\n\nvoid EnvironmentLight::Save(OutputArchive &archive) const\n{\n\tarchive(m_texture);\n}\n\nvoid EnvironmentLight::Load(InputArchive &archive)\n{\n\tarchive(m_texture);\n\tm_update = true;\n}\n\nstd::type_index EnvironmentLight::GetType() const\n{\n\treturn typeid(EnvironmentLight);\n}\n\nsize_t EnvironmentLight::GetDataSize() const\n{\n\treturn m_texture.length() + 1;\n}\n\nvoid *EnvironmentLight::GetData(Camera *camera)\n{\n\treturn m_texture.data();\n}\n}        // namespace Ilum::Cmpt"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Light/Light.cpp",
    "content": "#include \"Components/Light/Light.hpp\"\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nLight::Light(const char *name, Node *node) :\n    Component(name, node)\n{\n}\n\nbool Light::CastShadow() const\n{\n\treturn false;\n}\n\nvoid Light::SetShadowID(uint32_t &shadow_id)\n{\n}\n\nvoid Light::CalculateFrustum(const glm::mat4 &view_projection, std::array<glm::vec4, 6> &frustum)\n{\n\t// Left\n\tfrustum[0].x = view_projection[0].w + view_projection[0].x;\n\tfrustum[0].y = view_projection[1].w + view_projection[1].x;\n\tfrustum[0].z = view_projection[2].w + view_projection[2].x;\n\tfrustum[0].w = view_projection[3].w + view_projection[3].x;\n\n\t// Right\n\tfrustum[1].x = view_projection[0].w - view_projection[0].x;\n\tfrustum[1].y = view_projection[1].w - view_projection[1].x;\n\tfrustum[1].z = view_projection[2].w - view_projection[2].x;\n\tfrustum[1].w = view_projection[3].w - view_projection[3].x;\n\n\t// Top\n\tfrustum[2].x = view_projection[0].w - view_projection[0].y;\n\tfrustum[2].y = view_projection[1].w - view_projection[1].y;\n\tfrustum[2].z = view_projection[2].w - view_projection[2].y;\n\tfrustum[2].w = view_projection[3].w - view_projection[3].y;\n\n\t// Bottom\n\tfrustum[3].x = view_projection[0].w + view_projection[0].y;\n\tfrustum[3].y = view_projection[1].w + view_projection[1].y;\n\tfrustum[3].z = view_projection[2].w + view_projection[2].y;\n\tfrustum[3].w = view_projection[3].w + view_projection[3].y;\n\n\t// Near\n\tfrustum[4].x = view_projection[0].w + view_projection[0].z;\n\tfrustum[4].y = view_projection[1].w + view_projection[1].z;\n\tfrustum[4].z = view_projection[2].w + view_projection[2].z;\n\tfrustum[4].w = view_projection[3].w + view_projection[3].z;\n\n\t// Far\n\tfrustum[5].x = view_projection[0].w - view_projection[0].z;\n\tfrustum[5].y = view_projection[1].w - view_projection[1].z;\n\tfrustum[5].z = view_projection[2].w - view_projection[2].z;\n\tfrustum[5].w = view_projection[3].w - view_projection[3].z;\n\n\tfor (auto &plane : frustum)\n\t{\n\t\tfloat length = glm::length(glm::vec3(plane.x, plane.y, plane.z));\n\t\tplane /= length;\n\t}\n}\n\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Light/PointLight.cpp",
    "content": "#include \"Components/Light/PointLight.hpp\"\n#include \"Components/Transform.hpp\"\n#include \"Node.hpp\"\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nPointLight::PointLight(Node *node) :\n    Light(\"Point Light\", node)\n{\n}\n\nbool PointLight::OnImGui()\n{\n\tm_update |= ImGui::ColorEdit3(\"Color\", &m_data.color.x);\n\tm_update |= ImGui::DragFloat(\"Intensity\", &m_data.intensity, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tImGui::Text(\"Shadow Map Setting\");\n\tm_update |= ImGui::Checkbox(\"Cast Shadow\", reinterpret_cast<bool *>(&m_data.cast_shadow));\n\tm_update |= ImGui::SliderInt(\"Filter Sample\", reinterpret_cast<int32_t *>(&m_data.filter_sample), 1, 100);\n\tm_update |= ImGui::DragFloat(\"Filter Scale\", &m_data.filter_scale, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tm_update |= ImGui::DragFloat(\"Light Scale\", &m_data.light_scale, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\n\treturn m_update;\n}\n\nvoid PointLight::Save(OutputArchive &archive) const\n{\n\tarchive(m_data.color, m_data.intensity, m_data.position, m_data.filter_sample, m_data.filter_scale, m_data.light_scale);\n}\n\nvoid PointLight::Load(InputArchive &archive)\n{\n\tarchive(m_data.color, m_data.intensity, m_data.position, m_data.filter_sample, m_data.filter_scale, m_data.light_scale);\n\tm_update = true;\n}\n\nstd::type_index PointLight::GetType() const\n{\n\treturn typeid(PointLight);\n}\n\nbool PointLight::CastShadow() const\n{\n\treturn m_data.cast_shadow;\n}\n\nvoid PointLight::SetShadowID(uint32_t &shadow_id)\n{\n\tm_data.shadow_id = m_data.cast_shadow ? shadow_id++ : ~0u;\n}\n\nsize_t PointLight::GetDataSize() const\n{\n\treturn sizeof(m_data);\n}\n\nvoid *PointLight::GetData(Camera *camera)\n{\n\tauto *transform = p_node->GetComponent<Cmpt::Transform>();\n\n\tglm::vec3 scale;\n\tglm::quat rotation;\n\tglm::vec3 translation;\n\tglm::vec3 skew;\n\tglm::vec4 perspective;\n\tglm::decompose(transform->GetWorldTransform(), scale, rotation, translation, skew, perspective);\n\n\tm_data.position = translation;\n\treturn (void *) (&m_data);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Light/RectLight.cpp",
    "content": "#include \"Components/Light/RectLight.hpp\"\n#include \"Components/Transform.hpp\"\n#include \"Node.hpp\"\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nRectLight::RectLight(Node *node) :\n    Light(\"Rect Light\", node)\n{\n}\n\nbool RectLight::OnImGui()\n{\n\tm_update |= ImGui::ColorEdit3(\"Color\", &m_data.color.x);\n\tm_update |= ImGui::DragFloat(\"Intensity\", &m_data.intensity, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tm_update |= ImGui::Checkbox(\"Two Side\", reinterpret_cast<bool *>(&m_data.two_side));\n\treturn m_update;\n}\n\nvoid RectLight::Save(OutputArchive &archive) const\n{\n\tarchive(m_data.color, m_data.intensity, m_data.texture_id, m_data.corner);\n}\n\nvoid RectLight::Load(InputArchive &archive)\n{\n\tarchive(m_data.color, m_data.intensity, m_data.texture_id, m_data.corner);\n\tm_update = true;\n}\n\nstd::type_index RectLight::GetType() const\n{\n\treturn typeid(RectLight);\n}\n\nsize_t RectLight::GetDataSize() const\n{\n\treturn sizeof(m_data);\n}\n\nvoid *RectLight::GetData(Camera *camera)\n{\n\tglm::mat4 world_transform = p_node->GetComponent<Cmpt::Transform>()->GetWorldTransform();\n\n\tm_data.corner[0] = world_transform * glm::vec4(-0.5f, 0.f, -0.5f, 1.f);\n\tm_data.corner[1] = world_transform * glm::vec4(0.5f, 0.f, -0.5f, 1.f);\n\tm_data.corner[2] = world_transform * glm::vec4(0.5f, 0.f, 0.5f, 1.f);\n\tm_data.corner[3] = world_transform * glm::vec4(-0.5f, 0.f, 0.5f, 1.f);\n\n\treturn (void *) (&m_data);\n}\n}        // namespace Cmpt\n}        // namespace Ilum\n"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Light/SpotLight.cpp",
    "content": "#include \"Components/Light/SpotLight.hpp\"\n#include \"Components/Transform.hpp\"\n#include \"Node.hpp\"\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nSpotLight::SpotLight(Node *node) :\n    Light(\"Spot Light\", node)\n{\n}\n\nbool SpotLight::OnImGui()\n{\n\tfloat inner_angle = glm::degrees(m_data.inner_angle);\n\tfloat outer_angle = glm::degrees(m_data.outer_angle);\n\n\tm_update |= ImGui::ColorEdit3(\"Color\", &m_data.color.x);\n\tm_update |= ImGui::DragFloat(\"Intensity\", &m_data.intensity, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tm_update |= ImGui::DragFloat(\"Inner Angle\", &inner_angle, 0.1f, 0.f, outer_angle, \"%.1f\");\n\tm_update |= ImGui::DragFloat(\"Outer Angle\", &outer_angle, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tImGui::Text(\"Shadow Map Setting\");\n\tm_update |= ImGui::Checkbox(\"Cast Shadow\", reinterpret_cast<bool *>(&m_data.cast_shadow));\n\tm_update |= ImGui::SliderInt(\"Filter Sample\", reinterpret_cast<int32_t *>(&m_data.filter_sample), 1, 100);\n\tm_update |= ImGui::DragFloat(\"Filter Scale\", &m_data.filter_scale, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\tm_update |= ImGui::DragFloat(\"Light Scale\", &m_data.light_scale, 0.1f, 0.f, std::numeric_limits<float>::max(), \"%.1f\");\n\n\tm_data.inner_angle = glm::radians(inner_angle);\n\tm_data.outer_angle = glm::radians(outer_angle);\n\n\treturn m_update;\n}\n\nvoid SpotLight::Save(OutputArchive &archive) const\n{\n\tarchive(m_data.color, m_data.intensity, m_data.inner_angle, m_data.outer_angle, m_data.filter_sample, m_data.filter_scale, m_data.light_scale);\n}\n\nvoid SpotLight::Load(InputArchive &archive)\n{\n\tarchive(m_data.color, m_data.intensity, m_data.inner_angle, m_data.outer_angle, m_data.filter_sample, m_data.filter_scale, m_data.light_scale);\n\tm_update = true;\n}\n\nstd::type_index SpotLight::GetType() const\n{\n\treturn typeid(SpotLight);\n}\n\nbool SpotLight::CastShadow() const\n{\n\treturn m_data.cast_shadow;\n}\n\nvoid SpotLight::SetShadowID(uint32_t &shadow_id)\n{\n\tm_data.shadow_id = m_data.cast_shadow ? shadow_id++ : ~0u;\n}\n\nsize_t SpotLight::GetDataSize() const\n{\n\treturn sizeof(m_data);\n}\n\nvoid *SpotLight::GetData(Camera *camera)\n{\n\tauto *transform = p_node->GetComponent<Cmpt::Transform>();\n\n\tglm::vec3 scale;\n\tglm::quat rotation;\n\tglm::vec3 translation;\n\tglm::vec3 skew;\n\tglm::vec4 perspective;\n\tglm::decompose(transform->GetWorldTransform(), scale, rotation, translation, skew, perspective);\n\n\tm_data.position        = translation;\n\tm_data.direction       = glm::mat3_cast(rotation) * glm::vec3(0.f, 0.f, -1.f);\n\tm_data.view_projection = glm::perspective(2.f * m_data.outer_angle, 1.0f, 0.01f, 1000.f) * glm::lookAt(translation, translation + m_data.direction, glm::vec3(0.f, 1.f, 0.f));\n\n\treturn (void *) (&m_data);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Renderable/MeshRenderer.cpp",
    "content": "#include \"Components/Renderable/MeshRenderer.hpp\"\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nMeshRenderer::MeshRenderer(Node *node) :\n    Renderable(\"Mesh Renderer\", node)\n{\n}\n\nbool MeshRenderer::OnImGui()\n{\n\tif (ImGui::TreeNode(\"Submesh\"))\n\t{\n\t\tfor (auto &submesh : m_submeshes)\n\t\t{\n\t\t\tImGui::PushID(submesh.c_str());\n\n\t\t\tif (ImGui::Button(submesh.c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8f, 30.f)))\n\t\t\t{\n\t\t\t\tsubmesh  = \"\";\n\t\t\t\tm_update = true;\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropSource())\n\t\t\t{\n\t\t\t\tImGui::SetDragDropPayload(\"Mesh\", submesh.c_str(), submesh.length() + 1);\n\t\t\t\tImGui::EndDragDropSource();\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t{\n\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Mesh\"))\n\t\t\t\t{\n\t\t\t\t\tsubmesh  = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\tm_update = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::PopID();\n\t\t}\n\n\t\tif (ImGui::Button(\"+\"))\n\t\t{\n\t\t\tm_submeshes.emplace_back(\"\");\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(\"-\"))\n\t\t{\n\t\t\tm_submeshes.pop_back();\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::TreePop();\n\t}\n\n\tm_update |= Renderable::OnImGui();\n\n\treturn m_update;\n}\n\nstd::type_index MeshRenderer::GetType() const\n{\n\treturn typeid(MeshRenderer);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Renderable/Renderable.cpp",
    "content": "#include \"Components/Renderable/Renderable.hpp\"\n\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nRenderable::Renderable(const char *name, Node *node) :\n    Component(name, node)\n{\n}\n\nbool Renderable::OnImGui()\n{\n\tif (ImGui::TreeNode(\"Material\"))\n\t{\n\t\tfor (auto &material : m_materials)\n\t\t{\n\t\t\tImGui::PushID(material.c_str());\n\n\t\t\tif (ImGui::Button(material.c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8f, 30.f)))\n\t\t\t{\n\t\t\t\tmaterial = \"\";\n\t\t\t\tm_update = true;\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropSource())\n\t\t\t{\n\t\t\t\tImGui::SetDragDropPayload(\"Material\", material.c_str(), material.length() + 1);\n\t\t\t\tImGui::EndDragDropSource();\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t{\n\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Material\"))\n\t\t\t\t{\n\t\t\t\t\tmaterial = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\tm_update = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::PopID();\n\t\t}\n\n\t\tif (ImGui::Button(\"+\"))\n\t\t{\n\t\t\tm_materials.emplace_back(\"\");\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(\"-\"))\n\t\t{\n\t\t\tm_materials.pop_back();\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::TreePop();\n\t}\n\n\treturn m_update;\n}\n\nvoid Renderable::Save(OutputArchive &archive) const\n{\n\tarchive(m_submeshes, m_materials, m_animations);\n}\n\nvoid Renderable::Load(InputArchive &archive)\n{\n\tarchive(m_submeshes, m_materials, m_animations);\n\tm_update = true;\n}\n\nvoid Renderable::AddMaterial(const std::string &material)\n{\n\tm_materials.emplace_back(material);\n\tm_update = true;\n}\n\nvoid Renderable::AddSubmesh(const std::string &submesh)\n{\n\tm_submeshes.emplace_back(submesh);\n\tm_update = true;\n}\n\nvoid Renderable::AddAnimation(const std::string &animation)\n{\n\tm_animations.emplace_back(animation);\n\tm_update = true;\n}\n\nconst std::vector<std::string> &Renderable::GetSubmeshes() const\n{\n\treturn m_submeshes;\n}\n\nconst std::vector<std::string> &Renderable::GetMaterials() const\n{\n\treturn m_materials;\n}\n\nconst std::vector<std::string> &Renderable::GetAnimations() const\n{\n\treturn m_animations;\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Renderable/SkinnedMeshRenderer.cpp",
    "content": "#include \"Components/Renderable/SkinnedMeshRenderer.hpp\"\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nSkinnedMeshRenderer::SkinnedMeshRenderer(Node *node) :\n    Renderable(\"Skinned Mesh Renderer\", node)\n{\n}\n\nbool SkinnedMeshRenderer::OnImGui()\n{\n\tif (ImGui::TreeNode(\"Submesh\"))\n\t{\n\t\tfor (auto &submesh : m_submeshes)\n\t\t{\n\t\t\tImGui::PushID(submesh.c_str());\n\n\t\t\tif (ImGui::Button(submesh.c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8f, 30.f)))\n\t\t\t{\n\t\t\t\tsubmesh  = \"\";\n\t\t\t\tm_update = true;\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropSource())\n\t\t\t{\n\t\t\t\tImGui::SetDragDropPayload(\"SkinnedMesh\", submesh.c_str(), submesh.length() + 1);\n\t\t\t\tImGui::EndDragDropSource();\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t{\n\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"SkinnedMesh\"))\n\t\t\t\t{\n\t\t\t\t\tsubmesh  = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\tm_update = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::PopID();\n\t\t}\n\n\t\tif (ImGui::Button(\"+\"))\n\t\t{\n\t\t\tm_submeshes.emplace_back(\"\");\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(\"-\"))\n\t\t{\n\t\t\tm_submeshes.pop_back();\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::TreePop();\n\t}\n\n\tif (ImGui::TreeNode(\"Animation\"))\n\t{\n\t\tfor (auto &animation : m_animations)\n\t\t{\n\t\t\tImGui::PushID(animation.c_str());\n\n\t\t\tif (ImGui::Button(animation.c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8f, 30.f)))\n\t\t\t{\n\t\t\t\tanimation = \"\";\n\t\t\t\tm_update  = true;\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropSource())\n\t\t\t{\n\t\t\t\tImGui::SetDragDropPayload(\"Animation\", animation.c_str(), animation.length() + 1);\n\t\t\t\tImGui::EndDragDropSource();\n\t\t\t}\n\n\t\t\tif (ImGui::BeginDragDropTarget())\n\t\t\t{\n\t\t\t\tif (const auto *pay_load = ImGui::AcceptDragDropPayload(\"Animation\"))\n\t\t\t\t{\n\t\t\t\t\tanimation = static_cast<const char *>(pay_load->Data);\n\t\t\t\t\tm_update  = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::PopID();\n\t\t}\n\n\t\tif (ImGui::Button(\"+\"))\n\t\t{\n\t\t\tm_animations.emplace_back(\"\");\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::SameLine();\n\n\t\tif (ImGui::Button(\"-\"))\n\t\t{\n\t\t\tm_animations.pop_back();\n\t\t\tm_update = true;\n\t\t}\n\n\t\tImGui::TreePop();\n\t}\n\n\tm_update |= Renderable::OnImGui();\n\n\treturn m_update;\n}\n\nstd::type_index SkinnedMeshRenderer::GetType() const\n{\n\treturn typeid(SkinnedMeshRenderer);\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Components/Transform.cpp",
    "content": "#include \"Components/Transform.hpp\"\n\n#include <Scene/Node.hpp>\n\n#include <imgui.h>\n#include <imgui_internal.h>\n\n#include <glm/gtc/matrix_transform.hpp>\n#include <glm/gtc/quaternion.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nTransform::Transform(Node *node) :\n    Component(\"Transform\", node)\n{\n}\n\nbool Transform::OnImGui()\n{\n\tauto draw_vec3 =\n\t    [&](const std::string &label, glm::vec3 &values, float resetValue = 0.0f, float columnWidth = 100.0f) -> bool {\n\t\tImGuiIO &io        = ImGui::GetIO();\n\t\tauto     bold_font = io.Fonts->Fonts[0];\n\t\tbool     update    = false;\n\n\t\tImGui::PushID(label.c_str());\n\n\t\tImGui::Columns(2);\n\t\tImGui::SetColumnWidth(0, columnWidth);\n\t\tImGui::Text(label.c_str());\n\t\tImGui::NextColumn();\n\n\t\tImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());\n\t\tImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{0, 0});\n\n\t\tfloat  line_height = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f;\n\t\tImVec2 button_size = {line_height + 3.0f, line_height};\n\n\t\tImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.8f, 0.1f, 0.15f, 1.0f});\n\t\tImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{0.9f, 0.2f, 0.2f, 1.0f});\n\t\tImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.8f, 0.1f, 0.15f, 1.0f});\n\t\tImGui::PushFont(bold_font);\n\t\tif (ImGui::Button(\"X\", button_size))\n\t\t{\n\t\t\tvalues.x = resetValue;\n\t\t\tupdate   = true;\n\t\t}\n\t\tImGui::PopFont();\n\t\tImGui::PopStyleColor(3);\n\n\t\tImGui::SameLine();\n\t\tupdate |= ImGui::DragFloat(\"##X\", &values.x, 0.1f, 0.0f, 0.0f, \"%.3f\");\n\t\tImGui::PopItemWidth();\n\t\tImGui::SameLine();\n\n\t\tImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.2f, 0.7f, 0.2f, 1.0f});\n\t\tImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{0.3f, 0.8f, 0.3f, 1.0f});\n\t\tImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.2f, 0.7f, 0.2f, 1.0f});\n\t\tImGui::PushFont(bold_font);\n\t\tif (ImGui::Button(\"Y\", button_size))\n\t\t{\n\t\t\tvalues.y = resetValue;\n\t\t\tupdate   = true;\n\t\t}\n\t\tImGui::PopFont();\n\t\tImGui::PopStyleColor(3);\n\n\t\tImGui::SameLine();\n\t\tupdate |= ImGui::DragFloat(\"##Y\", &values.y, 0.1f, 0.0f, 0.0f, \"%.3f\");\n\t\tImGui::PopItemWidth();\n\t\tImGui::SameLine();\n\n\t\tImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.1f, 0.25f, 0.8f, 1.0f});\n\t\tImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{0.2f, 0.35f, 0.9f, 1.0f});\n\t\tImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.1f, 0.25f, 0.8f, 1.0f});\n\t\tImGui::PushFont(bold_font);\n\t\tif (ImGui::Button(\"Z\", button_size))\n\t\t{\n\t\t\tvalues.z = resetValue;\n\t\t\tupdate   = true;\n\t\t}\n\t\tImGui::PopFont();\n\t\tImGui::PopStyleColor(3);\n\n\t\tImGui::SameLine();\n\t\tupdate |= ImGui::DragFloat(\"##Z\", &values.z, 0.1f, 0.0f, 0.0f, \"%.3f\");\n\t\tImGui::PopItemWidth();\n\n\t\tImGui::PopStyleVar();\n\n\t\tImGui::Columns(1);\n\n\t\tImGui::PopID();\n\n\t\treturn update;\n\t};\n\n\tbool update = false;\n\n\tupdate |= draw_vec3(\"Translation\", m_translation, 0.f);\n\tupdate |= draw_vec3(\"Rotation\", m_rotation, 0.f);\n\tupdate |= draw_vec3(\"Scale\", m_scale, 1.f);\n\n\tif (update)\n\t{\n\t\tSetDirty();\n\t}\n\n\treturn update;\n}\n\nstd::type_index Transform::GetType() const\n{\n\treturn typeid(Transform);\n}\n\nvoid Transform::Save(OutputArchive &archive) const\n{\n\tarchive(m_translation, m_rotation, m_scale, m_world_transform);\n}\n\nvoid Transform::Load(InputArchive &archive)\n{\n\tarchive(m_translation, m_rotation, m_scale, m_world_transform);\n\tSetDirty();\n}\n\nconst glm::vec3 &Transform::GetTranslation() const\n{\n\treturn m_translation;\n}\n\nconst glm::vec3 &Transform::GetRotation() const\n{\n\treturn m_rotation;\n}\n\nconst glm::vec3 &Transform::GetScale() const\n{\n\treturn m_scale;\n}\n\nconst glm::mat4 Transform::GetLocalTransform() const\n{\n\treturn glm::scale(glm::translate(glm::mat4(1.f), m_translation) * glm::mat4_cast(glm::qua<float>(glm::radians(m_rotation))), m_scale);\n}\n\nconst glm::mat4 Transform::GetWorldTransform()\n{\n\tUpdate();\n\treturn m_world_transform;\n}\n\nvoid Transform::SetTranslation(const glm::vec3 &translation)\n{\n\tm_translation = translation;\n\tSetDirty();\n}\n\nvoid Transform::SetRotation(const glm::vec3 &rotation)\n{\n\tm_rotation = rotation;\n\tSetDirty();\n}\n\nvoid Transform::SetScale(const glm::vec3 &scale)\n{\n\tm_scale = scale;\n\tSetDirty();\n}\n\nvoid Transform::SetDirty()\n{\n\tm_update = true;\n\tif (!m_dirty)\n\t{\n\t\tm_dirty = true;\n\t\tfor (auto *child : p_node->GetChildren())\n\t\t{\n\t\t\tif (child->HasComponent<Transform>())\n\t\t\t{\n\t\t\t\tchild->GetComponent<Transform>()->SetDirty();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Transform::Update()\n{\n\tif (!m_dirty)\n\t{\n\t\treturn;\n\t}\n\n\tglm::mat4 local_matrix = GetLocalTransform();\n\n\tauto parent = GetNode()->GetParent();\n\n\tif (parent)\n\t{\n\t\tauto *transform   = parent->GetComponent<Transform>();\n\t\tm_world_transform = transform->GetWorldTransform() * local_matrix;\n\t}\n\telse\n\t{\n\t\tm_world_transform = local_matrix;\n\t}\n\n\tm_dirty = false;\n}\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Node.cpp",
    "content": "#include \"Node.hpp\"\n#include \"Component.hpp\"\n#include \"Scene.hpp\"\n\nnamespace Ilum\n{\nstruct Node::Impl\n{\n\tImpl(Scene &scene) :\n\t    scene(scene)\n\t{\n\t}\n\n\t~Impl() = default;\n\n\tScene &scene;\n\n\tsize_t id = ~0U;\n\n\tstd::string name;\n\n\tNode *parent = nullptr;\n\n\tstd::vector<Node *> children;\n\n\tstd::unordered_map<std::type_index, Component *> components;\n};\n\nNode::Node(size_t id, Scene &scene, const std::string &name)\n{\n\tm_impl       = new Impl(scene);\n\tm_impl->id   = id;\n\tm_impl->name = name;\n}\n\nNode::~Node()\n{\n\tfor (auto &child : m_impl->children)\n\t{\n\t\tchild->SetParent(nullptr);\n\t}\n\n\tif (m_impl->parent)\n\t{\n\t\tm_impl->parent->EraseChild(this);\n\t}\n\n\tfor (auto &[type, cmpt] : m_impl->components)\n\t{\n\t\tauto &scene_components = m_impl->scene.GetComponents()[type];\n\t\tfor (auto iter = scene_components.begin(); iter != scene_components.end(); iter++)\n\t\t{\n\t\t\tif (iter->get() == cmpt)\n\t\t\t{\n\t\t\t\tscene_components.erase(iter);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tdelete m_impl;\n}\n\nsize_t Node::GetID() const\n{\n\treturn m_impl->id;\n}\n\nvoid Node::SetName(const std::string &name)\n{\n\tm_impl->name = name;\n}\n\nconst std::string &Node::GetName() const\n{\n\treturn m_impl->name;\n}\n\nNode *Node::GetParent()\n{\n\treturn m_impl->parent;\n}\n\nScene &Node::GetScene()\n{\n\treturn m_impl->scene;\n}\n\nvoid Node::SetParent(Node *node)\n{\n\tif (m_impl->parent)\n\t{\n\t\tm_impl->parent->EraseChild(this);\n\t}\n\n\tm_impl->parent = node;\n\n\tif (m_impl->parent)\n\t{\n\t\tm_impl->parent->AddChild(this);\n\t}\n}\n\nconst std::vector<Node *> &Node::GetChildren() const\n{\n\treturn m_impl->children;\n}\n\nconst std::unordered_map<std::type_index, Component *> &Node::GetComponents() const\n{\n\treturn m_impl->components;\n}\n\nvoid Node::Save(OutputArchive &archive) const\n{\n\tarchive(m_impl->id, m_impl->name);\n}\n\nvoid Node::Load(InputArchive &archive)\n{\n\tarchive(m_impl->id, m_impl->name);\n}\n\nvoid Node::EraseChild(Node *node)\n{\n\tauto iter = std::find(m_impl->children.begin(), m_impl->children.end(), node);\n\tif (iter != m_impl->children.end())\n\t{\n\t\tm_impl->children.erase(iter);\n\t}\n}\n\nvoid Node::AddChild(Node *node)\n{\n\tm_impl->children.push_back(node);\n}\n\nbool Node::HasComponent_(std::type_index index)\n{\n\treturn m_impl->components.find(index) != m_impl->components.end();\n}\n\nComponent *Node::GetComponent_(std::type_index index)\n{\n\treturn HasComponent_(index) ? m_impl->components.at(index) : nullptr;\n}\n\nComponent *Node::AddComponent_(std::unique_ptr<Component> &&component)\n{\n\tauto &ptr = m_impl->scene.GetComponents()[component->GetType()].emplace_back(std::move(component));\n\tm_impl->components.emplace(ptr->GetType(), ptr.get());\n\treturn ptr.get();\n}\n\nvoid Node::AddComponent_(Component *component)\n{\n\tm_impl->components.emplace(component->GetType(), component);\n}\n\nvoid Node::EraseComponent(std::type_index index)\n{\n\tauto cmpt_iter = m_impl->components.find(index);\n\n\tif (cmpt_iter == m_impl->components.end())\n\t{\n\t\treturn;\n\t}\n\n\tauto &cmpt_list = m_impl->scene.GetComponents()[index];\n\n\tfor (auto iter = cmpt_list.begin(); iter != cmpt_list.end(); iter++)\n\t{\n\t\tif (iter->get() == cmpt_iter->second)\n\t\t{\n\t\t\tcmpt_list.erase(iter);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tm_impl->components.erase(cmpt_iter);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Private/Scene/Scene.cpp",
    "content": "#include \"Scene.hpp\"\n#include \"Component.hpp\"\n#include \"Components/AllComponents.hpp\"\n#include \"Node.hpp\"\n\nnamespace Ilum\n{\nstruct Scene::Impl\n{\n\tImpl() = default;\n\n\t~Impl()\n\t{\n\t\tnodes.clear();\n\t\tcomponents.clear();\n\t}\n\n\tstd::string name;\n\n\tstd::vector<std::unique_ptr<Node>> nodes;\n\n\tstd::unordered_map<std::type_index, std::vector<std::unique_ptr<Component>>> components;\n\n\tbool update = false;\n};\n\nScene::Scene(const std::string &name)\n{\n\tm_impl = new Impl;\n\n\tm_impl->name = name;\n}\n\nScene::~Scene()\n{\n\tauto roots = GetRoots();\n\tfor (auto &root : roots)\n\t{\n\t\tEraseNode(root);\n\t}\n\n\tdelete m_impl;\n\tm_impl = nullptr;\n}\n\nvoid Scene::SetName(const std::string &name)\n{\n\tm_impl->name = name;\n}\n\nconst std::string &Scene::GetName() const\n{\n\treturn m_impl->name;\n}\n\nconst std::vector<std::unique_ptr<Node>> &Scene::GetNodes() const\n{\n\treturn m_impl->nodes;\n}\n\nconst std::vector<Node *> Scene::GetRoots() const\n{\n\tstd::vector<Node *> roots;\n\troots.reserve(m_impl->nodes.size());\n\tfor (auto &node : m_impl->nodes)\n\t{\n\t\tif (node->GetParent() == nullptr)\n\t\t{\n\t\t\troots.emplace_back(node.get());\n\t\t}\n\t}\n\treturn roots;\n}\n\nNode *Scene::CreateNode(const std::string &name)\n{\n\treturn m_impl->nodes.emplace_back(std::make_unique<Node>(m_impl->nodes.empty() ? 0 : m_impl->nodes.back()->GetID() + 1, *this, name)).get();\n}\n\nvoid Scene::EraseNode(Node *node)\n{\n\tstd::function<void(Node *, std::vector<Node *> &)> gather_nodes = [&](Node *node, std::vector<Node *> &nodes) {\n\t\tnodes.push_back(node);\n\t\tfor (auto &child : node->GetChildren())\n\t\t{\n\t\t\tgather_nodes(child, nodes);\n\t\t}\n\t};\n\n\tstd::vector<Node *> remove_nodes;\n\tgather_nodes(node, remove_nodes);\n\tstd::reverse(remove_nodes.begin(), remove_nodes.end());\n\n\tfor (auto *remove_node : remove_nodes)\n\t{\n\t\tfor (auto iter = m_impl->nodes.begin(); iter != m_impl->nodes.end(); iter++)\n\t\t{\n\t\t\tif (iter->get() == remove_node)\n\t\t\t{\n\t\t\t\tm_impl->nodes.erase(iter);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nstd::unordered_map<std::type_index, std::vector<std::unique_ptr<Component>>> &Scene::GetComponents()\n{\n\treturn m_impl->components;\n}\n\nvoid Scene::Save(OutputArchive &archive)\n{\n\tarchive(m_impl->name);\n\n\t// Nodes\n\t{\n\t\tarchive(m_impl->nodes.size());\n\t\tfor (auto &node : m_impl->nodes)\n\t\t{\n\t\t\tnode->Save(archive);\n\t\t}\n\t\tfor (auto &node : m_impl->nodes)\n\t\t{\n\t\t\tarchive(node->GetParent() ? node->GetParent()->GetID() : ~0ull);\n\t\t}\n\t}\n\n\t// Components\n\t{\n\t\tarchive(m_impl->components.size());\n\t\tfor (auto &[type, components] : m_impl->components)\n\t\t{\n\t\t\tarchive(std::string(type.name()));\n\t\t\tarchive(components.size());\n\t\t\tfor (auto &component : components)\n\t\t\t{\n\t\t\t\tarchive(component->GetNode()->GetID());\n\t\t\t\tcomponent->Save(archive);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Scene::Load(InputArchive &archive)\n{\n\tarchive(m_impl->name);\n\n\tstd::unordered_map<size_t, Node *> node_map;\n\t// Nodes\n\t{\n\t\tm_impl->nodes.clear();\n\t\tsize_t node_count = 0;\n\t\tarchive(node_count);\n\t\tfor (size_t i = 0; i < node_count; i++)\n\t\t{\n\t\t\tstd::unique_ptr<Node> node = std::make_unique<Node>(0, *this);\n\t\t\tnode->Load(archive);\n\t\t\tm_impl->nodes.emplace_back(std::move(node));\n\t\t\tnode_map[m_impl->nodes.back()->GetID()] = m_impl->nodes.back().get();\n\t\t}\n\t\tfor (auto &node : m_impl->nodes)\n\t\t{\n\t\t\tsize_t parent = ~0ull;\n\t\t\tarchive(parent);\n\t\t\tif (parent != ~0ull)\n\t\t\t{\n\t\t\t\tnode->SetParent(node_map[parent]);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Components\n\t{\n\t\tconst std::unordered_map<std::string, std::function<void(Node *&, InputArchive &)>> load_component_map = {\n#define LOAD_COMPONENT(Cmpt)                                                                                                                   \\\n\t{                                                                                                                                          \\\n\t\ttypeid(Cmpt).name(), [](Node *&node, InputArchive &archive) { node->AddComponent<Cmpt>(std::make_unique<Cmpt>(node))->Load(archive); } \\\n\t}\n\n\t\t    LOAD_COMPONENT(Cmpt::Transform),\n\t\t    LOAD_COMPONENT(Cmpt::PerspectiveCamera),\n\t\t    LOAD_COMPONENT(Cmpt::OrthographicCamera),\n\t\t    LOAD_COMPONENT(Cmpt::MeshRenderer),\n\t\t    LOAD_COMPONENT(Cmpt::SkinnedMeshRenderer),\n\t\t    LOAD_COMPONENT(Cmpt::SpotLight),\n\t\t    LOAD_COMPONENT(Cmpt::PointLight),\n\t\t    LOAD_COMPONENT(Cmpt::DirectionalLight),\n\t\t    LOAD_COMPONENT(Cmpt::RectLight),\n\t\t    LOAD_COMPONENT(Cmpt::EnvironmentLight),\n\t\t};\n\n\t\tsize_t component_type_count = 0;\n\t\tarchive(component_type_count);\n\t\tfor (size_t i = 0; i < component_type_count; i++)\n\t\t{\n\t\t\tstd::string type_name = \"\";\n\t\t\tarchive(type_name);\n\t\t\tsize_t compoent_count = 0;\n\t\t\tarchive(compoent_count);\n\t\t\tfor (size_t j = 0; j < compoent_count; j++)\n\t\t\t{\n\t\t\t\tsize_t node_id = 0;\n\t\t\t\tarchive(node_id);\n\t\t\t\tNode *node = node_map[node_id];\n\t\t\t\tload_component_map.at(type_name)(node, archive);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Scene::Clear()\n{\n\tauto roots = GetRoots();\n\tfor (auto &root : roots)\n\t{\n\t\tEraseNode(root);\n\t}\n}\n\nbool Scene::IsUpdate() const\n{\n\treturn m_impl->update;\n}\n\nvoid Scene::Update(bool update)\n{\n\tif (update)\n\t{\n\t\tm_impl->update = true;\n\t}\n\telse\n\t{\n\t\tfor (auto &[type, cmpts] : m_impl->components)\n\t\t{\n\t\t\tfor (auto &cmpt : cmpts)\n\t\t\t{\n\t\t\t\tm_impl->update |= cmpt->IsUpdate();\n\t\t\t\tcmpt->SetUpdate(false);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid Scene::Reset()\n{\n\tm_impl->update = false;\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Component.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\n#include <string>\n#include <typeindex>\n\nnamespace Ilum\n{\nclass Node;\n\nclass EXPORT_API Component\n{\n  public:\n\tComponent(const char *name, Node *node);\n\n\tComponent(Component &&) = default;\n\n\tvirtual ~Component();\n\n\tvirtual bool OnImGui() = 0;\n\n\tvirtual std::type_index GetType() const = 0;\n\n\tconst char *GetName() const;\n\n\tNode *GetNode() const;\n\n\tvirtual void Save(OutputArchive &archive) const = 0;\n\n\tvirtual void Load(InputArchive &archive) = 0;\n\n\tbool IsUpdate();\n\n\tvoid SetUpdate(bool update);\n\n  protected:\n\tconst char *m_name;\n\n\tbool m_update = false;\n\n\tNode *p_node = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/AllComponents.hpp",
    "content": "#pragma once\n\n#include \"Camera/OrthographicCamera.hpp\"\n#include \"Camera/PerspectiveCamera.hpp\"\n#include \"Light/DirectionalLight.hpp\"\n#include \"Light/EnvironmentLight.hpp\"\n#include \"Light/PointLight.hpp\"\n#include \"Light/RectLight.hpp\"\n#include \"Light/SpotLight.hpp\"\n#include \"Renderable/MeshRenderer.hpp\"\n#include \"Renderable/SkinnedMeshRenderer.hpp\"\n#include \"Transform.hpp\"\n\nstruct ImGuiContext;\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nvoid SetImGuiContext(ImGuiContext *context);\n}\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Camera/Camera.hpp",
    "content": "#pragma once\n\n#include <Scene/Component.hpp>\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass Camera : public Component\n{\n  public:\n\tCamera(const char *name, Node *node);\n\n\tvirtual ~Camera() = default;\n\n\tvirtual bool OnImGui() override = 0;\n\n\tvirtual std::type_index GetType() const = 0;\n\n\tvirtual void Save(OutputArchive &archive) const = 0;\n\n\tvirtual void Load(InputArchive &archive) = 0;\n\n\tvoid SetAspect(float aspect);\n\n\tfloat GetAspect();\n\n\tvoid SetNearPlane(float near_plane);\n\n\tvoid SetFarPlane(float far_plane);\n\n\tfloat GetNearPlane() const;\n\n\tfloat GetFarPlane() const;\n\n\tglm::mat4 GetViewMatrix();\n\n\tglm::mat4 GetProjectionMatrix();\n\n\tglm::mat4 GetViewProjectionMatrix();\n\n\tglm::mat4 GetInvViewMatrix();\n\n\tglm::mat4 GetInvProjectionMatrix();\n\n\tglm::mat4 GetInvViewProjectionMatrix();\n\n\tconst std::array<glm::vec4, 6> &GetFrustumPlanes();\n\n  protected:\n\tvirtual void UpdateProjection() = 0;\n\n\tvoid UpdateView();\n\n  protected:\n\tfloat m_aspect = 1.f;\n\tfloat m_near   = 0.1f;\n\tfloat m_far    = 500.f;\n\n\tstd::array<glm::vec4, 6> m_frustum_planes;\n\n\tglm::mat4 m_view                = glm::mat4(1.f);\n\tglm::mat4 m_inv_view            = glm::mat4(1.f);\n\tglm::mat4 m_projection          = glm::mat4(1.f);\n\tglm::mat4 m_inv_projection      = glm::mat4(1.f);\n\tglm::mat4 m_view_projection     = glm::mat4(1.f);\n\tglm::mat4 m_inv_view_projection = glm::mat4(1.f);\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Camera/OrthographicCamera.hpp",
    "content": "#pragma once\n\n#include \"Camera.hpp\"\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass OrthographicCamera : public Camera\n{\n  public:\n\tOrthographicCamera(Node *node);\n\n\tvirtual ~OrthographicCamera() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvoid SetScale(float scale);\n\n\tvoid SetOffset(float x, float y);\n\n\tfloat GetScale() const;\n\n\tfloat GetOffsetX() const;\n\n\tfloat GetOffsetY() const;\n\n  protected:\n\tvirtual void UpdateProjection() override;\n\n  private:\n\tfloat m_scale    = 1.f;\n\tfloat m_offset_x = 0.f;\n\tfloat m_offset_y = 0.f;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Camera/PerspectiveCamera.hpp",
    "content": "#pragma once\n\n#include \"Camera.hpp\"\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass PerspectiveCamera : public Camera\n{\n  public:\n\tPerspectiveCamera(Node *node);\n\n\tvirtual ~PerspectiveCamera() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvoid SetFov(float fov);\n\n\tfloat GetFov() const;\n\n  protected:\n\tvirtual void UpdateProjection() override;\n\n  private:\n\tfloat m_fov   = 45.f;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Light/DirectionalLight.hpp",
    "content": "#pragma once\n\n#include \"Light.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass DirectionalLight : public Light\n{\n  public:\n\tDirectionalLight(Node *node);\n\n\tvirtual ~DirectionalLight() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tbool CastShadow() const;\n\n\tvoid SetShadowID(uint32_t &shadow_id);\n\n\tvirtual size_t GetDataSize() const override;\n\n\tvirtual void *GetData(Camera *camera = nullptr) override;\n\n  private:\n\tstruct\n\t{\n\t\tglm::vec3 color = glm::vec3(1.f);\n\n\t\tfloat intensity = 100.f;\n\n\t\tglm::vec4 split_depth;\n\t\tglm::mat4 view_projection[4];\n\t\tglm::vec4 shadow_cam_pos[4];\n\n\t\tglm::vec3 direction = glm::vec3(1.f);\n\n\t\tfloat    filter_scale  = 2.f;\n\t\tfloat    light_scale   = 1.f;\n\t\tuint32_t filter_sample = 10;\n\t\tuint32_t cast_shadow   = 1;\n\t\tuint32_t shadow_id     = ~0u;\n\t} m_data;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Light/EnvironmentLight.hpp",
    "content": "#pragma once\n\n#include \"Light.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass EnvironmentLight : public Light\n{\n  public:\n\tEnvironmentLight(Node *node);\n\n\tvirtual ~EnvironmentLight() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tvirtual size_t GetDataSize() const override;\n\n\tvirtual void *GetData(Camera *camera = nullptr) override;\n\n  private:\n\tstd::string m_texture = \"\";\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Light/Light.hpp",
    "content": "#pragma once\n\n#include <Scene/Component.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass Camera;\n\nclass Light : public Component\n{\n  public:\n\tLight(const char *name, Node *node);\n\n\tvirtual ~Light() = default;\n\n\tvirtual bool OnImGui() = 0;\n\n\tvirtual std::type_index GetType() const = 0;\n\n\tvirtual void Save(OutputArchive &archive) const = 0;\n\n\tvirtual void Load(InputArchive &archive) = 0;\n\n\tvirtual bool CastShadow() const;\n\n\tvirtual void SetShadowID(uint32_t &shadow_id);\n\n\t// GPU data size\n\tvirtual size_t GetDataSize() const = 0;\n\n\t// GPU data info\n\tvirtual void *GetData(Camera *camera = nullptr) = 0;\n\n  protected:\n\tvoid CalculateFrustum(const glm::mat4 &view_projection, std::array<glm::vec4, 6> &frustum);\n\n  private:\n\t// Shadow\n\tbool  m_shadow_enabled = true;\n\tfloat m_shadow_bias    = 0.1f;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Light/PointLight.hpp",
    "content": "#pragma once\n\n#include \"Light.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass PointLight : public Light\n{\n  public:\n\tPointLight(Node *node);\n\n\tvirtual ~PointLight() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tbool CastShadow() const;\n\n\tvoid SetShadowID(uint32_t &shadow_id);\n\n\tvirtual size_t GetDataSize() const override;\n\n\tvirtual void *GetData(Camera *camera = nullptr) override;\n\n  private:\n\tstruct\n\t{\n\t\tglm::vec3 color     = glm::vec3(1.f);\n\t\tfloat     intensity = 100.f;\n\n\t\tglm::vec3 position     = glm::vec3(0.f);\n\t\tfloat     filter_scale = 2.f;\n\n\t\talignas(16) float light_scale = 1.f;\n\t\tuint32_t filter_sample        = 10;\n\t\tuint32_t cast_shadow          = 1;\n\t\tuint32_t shadow_id            = ~0u;\n\t} m_data;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Light/RectLight.hpp",
    "content": "#pragma once\n\n#include \"Light.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass RectLight : public Light\n{\n  public:\n\tRectLight(Node *node);\n\n\tvirtual ~RectLight() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tvirtual size_t GetDataSize() const override;\n\n\tvirtual void *GetData(Camera *camera = nullptr) override;\n\n  private:\n\tstruct\n\t{\n\t\tglm::vec3 color = glm::vec3(1.f);\n\n\t\tfloat intensity = 100.f;\n\n\t\tglm::vec4 corner[4];\n\n\t\talignas(16) uint32_t texture_id = ~0U;\n\t\tuint32_t two_side               = 0;\n\t} m_data;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Light/SpotLight.hpp",
    "content": "#pragma once\n\n#include \"Light.hpp\"\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass SpotLight : public Light\n{\n  public:\n\tSpotLight(Node *node);\n\n\tvirtual ~SpotLight() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tbool CastShadow() const;\n\n\tvoid SetShadowID(uint32_t &shadow_id);\n\n\tvirtual size_t GetDataSize() const override;\n\n\tvirtual void *GetData(Camera *camera = nullptr) override;\n\n  private:\n\tstruct\n\t{\n\t\tglm::vec3 color = glm::vec3(1.f);\n\n\t\tfloat intensity = 100.f;\n\n\t\tglm::vec3 position = glm::vec3(0.f);\n\n\t\tfloat inner_angle = glm::radians(30.f);\n\n\t\tglm::vec3 direction = glm::vec3(0.f);\n\n\t\tfloat outer_angle = glm::radians(60.f);\n\n\t\tglm::mat4 view_projection = glm::mat4(1.f);\n\n\t\t// Shadow map setting\n\t\tfloat    filter_scale  = 2.f;\n\t\tfloat    light_scale   = 1.f;\n\t\tuint32_t filter_sample = 10;\n\t\tuint32_t cast_shadow   = 1;\n\n\t\talignas(16) uint32_t shadow_id = ~0u;\n\t} m_data;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Renderable/MeshRenderer.hpp",
    "content": "#pragma once\n\n#include \"Renderable.hpp\"\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass MeshRenderer : public Renderable\n{\n  public:\n\tMeshRenderer(Node *node);\n\n\tvirtual ~MeshRenderer() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual std::type_index GetType() const override;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Renderable/Renderable.hpp",
    "content": "#pragma once\n\n#include <Scene/Component.hpp>\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass Renderable : public Component\n{\n  public:\n\tRenderable(const char *name, Node *node);\n\n\tvirtual ~Renderable() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual std::type_index GetType() const = 0;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tvoid AddMaterial(const std::string &material);\n\n\tvoid AddSubmesh(const std::string &submesh);\n\n\tvoid AddAnimation(const std::string &animation);\n\n\tconst std::vector<std::string> &GetSubmeshes() const;\n\n\tconst std::vector<std::string> &GetMaterials() const;\n\n\tconst std::vector<std::string> &GetAnimations() const;\n\n  protected:\n\tstd::vector<std::string> m_submeshes;\n\tstd::vector<std::string> m_materials;\n\tstd::vector<std::string> m_animations;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Renderable/SkinnedMeshRenderer.hpp",
    "content": "#pragma once\n\n#include \"Renderable.hpp\"\n\nnamespace Ilum\n{\nnamespace Cmpt\n{\nclass SkinnedMeshRenderer : public Renderable\n{\n  public:\n\tSkinnedMeshRenderer(Node *node);\n\n\tvirtual ~SkinnedMeshRenderer() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual std::type_index GetType() const override;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Components/Transform.hpp",
    "content": "#pragma once\n\n#include <Scene/Component.hpp>\n\n#include <glm/glm.hpp>\n\nnamespace Ilum\n{\nclass Node;\n\nnamespace Cmpt\n{\nclass Transform : public Component\n{\n  public:\n\tTransform(Node *node);\n\n\t~Transform() = default;\n\n\tvirtual bool OnImGui() override;\n\n\tvirtual std::type_index GetType() const override;\n\n\tvirtual void Save(OutputArchive &archive) const override;\n\n\tvirtual void Load(InputArchive &archive) override;\n\n\tconst glm::vec3 &GetTranslation() const;\n\n\tconst glm::vec3 &GetRotation() const;\n\n\tconst glm::vec3 &GetScale() const;\n\n\tconst glm::mat4 GetLocalTransform() const;\n\n\tconst glm::mat4 GetWorldTransform();\n\n\tvoid SetTranslation(const glm::vec3 &translation);\n\n\tvoid SetRotation(const glm::vec3 &rotation);\n\n\tvoid SetScale(const glm::vec3 &scale);\n\n\tvoid SetDirty();\n\n  private:\n\tvoid Update();\n\n  private:\n\tglm::vec3 m_translation = {0.f, 0.f, 0.f};\n\tglm::vec3 m_rotation    = {0.f, 0.f, 0.f};\n\tglm::vec3 m_scale       = {1.f, 1.f, 1.f};\n\n\tglm::mat4 m_world_transform = glm::mat4(1.f);\n\n\tbool m_dirty = false;\n};\n}        // namespace Cmpt\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Node.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\n#include <memory>\n#include <string>\n#include <typeindex>\n#include <unordered_map>\n\nnamespace Ilum\n{\nclass Component;\nclass Scene;\n\nclass Node\n{\n  public:\n\tNode(size_t id, Scene &scene, const std::string &name = \"untitled node\");\n\n\t~Node();\n\n\tsize_t GetID() const;\n\n\tvoid SetName(const std::string &name);\n\n\tconst std::string &GetName() const;\n\n\tNode *GetParent();\n\n\tScene &GetScene();\n\n\tvoid SetParent(Node *node);\n\n\tconst std::vector<Node *> &GetChildren() const;\n\n\ttemplate <typename _Ty>\n\tbool HasComponent()\n\t{\n\t\treturn HasComponent_(typeid(_Ty));\n\t}\n\n\ttemplate <typename _Ty>\n\tvoid EraseComponent()\n\t{\n\t\treturn EraseComponent(typeid(_Ty));\n\t}\n\n\tvoid EraseComponent(std::type_index index);\n\n\ttemplate <typename _Ty, typename = std::is_base_of<Component, _Ty>>\n\t_Ty *GetComponent()\n\t{\n\t\treturn static_cast<_Ty *>(GetComponent_(typeid(_Ty)));\n\t}\n\n\ttemplate <typename _Ty, typename = std::is_base_of<Component, _Ty>>\n\t_Ty *AddComponent(std::unique_ptr<_Ty> &&component)\n\t{\n\t\treturn static_cast<_Ty *>(AddComponent_(std::move(component)));\n\t}\n\n\tconst std::unordered_map<std::type_index, Component *> &GetComponents() const;\n\n\tvoid Save(OutputArchive &archive) const;\n\n\tvoid Load(InputArchive &archive);\n\n  private:\n\tvoid EraseChild(Node *node);\n\n\tvoid AddChild(Node *node);\n\n\tbool HasComponent_(std::type_index index);\n\n\tComponent *GetComponent_(std::type_index index);\n\n\tComponent *AddComponent_(std::unique_ptr<Component> &&component);\n\n\tvoid AddComponent_(Component *component);\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/Scene/Public/Scene/Scene.hpp",
    "content": "#pragma once\n\n#include <Core/Core.hpp>\n\n#include <algorithm>\n#include <memory>\n#include <string>\n#include <typeindex>\n#include <unordered_map>\n#include <vector>\n\nnamespace Ilum\n{\nclass Node;\nclass Component;\nclass RHIContext;\n\nclass Scene\n{\n\tfriend class Node;\n\n  public:\n\tScene(const std::string &name = \"untitled scene\");\n\n\t~Scene();\n\n\tvoid SetName(const std::string &name);\n\n\tconst std::string &GetName() const;\n\n\tconst std::vector<std::unique_ptr<Node>> &GetNodes() const;\n\n\tconst std::vector<Node *> GetRoots() const;\n\n\ttemplate <typename _Ty>\n\tstd::vector<_Ty *> GetComponents()\n\t{\n\t\tstd::vector<_Ty *> result;\n\n\t\tif (HasComponent<_Ty>())\n\t\t{\n\t\t\tauto &scene_components = GetComponents().at(typeid(_Ty));\n\n\t\t\tstd::transform(scene_components.begin(), scene_components.end(), std::back_inserter(result),\n\t\t\t               [](const std::unique_ptr<Component> &component) -> _Ty * {\n\t\t\t\t               return static_cast<_Ty *>(component.get());\n\t\t\t               });\n\t\t}\n\n\t\treturn result;\n\t}\n\n\ttemplate <typename _Ty>\n\tbool HasComponent()\n\t{\n\t\treturn GetComponents().find(typeid(_Ty)) != GetComponents().end();\n\t}\n\n\tNode *CreateNode(const std::string &name = \"untitled node\");\n\n\tvoid EraseNode(Node *node);\n\n\tvoid Save(OutputArchive &archive);\n\n\tvoid Load(InputArchive &archive);\n\n\tvoid Clear();\n\n\tbool IsUpdate() const;\n\n\tvoid Update(bool update = false);\n\n\tvoid Reset();\n\n  private:\n\tstd::unordered_map<std::type_index, std::vector<std::unique_ptr<Component>>> &GetComponents();\n\n  private:\n\tstruct Impl;\n\tImpl *m_impl = nullptr;\n};\n}        // namespace Ilum"
  },
  {
    "path": "Source/Runtime/xmake.lua",
    "content": "add_runtime_moulde(\n    \"Core\",\n    \"Runtime\",\n    true, \n    {}, \n    {}\n)\n\ntarget(\"Core\")\n    add_packages(\"glfw\", \"spdlog\", \"glm\", \"cereal\", \"stb\", {public = true})\ntarget_end()\n\nadd_runtime_moulde(\n    \"RHI\", \n    \"Runtime\",\n    false, \n    {\"Core\"}, \n    {}\n)\n\nadd_runtime_moulde(\n    \"Geometry\", \n    \"Runtime\",\n    false, \n    {\"Core\"}, \n    {\"glm\"}\n)\n\nadd_runtime_moulde(\n    \"Scene\", \n    \"Runtime\",\n    false, \n    {\"Core\", \"ImGui-Tools\"},\n    {\"imgui\"}\n)\n\nadd_runtime_moulde(\n    \"Resource\", \n    \"Runtime\",\n    false, \n    {\"Core\", \"RHI\", \"Geometry\", \"Material\", \"RenderGraph\", \"ShaderCompiler\", \"Scene\"}, \n    {\"imgui\", \"meshoptimizer\", \"mustache\"}\n)\n\n-- Render\nincludes(\"Render\")"
  },
  {
    "path": "Source/Shaders/AmbientOcclusion/RayTracedAO.hlsl",
    "content": ""
  },
  {
    "path": "Source/Shaders/AmbientOcclusion/SSAO.hlsl",
    "content": "#include \"../Common.hlsli\"\n#include \"../Random.hlsli\"\n\n#define KERNAL_SIZE 64\n#define RADIUS 0.5\n#define NOISE_DIM 4\n\nstruct Sample\n{\n    float4 samples[KERNAL_SIZE];\n};\n\nTexture2D<float4> Normal;\nTexture2D<float4> PositionDepth;\nRWTexture2D<float> SSAOMap;\nSamplerState TexSampler;\nConstantBuffer<View> ViewBuffer;\nTexture2D<float4> NoiseTexture;\nConstantBuffer<Sample> SampleBuffer;\n\n[numthreads(8, 8, 1)]\nvoid SSAO(CSParam param)\n{\n    uint2 extent;\n    SSAOMap.GetDimensions(extent.x, extent.y);\n    \n    if (param.DispatchThreadID.x >= extent.x ||\n        param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    float2 uv = (float2(param.DispatchThreadID.xy) + 0.5f) / float2(extent);\n    \n    float3 position = PositionDepth[param.DispatchThreadID.xy].rgb;\n    \n    if (IsBlack(position))\n    {\n        SSAOMap[param.DispatchThreadID.xy] = 1.f;\n        return;\n    }\n    \n    position = mul(ViewBuffer.view_matrix, float4(position, 1.f)).xyz;\n    float3 normal = Normal[param.DispatchThreadID.xy].rgb * 2.f - 1.f;\n    normal = mul((float3x3) ViewBuffer.view_matrix, normal).xyz;\n    \n    PCGSampler rng;\n    rng.Init(extent, param.DispatchThreadID.xy, 0);\n    \n    uint2 noise_extent;\n    NoiseTexture.GetDimensions(noise_extent.x, noise_extent.y);\n    \n    const float2 noise_uv = float2(float(extent.x) / float(noise_extent.x), float(extent.y) / (noise_extent.y)) * uv;\n    float3 random_vec = NoiseTexture.SampleLevel(TexSampler, noise_uv, 0).xyz * 2.0 - 1.0;\n    \n    float3 tangent = normalize(random_vec - normal * dot(random_vec, normal));\n    float3 bitangent = cross(tangent, normal);\n    float3x3 TBN = transpose(float3x3(tangent, bitangent, normal));\n    \n    float occlusion = 0.f;\n    \n    for (uint i = 0; i < KERNAL_SIZE; i++)\n    {\n        float3 sample_pos = mul(TBN, SampleBuffer.samples[i].xyz);\n        sample_pos = position + sample_pos * RADIUS;\n        \n        float4 offset = float4(sample_pos, 1.f);\n        offset = mul(ViewBuffer.projection_matrix, offset);\n        offset.y = -offset.y;\n        offset.xyz /= offset.w;\n        offset.xyz = offset.xyz * 0.5f + 0.5f;\n\n        float sample_depth = PositionDepth.SampleLevel(TexSampler, offset.xy, 0).w;\n        float range = smoothstep(0.f, 1.f, RADIUS / abs(position.z - sample_depth));\n        \n        occlusion += (sample_depth >= sample_pos.z ? 1.0f : 0.0f) * range;\n    }\n    occlusion = 1.f - (occlusion / float(KERNAL_SIZE));\n    SSAOMap[param.DispatchThreadID.xy] = occlusion;\n}\n\ngroupshared float cache[8][8];\n\n[numthreads(8, 8, 1)]\nvoid SSAOBlur(CSParam param)\n{\n    uint2 extent;\n    SSAOMap.GetDimensions(extent.x, extent.y);\n    \n    if (param.DispatchThreadID.x >= extent.x ||\n        param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    float sum = 0;\n    uint idx = 0;\n    for (int i = -1; i <= 1; i++)\n    {\n        for (int j = -1; j <= 1; j++)\n        {\n            sum += SSAOMap[int2(clamp(param.DispatchThreadID.x + i, 0, extent.x), clamp(param.DispatchThreadID.y + j, 0, extent.y))];\n        }\n    }\n    \n    cache[param.GroupThreadID.x][param.GroupThreadID.y] = sum;\n    \n    GroupMemoryBarrierWithGroupSync();\n\n    // Mean filter\n    SSAOMap[param.GroupThreadID.xy] = cache[param.GroupThreadID.x][param.GroupThreadID.y] / 9.f;\n}"
  },
  {
    "path": "Source/Shaders/Attribute.hlsli",
    "content": "#ifndef ATTRIBUTE_HLSLI\n#define ATTRIBUTE_HLSLI\n\nstruct InstanceAttribute\n{\n    float instance_id;\n    float material_id;\n    float primitive_id;\n};\n\nstruct VertexAttribute\n{\n    float3 position;\n    float3 normal;\n    float3 tangent;\n    float3 texcoord0;\n    float3 texcoord1;\n};\n\nstatic InstanceAttribute instance_attribute;\nstatic VertexAttribute vertex_attribute;\n\n#endif"
  },
  {
    "path": "Source/Shaders/Common.hlsli",
    "content": "#ifndef COMMON_HLSLI\n#define COMMON_HLSLI\n\n#include \"Math.hlsli\"\n\n#define MAX_BONE_INFLUENCE 8\n\n#define MESH_TYPE 0\n#define SKINNED_MESH_TYPE 1\n\nstruct DrawIndirectCommand\n{\n    uint vertex_count;\n    uint instance_count;\n    uint vertex_offset;\n    uint instance_offset;\n};\n\nstruct DrawIndexedIndirectCommand\n{\n    uint index_count;\n    uint instance_count;\n    uint index_offset;\n    int vertex_offset;\n    uint instance_offset;\n};\n\nstruct DispatchIndirectCommand\n{\n    uint x;\n    uint y;\n    uint z;\n};\n\nstruct DrawMeshTasksIndirectCommand\n{\n    uint group_count_x;\n    uint group_count_y;\n    uint group_count_z;\n};\n\nstruct Vertex\n{\n    float3 position;\n    float3 normal;\n    float3 tangent;\n    float2 texcoord0;\n    float2 texcoord1;\n};\n\nstruct SkinnedVertex\n{\n    float3 position;\n    float3 normal;\n    float3 tangent;\n\n    float2 texcoord0;\n    float2 texcoord1;\n\n    int bones[8];\n    float weights[8];\n};\n\nstruct Meshlet\n{\n    float3 center;\n    float radius;\n\n    uint data_offset;\n    uint vertex_offset;\n    uint vertex_count;\n    uint triangle_count;\n    \n    float3 cone_axis;\n    float cone_cutoff;\n    float3 cone_apex;\n    \n    uint visible;\n};\n\nstruct Instance\n{\n    float4x4 transform;\n\n    uint mesh_id;\n    uint material_id;\n    uint animation_id;\n    uint visible;\n};\n\nstruct RayDiff\n{\n    float3 dOdx;\n    float3 dOdy;\n    float3 dDdx;\n    float3 dDdy;\n    \n    void Propagate(float3 direction, float t, float3 normal)\n    {\n        float3 dodx = dOdx + t * dDdx;\n        float3 dody = dOdy + t * dDdy;\n\n        float rcpDN = 1.0f / dot(direction, normal);\n        float dtdx = -dot(dodx, normal) * rcpDN;\n        float dtdy = -dot(dody, normal) * rcpDN;\n        dodx += direction * dtdx;\n        dody += direction * dtdy;\n\n        dOdx = dodx;\n        dOdy = dody;\n    }\n};\n\nbool IsInsideFrustum(Meshlet meshlet, float4x4 model, float4 frustum[6], float3 eye)\n{\n    float sx = length(float3(model[0][0], model[0][1], model[0][2]));\n    float sy = length(float3(model[1][0], model[1][1], model[1][2]));\n    float sz = length(float3(model[2][0], model[2][1], model[2][2]));\n        \n    float3 radius = meshlet.radius * float3(sx, sy, sz);\n    float3 center = mul(model, float4(meshlet.center, 1.0)).xyz;\n        \n        // Frustum Culling\n    for (uint i = 0; i < 6; i++)\n    {\n        if (dot(frustum[i], float4(center, 1)) + length(radius) < 0.0)\n        {\n            return false;\n        }\n    }\n        \n    // Cone Culling\n    float3 cone_apex = mul(model, float4(meshlet.cone_apex, 1.0)).xyz;\n        \n    float3x3 rotation = float3x3(\n            model[0].xyz / sx,\n            model[1].xyz / sy,\n            model[2].xyz / sz\n        );\n\n    float3 cone_axis = mul(rotation, meshlet.cone_axis);\n    float result = dot(normalize(mul(model, float4(meshlet.cone_apex, 1.0)).xyz - eye), cone_axis);\n    return result < meshlet.cone_cutoff || result > 0.f;\n}\n\nbool IsInsideFrustum(Meshlet meshlet, float4x4 model, float4 frustum[6], float3 eye, float3 offset)\n{\n    float sx = length(float3(model[0][0], model[0][1], model[0][2]));\n    float sy = length(float3(model[1][0], model[1][1], model[1][2]));\n    float sz = length(float3(model[2][0], model[2][1], model[2][2]));\n        \n    float3 radius = meshlet.radius * float3(sx, sy, sz);\n    float3 center = mul(model, float4(meshlet.center, 1.0)).xyz - offset;\n        \n        // Frustum Culling\n    for (uint i = 0; i < 6; i++)\n    {\n        if (dot(frustum[i], float4(center, 1)) + length(radius) < 0.0)\n        {\n            return false;\n        }\n    }\n        \n    // Cone Culling\n    float3 cone_apex = mul(model, float4(meshlet.cone_apex, 1.0)).xyz - offset;\n        \n    float3x3 rotation = float3x3(\n            model[0].xyz / sx,\n            model[1].xyz / sy,\n            model[2].xyz / sz\n        );\n\n    float3 cone_axis = mul(rotation, meshlet.cone_axis);\n    float result = dot(normalize(mul(model, float4(meshlet.cone_apex, 1.0)).xyz - eye) - offset, cone_axis);\n    return result < meshlet.cone_cutoff || result > 0.f;\n}\n\nstruct View\n{\n    float4 frustum[6];\n    float4x4 view_matrix;\n    float4x4 inv_view_matrix;\n    float4x4 projection_matrix;\n    float4x4 inv_projection_matrix;\n    float4x4 view_projection_matrix;\n    float4x4 inv_view_projection_matrix;\n    float3 position;\n    uint frame_count;\n    float2 viewport;\n    \n    bool IsVisible(Meshlet meshlet, float4x4 model)\n    {\n        return IsInsideFrustum(meshlet, model, frustum, position);\n    }\n    \n    void CastRay(float2 scene_uv, float2 frame_dim, out RayDesc ray, out RayDiff ray_diff)\n    {\n        float yaw = atan2(-view_matrix[2][2], -view_matrix[0][2]);\n        float pitch = asin(-clamp(view_matrix[1][2], -1.f, 1.f));\n        float3 forward = normalize(float3(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));\n        float3 right = normalize(cross(forward, float3(0, 1, 0)));\n        float3 up = normalize(cross(right, forward));\n        float3 target = mul(inv_projection_matrix, float4(scene_uv.x, scene_uv.y, 1, 1)).xyz;\n\n        ray.Origin = mul(inv_view_matrix, float4(0, 0, 0, 1)).xyz;\n        ray.Direction = normalize(mul(inv_view_matrix, float4(target, 0)).xyz);\n        ray.TMin = 0.0;\n        ray.TMax = Infinity;\n\n        float3 dir = forward + right * scene_uv.x + up * scene_uv.y;\n        ray_diff.dOdx = 0;\n        ray_diff.dOdy = 0;\n        float dd = dot(dir, dir);\n        float divd = 2.0f / (dd * sqrt(dd));\n        float dr = dot(dir, right);\n        float du = dot(dir, up);\n        ray_diff.dDdx = ((dd * right) - (dr * dir)) * divd / frame_dim.x;\n        ray_diff.dDdy = -((dd * up) - (du * dir)) * divd / frame_dim.y;\n    }\n};\n\nstruct CSParam\n{\n    uint3 DispatchThreadID : SV_DispatchThreadID;\n    uint3 GroupThreadID : SV_GroupThreadID;\n    uint3 GroupID : SV_GroupID;\n    uint GroupIndex : SV_GroupIndex;\n};\n\nvoid UnPackTriangle(uint encode, out uint v0, out uint v1, out uint v2)\n{\n    v0 = encode & 0xff;\n    v1 = (encode >> 8) & 0xff;\n    v2 = (encode >> 16) & 0xff;\n}\n\nuint PackVisibilityBuffer(uint mesh_type, uint instance_id, uint primitive_id)\n{\n    // Mesh Type 1\n    // Instance ID 8\n    // Primitive ID 23\n    uint vbuffer = 0;\n    vbuffer += mesh_type & 0x1;\n    vbuffer += (instance_id & 0xff) << 1;\n    vbuffer += (primitive_id & 0x7fffff) << 9;\n    return vbuffer;\n}\n\nvoid UnPackVisibilityBuffer(uint visibility_buffer, out uint mesh_type, out uint instance_id, out uint primitive_id)\n{\n    // Mesh Type 1\n    // Instance ID 8\n    // Primitive ID 23\n    mesh_type = visibility_buffer & 0x1;\n    instance_id = (visibility_buffer >> 1) & 0xff;\n    primitive_id = (visibility_buffer >> 9) & 0x7fffff;\n}\n\nuint PackXY(uint x, uint y)\n{\n    return (x & 0xffff) + ((y & 0xffff) << 16);\n}\n\nvoid UnpackXY(uint xy, out uint x, out uint y)\n{\n    x = xy & 0xffff;\n    y = (xy >> 16) & 0xffff;\n}\n\nfloat Luminance(float3 color)\n{\n    return dot(color, float3(0.2126f, 0.7152f, 0.0722f)); //color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;\n}\n\nvoid CalculateFrustum(float4x4 view_projection, out float4 frustum[6])\n{\n    view_projection = transpose(view_projection);\n    \n\t// Left\n    frustum[0].x = view_projection[0].w + view_projection[0].x;\n    frustum[0].y = view_projection[1].w + view_projection[1].x;\n    frustum[0].z = view_projection[2].w + view_projection[2].x;\n    frustum[0].w = view_projection[3].w + view_projection[3].x;\n\n\t// Right\n    frustum[1].x = view_projection[0].w - view_projection[0].x;\n    frustum[1].y = view_projection[1].w - view_projection[1].x;\n    frustum[1].z = view_projection[2].w - view_projection[2].x;\n    frustum[1].w = view_projection[3].w - view_projection[3].x;\n\n\t// Top\n    frustum[2].x = view_projection[0].w - view_projection[0].y;\n    frustum[2].y = view_projection[1].w - view_projection[1].y;\n    frustum[2].z = view_projection[2].w - view_projection[2].y;\n    frustum[2].w = view_projection[3].w - view_projection[3].y;\n\n\t// Bottom\n    frustum[3].x = view_projection[0].w + view_projection[0].y;\n    frustum[3].y = view_projection[1].w + view_projection[1].y;\n    frustum[3].z = view_projection[2].w + view_projection[2].y;\n    frustum[3].w = view_projection[3].w + view_projection[3].y;\n\n\t// Near\n    frustum[4].x = view_projection[0].w + view_projection[0].z;\n    frustum[4].y = view_projection[1].w + view_projection[1].z;\n    frustum[4].z = view_projection[2].w + view_projection[2].z;\n    frustum[4].w = view_projection[3].w + view_projection[3].z;\n\n\t// Far\n    frustum[5].x = view_projection[0].w - view_projection[0].z;\n    frustum[5].y = view_projection[1].w - view_projection[1].z;\n    frustum[5].z = view_projection[2].w - view_projection[2].z;\n    frustum[5].w = view_projection[3].w - view_projection[3].z;\n\n    for (uint i = 0; i < 6; i++)\n    {\n        float len = length(frustum[i].xyz);\n        frustum[i] /= len;\n    }\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/Complex.hlsli",
    "content": "#ifndef COMPLEX_HLSLI\n#define COMPLEX_HLSLI\n\nstruct Complex\n{\n    float re;\n    float im;\n};\n\nComplex CreateComplex(float re, float im)\n{\n    Complex result;\n    result.re = re;\n    result.im = im;\n    return result;\n}\n\nComplex ComplexFromReal(float x)\n{\n    Complex result;\n    result.re = x;\n    result.im = 0;\n    return result;\n}\n\nComplex Add(Complex lhs, Complex rhs)\n{\n    Complex result;\n    result.re = lhs.re + rhs.re;\n    result.im = lhs.im + rhs.im;\n    return result;\n}\n\nComplex Sub(Complex lhs, Complex rhs)\n{\n    Complex result;\n    result.re = lhs.re - rhs.re;\n    result.im = lhs.im - rhs.im;\n    return result;\n}\n\nComplex Mul(Complex lhs, Complex rhs)\n{\n    Complex result;\n    float a = lhs.re;\n    float b = lhs.im;\n    float c = rhs.re;\n    float d = rhs.im;\n    \n    result.re = a * c - b * d;\n    result.im = a * d + b * c;\n    \n    return result;\n}\n\nComplex Div(Complex lhs, Complex rhs)\n{\n    Complex result;\n    float a = lhs.re;\n    float b = lhs.im;\n    float c = rhs.re;\n    float d = rhs.im;\n    \n    float s = rhs.re * rhs.re + rhs.im * rhs.im;\n    result.re = (a * c + b * d) / s;\n    result.im = (b * c - a * d) / s;\n    \n    return result;\n}\n\nfloat Norm(Complex x)\n{\n    return x.re * x.re + x.im * x.im;\n}\n\nfloat Abs(Complex x)\n{\n    return sqrt(Norm(x));\n}\n\nComplex Sqrt(Complex x)\n{\n    Complex result;\n    \n    float n = Abs(x);\n    float t1 = sqrt(0.5 * (n + abs(x.re)));\n    float t2 = 0.5 * x.im / t1;\n\n    if (n == 0)\n    {\n        return ComplexFromReal(0);\n    }\n\n    if (x.re >= 0)\n    {\n        return CreateComplex(t1, t2);\n    }\n    else\n    {\n        return CreateComplex(abs(t2), sign(t1) * x.im);\n    }\n    \n    return ComplexFromReal(0);\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/Editor/AnimationEditor/DrawSkeleton.hlsl",
    "content": "struct VSInput\n{\n    float3 Position : POSITIONT0;\n    uint BoneID : BLENDINDICES0;\n};\n\nstruct UniformBlock\n{\n    float4x4 transform;\n};\n\nConstantBuffer<UniformBlock> UniformBuffer;\nStructuredBuffer<float4x4> BoneMatrices;\n\nstruct VSOutput\n{\n    float4 Position : SV_Position;\n    float4 Color : COLOR0;\n};\n\nuint Hash(uint a)\n{\n    a = (a + 0x7ed55d16) + (a << 12);\n    a = (a ^ 0xc761c23c) ^ (a >> 19);\n    a = (a + 0x165667b1) + (a << 5);\n    a = (a + 0xd3a2646c) ^ (a << 9);\n    a = (a + 0xfd7046c5) + (a << 3);\n    a = (a ^ 0xb55a4f09) ^ (a >> 16);\n    return a;\n}\n\nfloat4 GenerateColor(uint a)\n{\n    uint hash = Hash(a);\n    return float4(float3(float(hash & 255), float((hash >> 8) & 255), float((hash >> 16) & 255)) / 255.0, 1.0);\n}\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    //output.Position = mul(UniformBuffer.transform, mul(BoneMatrices[input.BoneID], float4(input.Position, 1.0f)));\n    output.Position = mul(UniformBuffer.transform, mul(BoneMatrices[input.BoneID], float4(input.Position, 1.0f)));\n    output.Color = GenerateColor(input.BoneID);\n    return output;\n}\n\nstruct PSInput\n{\n    float4 Color : COLOR0;\n};\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n    return input.Color;\n}\n"
  },
  {
    "path": "Source/Shaders/Editor/AnimationEditor.hlsl",
    "content": "#define MAX_BONE_INFLUENCE 8\n\nstruct VSInput\n{\n    float3 Position : POSITIONT0;\n    int4 BoneID0 : BLENDINDICES0;\n    int4 BoneID1 : BLENDINDICES1;\n    float4 BoneWeight0 : BLENDWEIGHT0;\n    float4 BoneWeight1 : BLENDWEIGHT1;\n};\n\nstruct UniformBlock\n{\n    float4x4 transform;\n};\n\nConstantBuffer<UniformBlock> UniformBuffer;\nStructuredBuffer<float4x4> BoneMatrices;\n\nstruct VSOutput\n{\n    float4 Position : SV_Position;\n    float4 Color : COLOR0;\n};\n\nuint Hash(uint a)\n{\n    a = (a + 0x7ed55d16) + (a << 12);\n    a = (a ^ 0xc761c23c) ^ (a >> 19);\n    a = (a + 0x165667b1) + (a << 5);\n    a = (a + 0xd3a2646c) ^ (a << 9);\n    a = (a + 0xfd7046c5) + (a << 3);\n    a = (a ^ 0xb55a4f09) ^ (a >> 16);\n    return a;\n}\n\nfloat4 GenerateColor(uint a)\n{\n    uint hash = Hash(a);\n    return float4(float3(float(hash & 255), float((hash >> 8) & 255), float((hash >> 16) & 255)) / 255.0, 1.0);\n}\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    \n    uint bone_count = 0;\n    uint bone_stride = 0;\n    BoneMatrices.GetDimensions(bone_count, bone_stride);\n    \n    float4 total_position = 0.f;\n    for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n    {\n        int bone = -1;\n        float weight = 0.f;\n        \n        if (i < 4)\n        {\n            bone = input.BoneID0[i];\n            weight = input.BoneWeight0[i];\n        }\n        else\n        {\n            bone = input.BoneID1[i - 4];\n            weight = input.BoneWeight1[i - 4];\n        }\n        \n        if (bone == -1)\n        {\n            continue;\n        }\n        \n        if (bone >= bone_count)\n        {\n            total_position = float4(input.Position, 1.0f);\n            break;\n        }\n        \n        float4 local_position = mul(BoneMatrices[bone], float4(input.Position, 1.0f));\n        total_position += local_position * weight;\n    }\n        \n    output.Position = mul(UniformBuffer.transform, total_position);\n    output.Color = GenerateColor(input.BoneID0[0]);\n    return output;\n}\n\nstruct PSInput\n{\n    float4 Color : COLOR0;\n};\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n    return input.Color;\n}\n"
  },
  {
    "path": "Source/Shaders/Editor/MaterialEditor.hlsl",
    "content": "#ifndef USE_MATERIAL\n#include \"Material/Material.hlsli\"\n#endif\n#include \"Tonemapper.hlsli\"\n\nstruct VSInput\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n};\n\nstruct UniformBlock\n{\n    float4x4 transform;\n    float4x4 model;\n    float3 camera_pos;\n    uint material_id;\n};\n\nConstantBuffer<UniformBlock> UniformBuffer;\n\nstruct VSOutput\n{\n    float4 Position_ : SV_Position;\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord : TEXCOORD0;\n};\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    output.Position_ = mul(UniformBuffer.transform, mul(UniformBuffer.model, float4(input.Position, 1.f)));\n    output.Position = output.Position_.xyz/output.Position_.w;\n    output.Normal = normalize(mul((float3x3) UniformBuffer.model, input.Normal));\n    output.Tangent = normalize(mul((float3x3) UniformBuffer.model, input.Tangent));\n    output.Texcoord = input.Texcoord0;\n    return output;\n}\n\nstruct PSInput\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord : TEXCOORD0;\n};\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n    SurfaceInteraction surface_interaction;\n    surface_interaction.isect.p = input.Position;\n    surface_interaction.isect.n = input.Normal;\n    surface_interaction.isect.nt = input.Tangent;\n    surface_interaction.isect.uv = input.Texcoord;\n    surface_interaction.duvdx = ddx(input.Texcoord);\n    surface_interaction.duvdy = ddy(input.Texcoord);\n    surface_interaction.material = UniformBuffer.material_id;\n    \n    Material material;\n    material.Init(surface_interaction);\n    \n    float3 wo = normalize(UniformBuffer.camera_pos - surface_interaction.isect.p);\n    float3 wi = normalize(float3(0.f, 1.f, 3.f) - surface_interaction.isect.p);\n    float intensity = 1.5f;\n    \n    float3 color = (material.bsdf.Eval(wo, wi, TransportMode_Radiance) * abs(dot(wo, input.Normal)) + material.bsdf.GetGBufferData().emissive) * intensity;\n    return float4(ToneMapUncharted(color), 1.f);\n}\n"
  },
  {
    "path": "Source/Shaders/Editor/MeshEditor.hlsl",
    "content": "//#define SHADING\n//#define DRAW_NORMAL\n//#define DRAW_UV\n//#define DRAW_TEXTURE\n//#define WIREFRAME\n\nstruct VSInput\n{\n    float3 Position : POSITIONT0;\n#if !defined(DRAW_UV) && !defined(WIREFRAME)\n    float3 Normal : NORMAL0;\n#endif\n#if defined(DRAW_UV) || defined(DRAW_TEXTURE)\n    float2 UV : TEXCOORD0;\n#endif\n};\n\nstruct UniformBlock\n{\n    float4x4 transform;\n    float3 color;\n    float3 direction;\n};\n\nTexture2D UVTexture;\nSamplerState UVSampler;\nConstantBuffer<UniformBlock> UniformBuffer;\n\nstruct VSOutput\n{\n    float4 Position : SV_Position;\n#if !defined(DRAW_UV) && !defined(WIREFRAME)\n    float3 Normal : NORMAL0;\n#endif\n#if defined(DRAW_UV) || defined(DRAW_TEXTURE)\n    float2 UV : TEXCOORD0;\n#endif\n};\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n#if defined(DRAW_UV) || defined(DRAW_TEXTURE)\n    output.UV = input.UV;\n#endif\n    output.Position = mul(UniformBuffer.transform, float4(input.Position, 1.0f));\n#if !defined(DRAW_UV) && !defined(WIREFRAME)\n    output.Normal = input.Normal;\n#endif\n    return output;\n}\n\nstruct PSInput\n{\n#if !defined(DRAW_UV) && !defined(WIREFRAME)\n    float3 Normal : NORMAL0;\n#endif\n#if defined(DRAW_UV) || defined(DRAW_TEXTURE)\n    float2 UV : TEXCOORD0;\n#endif\n};\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n#ifdef SHADING\n    float3 ambient = 0.3f;\n    float3 norm = normalize(input.Normal);\n\n    float3 diffuse = max(dot(norm, UniformBuffer.direction), 0.0);\n    \n    float3 reflect_dir = reflect(-UniformBuffer.direction, norm);\n    float specular = pow(max(dot(UniformBuffer.direction, reflect_dir), 0.0), 3.f);\n    return float4((ambient + diffuse + specular) * UniformBuffer.color, 1.0f);\n#endif\n    \n#ifdef DRAW_NORMAL\n    return float4(input.Normal, 1.0f);\n#endif\n    \n#ifdef DRAW_UV\n    return float4(input.UV, 0.f, 1.0f);\n#endif\n    \n#ifdef DRAW_TEXTURE\n    float3 ambient = 0.3f;\n    float3 norm = normalize(input.Normal);\n    float3 texture_color = UVTexture.Sample(UVSampler, input.UV).rgb;\n\n    float3 diffuse = max(dot(norm, UniformBuffer.direction), 0.0);\n    \n    float3 reflect_dir = reflect(-UniformBuffer.direction, norm);\n    float specular = pow(max(dot(UniformBuffer.direction, reflect_dir), 0.0), 3.f);\n    return float4((ambient + diffuse + specular) * texture_color, 1.0f);\n#endif\n    \n#ifdef WIREFRAME\n    return float4(0.f, 0.f, 0.f, 1.f);\n#endif\n}\n"
  },
  {
    "path": "Source/Shaders/Editor/Preview/Material.hlsl",
    "content": "#ifndef USE_MATERIAL\n#include \"../../Material/Material.hlsli\"\n#endif\n#include \"../../Tonemapper.hlsli\"\n\n#ifndef RUNTIME\n#define MATERIAL_ID 0\n#endif\n\nstruct VSInput\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    uint InstanceID : SV_InstanceID;\n};\n\nstruct VSOutput\n{\n    float4 Position_ : SV_Position;\n    float3 Position : POSITION0;\n    float3 Tangent : TANGENT0;\n    float3 Normal : NORMAL0;\n    float2 Texcoord : TEXCOORD0;\n};\n\nstruct PSInput\n{\n    float3 Position : POSITION0;\n    float3 Tangent : TANGENT0;\n    float3 Normal : NORMAL0;\n    float2 Texcoord : TEXCOORD0;\n};\n\nstruct UniformBlock\n{\n    float4x4 transform;\n    float4x4 model;\n};\n\nConstantBuffer<UniformBlock> UniformBuffer;\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    output.Position_ = mul(UniformBuffer.transform, mul(UniformBuffer.model, float4(input.Position, 1.f)));\n    output.Position = output.Position_.xyz / output.Position_.w;\n    output.Normal = normalize(mul((float3x3) UniformBuffer.model, input.Normal));\n    output.Tangent = normalize(mul((float3x3) UniformBuffer.model, input.Tangent));\n    output.Texcoord = input.Texcoord0;\n    return output;\n}\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n    SurfaceInteraction surface_interaction;\n    surface_interaction.isect.p = input.Position;\n    surface_interaction.isect.n = input.Normal;\n    surface_interaction.isect.n = input.Normal;\n    surface_interaction.isect.nt = input.Tangent;\n    surface_interaction.isect.uv = input.Texcoord;\n    surface_interaction.duvdx = ddx(input.Texcoord);\n    surface_interaction.duvdy = ddy(input.Texcoord);\n    surface_interaction.material = MATERIAL_ID;\n    \n    Material material;\n    material.Init(surface_interaction);\n    \n    float3 wo = normalize(float3(0.f, 2.f, 3.46f) - surface_interaction.isect.p);\n    float3 wi = normalize(float3(0.f, 1.f, 3.f) - surface_interaction.isect.p);\n    float intensity = 1.5f;\n    \n    float3 color = (material.bsdf.Eval(wo, wi, TransportMode_Radiance) * abs(dot(wo, input.Normal)) + material.bsdf.GetGBufferData().emissive) * intensity;\n    return float4(ToneMapUncharted(color), 1.f);\n}"
  },
  {
    "path": "Source/Shaders/Editor/Preview/Mesh.hlsl",
    "content": "struct VSInput\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    uint InstanceID : SV_InstanceID;\n};\n\nstruct VSOutput\n{\n    float4 Position : SV_Position;\n    float3 Normal : NORMAL0;\n};\n\nstruct PSInput\n{\n    float3 Normal : NORMAL0;\n};\n\nstruct UniformBlock\n{\n    float4x4 transform;\n};\n\nConstantBuffer<UniformBlock> UniformBuffer;\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    float4 position = mul(UniformBuffer.transform, float4(input.Position, 1.0f));\n    output.Position = position;\n    output.Normal = input.Normal;\n    return output;\n}\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n    float3 norm = normalize(input.Normal);\n    float3 diffuse = max(dot(norm, normalize(float3(0, 1, 1))), 0.0);\n    return float4(diffuse, 1.f);\n}"
  },
  {
    "path": "Source/Shaders/GlobalIllumination/DDGI.hlsl",
    "content": ""
  },
  {
    "path": "Source/Shaders/ImGui.hlsl",
    "content": "struct VSInput\n{\n    float2 Pos : POSITIONT0;\n    float2 UV : TEXCOORD0;\n    float4 Color : COLOR0;\n};\n\nstruct Constant\n{\n    float2 scale;\n    float2 translate;\n};\n\nConstantBuffer<Constant> constant : register(b0);\n\nTexture2D fontTexture : register(t1);\nSamplerState fontSampler : register(s2);\n\nstruct VSOutput\n{\n    float4 Pos : SV_Position;\n    float2 UV : TEXCOORD0;\n    float4 Color : COLOR0;\n};\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    output.UV = input.UV;\n    output.Color = input.Color;\n    output.Pos = float4(input.Pos * constant.scale + constant.translate, 0.0, 1.0);\n#ifdef VULKAN_BACKEND\n    output.Pos.y *= -1.f;\n#endif\n    return output;\n}\n\nstruct PSInput\n{\n    float2 UV : TEXCOORD0;\n    float4 Color : COLOR0;\n};\n\nfloat4 PSmain(PSInput input) : SV_TARGET\n{\n    return input.Color * fontTexture.Sample(fontSampler, input.UV);\n}\n"
  },
  {
    "path": "Source/Shaders/Interaction.hlsli",
    "content": "#ifndef INTERATION_HLSLI\n#define INTERATION_HLSLI\n\n#include \"Math.hlsli\"\n\nfloat3 OffsetRayOrigin(float3 p, float3 n)\n{\n    const float intScale = 256.0f;\n    const float floatScale = 1.0f / 65536.0f;\n    const float origin = 1.0f / 32.0f;\n\n    int3 of_i = int3(intScale * n.x, intScale * n.y, intScale * n.z);\n\n    float3 p_i = float3(asfloat(asint(p.x) + ((p.x < 0) ? -of_i.x : of_i.x)),\n                  asfloat(asint(p.y) + ((p.y < 0) ? -of_i.y : of_i.y)),\n                  asfloat(asint(p.z) + ((p.z < 0) ? -of_i.z : of_i.z)));\n\n    return float3(abs(p.x) < origin ? p.x + floatScale * n.x : p_i.x, //\n              abs(p.y) < origin ? p.y + floatScale * n.y : p_i.y, //\n              abs(p.z) < origin ? p.z + floatScale * n.z : p_i.z);\n}\n\nstruct Frame\n{\n    float3 x, y, z;\n    \n    void FromXZ(float3 x_, float3 z_)\n    {\n        x = x_;\n        y = cross(z_, x_);\n        z = z_;\n    }\n    \n    void FromXY(float3 x_, float3 y_)\n    {\n        x = x_;\n        y = y_;\n        z = cross(x, y);\n    }\n\n    void FromZ(float3 z_)\n    {\n        z = z_;\n        CoordinateSystem(z, x, y);\n    }\n\n    void FromX(float3 x_)\n    {\n        x = x_;\n        CoordinateSystem(x, y, z);\n    }\n\n    void FromY(float3 y_)\n    {\n        y = y_;\n        CoordinateSystem(y, z, x);\n    }\n\n    float3 ToLocal(float3 v)\n    {\n        return float3(dot(v, x), dot(v, y), dot(v, z));\n    }\n\n    float3 ToWorld(float3 v)\n    {\n        return v.x * x + v.y * y + v.z * z;\n    }\n};\n\nstruct Interaction\n{\n    float3 p;\n    float3 n;\n    float3 nt;\n    float2 uv;\n    float3 wo;\n    float t;\n    \n    void Init(float3 p_, float3 n_, float2 uv_, float3 wo_, float t_)\n    {\n        p = p_;\n        n = n_;\n        uv = uv_;\n        wo = wo_;\n        t = t_;\n    }\n        \n    RayDesc SpawnRay(float3 dir)\n    {\n        RayDesc ray;\n        ray.Direction = dir;\n        ray.Origin = OffsetRayOrigin(p, FaceForward(n, dir));\n        return ray;\n    }\n    \n    RayDesc SpawnRayTo(float3 position)\n    {\n        return SpawnRay(normalize(position - p));\n    }\n};\n\nstruct MediumInteraction\n{\n    Interaction isect;\n};\n\nstruct SurfaceInteraction\n{\n    Interaction isect;\n    \n    /*float3 dpdu, dpdv;\n    float3 dndu, dndv;\n    \n    struct\n    {\n        float3 n;\n        float3 dpdu, dpdv;\n        float3 dndu, dndv;\n    } shading;*/\n  \n    float3 shading_n;\n    uint material;\n    float3 dpdx, dpdy;\n    float3 dndx, dndy;\n    float2 duvdx, duvdy;\n};\n\nstruct VisibilityTester\n{\n    SurfaceInteraction from;\n    float3 dir;\n    float dist;\n};\n\n#endif "
  },
  {
    "path": "Source/Shaders/Light.hlsli",
    "content": "#ifndef LIGHT_HLSLI\n#define LIGHT_HLSLI\n\n#include \"Interaction.hlsli\"\n#include \"Math.hlsli\"\n\n#define POINT_LIGHT 0\n#define SPOT_LIGHT 1\n#define DIRECTIONAL_LIGHT 2\n#define RECT_LIGHT 3\n\n#define LIGHT_TYPE_COUNT 4\n\nstruct LightInfo\n{\n    uint point_light_count;\n    uint spot_light_count;\n    uint directional_light_count;\n    uint rect_light_count;\n};\n\nstruct LightLeSample\n{\n    float3 L;\n    RayDesc ray;\n    Interaction isect;\n    float pdf_pos;\n    float pdf_dir;\n    \n    void Create(float3 L_, RayDesc ray_, float pdf_pos_, float pdf_dir_)\n    {\n        L = L_;\n        ray = ray_;\n        pdf_pos = pdf_pos_;\n        pdf_dir = pdf_dir_;\n    }\n\n    void Create(float3 L_, RayDesc ray_, Interaction isect_, float pdf_pos_, float pdf_dir_)\n    {\n        L = L_;\n        ray = ray_;\n        isect = isect_;\n        pdf_pos = pdf_pos_;\n        pdf_dir = pdf_dir_;\n    }\n};\n\nstruct LightLiSample\n{\n    float3 L;\n    float3 wi;\n    float pdf;\n    Interaction isect;\n    \n    void Create(float3 L_, float3 wi_, float pdf_, Interaction isect_)\n    {\n        L = L_;\n        wi = wi_;\n        pdf = pdf_;\n        isect = isect_;\n    }\n};\n\nstruct LightSampleContext\n{\n    float3 p;\n    float3 n;\n    float3 ns;\n};\n\nstruct PointLight\n{\n    float3 color;\n    float intensity;\n    float3 position;\n    \n    float filter_scale;\n    float light_scale;\n    uint filter_sample;\n    uint cast_shadow;\n    uint shadow_id;\n    \n    LightLeSample SampleLe(float2 u1, float2 u2, float time)\n    {\n        RayDesc ray;\n        ray.Origin = position;\n        ray.Direction = UniformSampleSphere(u1);\n        ray.TMin = 0.f;\n        ray.TMax = time;\n        \n        LightLeSample le_sample;\n        le_sample.Create(color * intensity, ray, 1, UniformSpherePdf());\n        \n        return le_sample;\n    }\n    \n    void PDF_Le(RayDesc ray, out float pdf_pos, out float pdf_dir)\n    {\n        pdf_pos = 0;\n        pdf_dir = UniformSpherePdf();\n    }\n\n    void PDF_Le(Interaction isect, float3 w, out float pdf_pos, out float pdf_dir)\n    {\n        \n    }\n\n    LightLiSample SampleLi(LightSampleContext ctx, float2 u)\n    {\n        float3 p = position;\n        float3 wi = normalize(p - ctx.p);\n        float3 L = color * intensity / DistanceSquared(p, ctx.p);\n        \n        Interaction isect;\n        isect.p = p;\n        \n        LightLiSample li_sample;\n        li_sample.Create(L, wi, 1, isect);\n        \n        return li_sample;\n    }\n\n    float PDF_Li(LightSampleContext ctx, float3 wi)\n    {\n        return 0.f;\n    }\n    \n    bool IsDelta()\n    {\n        return true;\n    }\n};\n\nstruct SpotLight\n{\n    float3 color;\n    float intensity;\n    float3 position;\n    float inner_angle;\n    float3 direction;\n    float outer_angle;\n    float4x4 view_projection;\n    \n    float filter_scale;\n    float light_scale;\n    uint filter_sample;\n    uint cast_shadow;\n    uint shadow_id;\n    \n    float3 EvalL(float3 p, out float3 wi)\n    {\n        wi = normalize(position - p);\n        float light_angle_scale = 1.0 / max(0.001, cos(inner_angle) - cos(outer_angle));\n        float light_angle_offset = -cos(outer_angle) * light_angle_scale;\n        float cd = max(dot(-direction, wi), 0.0);\n        float angular_attenuation = saturate(cd * light_angle_scale + light_angle_offset);\n        return color.rgb * intensity * angular_attenuation * angular_attenuation;\n    }\n    \n    LightLeSample SampleLe(float2 u1, float2 u2, float time)\n    {\n        // TODO\n        \n        LightLeSample le_sample;\n        \n        return le_sample;\n    }\n    \n    void PDF_Le(RayDesc ray, out float pdf_pos, out float pdf_dir)\n    {\n        // TODO\n    }\n\n    void PDF_Le(Interaction isect, float3 w, out float pdf_pos, out float pdf_dir)\n    {\n        // TODO\n    }\n\n    LightLiSample SampleLi(LightSampleContext ctx, float2 u)\n    {\n        float3 p = position;\n        float3 wi;\n        float3 L = EvalL(ctx.p, wi) / DistanceSquared(p, ctx.p);\n        \n        Interaction isect;\n        isect.p = p;\n        \n        LightLiSample li_sample;\n        li_sample.Create(L, wi, 1, isect);\n        \n        return li_sample;\n    }\n\n    float PDF_Li(LightSampleContext ctx, float3 wi)\n    {\n        return 0.f;\n    }\n    \n    bool IsDelta()\n    {\n        return true;\n    }\n};\n\nstruct DirectionalLight\n{\n    float3 color;\n    float intensity;\n    float4 split_depth;\n    float4x4 view_projection[4];\n    float4 shadow_cam_pos[4];\n    float3 direction;\n    \n    float filter_scale;\n    float light_scale;\n    uint filter_sample;\n    uint cast_shadow;\n    uint shadow_id;\n    \n    LightLiSample SampleLi(LightSampleContext ctx, float2 u)\n    {\n        float3 wi = normalize(-direction);\n        \n        Interaction isect;\n        isect.p = ctx.p + 1e16 * wi;\n        \n        float3 L = color.rgb * intensity;\n        \n        LightLiSample li_sample;\n        li_sample.Create(L, wi, 1, isect);\n        \n        return li_sample;\n    }\n    \n    bool IsDelta()\n    {\n        return true;\n    }\n};\n\nstruct RectLight\n{\n    float3 color;\n    float intensity;\n    float4 corner[4];\n    uint texture_id;\n    uint two_side;\n\n    LightLiSample SampleLi(LightSampleContext ctx, float2 u)\n    {\n        float3 v0 = (corner[1] - corner[0]).xyz;\n        float3 v1 = (corner[3] - corner[0]).xyz;\n        \n        float3 n = cross(v0, v1);\n        \n        float area = length(cross(v0, v1));\n        \n        Interaction isect;\n        isect.p = corner[0].xyz + v0 * u.x + v1 * u.y;\n        \n        float3 wi = normalize(isect.p - ctx.p);\n        float3 L = (two_side || dot(wi, n)) > 0 ? color.rgb * intensity / DistanceSquared(isect.p, ctx.p) / area : 0.f;\n        \n        LightLiSample li_sample;\n        li_sample.Create(L, wi, 1.f / area, isect);\n        \n        return li_sample;\n    }\n    \n    bool IsDelta()\n    {\n        return true;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/BSDF.hlsli",
    "content": "#ifndef BSDF_HLSLI\n#define BSDF_HLSLI\n\n// BxDF Flags\nstatic uint BSDF_Reflection = 1 << 0;\nstatic uint BSDF_Transmission = 1 << 1;\nstatic uint BSDF_Diffuse = 1 << 2;\nstatic uint BSDF_Glossy = 1 << 3;\nstatic uint BSDF_Specular = 1 << 4;\nstatic uint BSDF_DiffuseReflection = BSDF_Diffuse | BSDF_Reflection;\nstatic uint BSDF_DiffuseTransmission = BSDF_Diffuse | BSDF_Transmission;\nstatic uint BSDF_GlossyReflection = BSDF_Glossy | BSDF_Reflection;\nstatic uint BSDF_GlossyTransmission = BSDF_Glossy | BSDF_Transmission;\nstatic uint BSDF_SpecularReflection = BSDF_Specular | BSDF_Reflection;\nstatic uint BSDF_SpecularTransmission = BSDF_Specular | BSDF_Transmission;\nstatic uint BSDF_All = BSDF_Diffuse | BSDF_Glossy | BSDF_Specular | BSDF_Reflection | BSDF_Transmission;\n\n// Sample Flag\nstatic uint SampleFlags_Unset = 0;\nstatic uint SampleFlags_Reflection = 1 << 0;\nstatic uint SampleFlags_Transmission = 1 << 1;\nstatic uint SampleFlags_All = SampleFlags_Reflection | SampleFlags_Transmission;\n\n// Transport Mode\nstatic uint TransportMode_Radiance = 0;\nstatic uint TransportMode_Importance = 1;\n\n#define SampleFlags uint\n#define TransportMode uint\n#define BxDFFlags uint\n\nbool IsReflective(uint f)\n{\n    return f & BSDF_Reflection;\n}\n\nbool IsTransmissive(uint f)\n{\n    return f & BSDF_Transmission;\n}\n\nbool IsDiffuse(uint f)\n{\n    return f & BSDF_Diffuse;\n}\n\nbool IsGlossy(uint f)\n{\n    return f & BSDF_Glossy;\n}\n\nbool IsSpecular(uint f)\n{\n    return f & BSDF_Specular;\n}\n\nbool IsNonSpecular(uint f)\n{\n    return f & (BSDF_Diffuse | BSDF_Glossy);\n}\n\nstruct BSDFSample\n{\n    float3 f;\n    float3 wiW;\n    float3 wi;\n    float pdf;\n    BxDFFlags flags;\n    float eta;\n    bool pdfIsProportional;\n    \n    void Init()\n    {\n        f = 0.f;\n        wiW = 0.f;\n        wi = 0.f;\n        pdf = 0.f;\n        flags = 0.f;\n        eta = 1.f;\n        pdfIsProportional = false;\n\n    }\n    \n    bool IsReflection()\n    {\n        return flags & BSDF_Reflection;\n    }\n    \n    bool IsTransmission()\n    {\n        return flags & BSDF_Transmission;\n    }\n    \n    bool IsDiffuse()\n    {\n        return flags & BSDF_Diffuse;\n    }\n    \n    bool IsGlossy()\n    {\n        return flags & BSDF_Glossy;\n    }\n    \n    bool IsSpecular()\n    {\n        return flags & BSDF_Specular;\n    }\n};\n\nfloat3 SRGBtoLINEAR(float3 srgb_in)\n{\n#ifdef SRGB_FAST_APPROXIMATION\n  float3 linOut = pow(srgbIn, vec3(2.2));\n#else  //SRGB_FAST_APPROXIMATION\n    float3 bLess = step(0.04045, srgb_in);\n    float3 linOut = lerp(srgb_in.xyz / 12.92, pow((srgb_in + 0.055) / 1.055, 2.4), bLess);\n#endif  //SRGB_FAST_APPROXIMATION\n    return linOut;\n}\n\nstruct GBufferData\n{\n    float3 normal;\n    float3 albedo;\n    float3 emissive;\n    float metallic;\n    float roughness;\n    float anisotropic;\n};\n\n// struct BSDF\n// {\n//     void Init();\n\n//     float3 Eval(float3 wo, float3 wi, TransportMode mode);\n\n//     float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags);\n\n//     BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags);\n\n//     GBufferData GetGBufferData();\n\n// };\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/ConductorBSDF.hlsli",
    "content": "#ifndef CONDUCTOR_BSDF_HLSLI\n#define CONDUCTOR_BSDF_HLSLI\n\n#include \"BSDF.hlsli\"\n#include \"../Scattering.hlsli\"\n#include \"../Fresnel.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct ConductorBSDF\n{\n    TrowbridgeReitzDistribution distribution;\n    float3 eta;\n    float3 k;\n    float3 R;\n    \n    void Init(float3 R_, float roughness, float3 eta_, float3 k_)\n    {\n        R = R_;\n        eta = eta_;\n        k = k_;\n        distribution.alpha_x = roughness;\n        distribution.alpha_y = roughness;\n        distribution.sample_visible_area = true;\n    }\n\n    uint Flags()\n    {\n        return distribution.EffectivelySmooth() ? BSDF_SpecularReflection : BSDF_GlossyReflection;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        if(!SameHemisphere(wo, wi))\n        {\n            return 0.f;\n        }\n\n        if(distribution.EffectivelySmooth())\n        {\n            return 0.f;\n        }\n\n        float cos_theta_o = AbsCosTheta(wo);\n        float cos_theta_i = AbsCosTheta(wi);\n\n        if(cos_theta_i == 0 || cos_theta_o == 0)\n        {\n            return 0.f;\n        }\n\n        float3 wm = wi + wo;\n\n        if(LengthSquared(wm) == 0)\n        {\n            return 0.f;\n        }\n\n        wm = normalize(wm);\n\n        float3 F = FresnelConductor(abs(dot(wo, wm)), eta, k);\n\n        return R * distribution.D(wm) * F * distribution.G(wo, wi) / (4 * cos_theta_i * cos_theta_o);\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        if(!(flags & SampleFlags_Reflection))\n        {\n            return 0.f;\n        }\n        if(!SameHemisphere(wo, wi))\n        {\n            return 0.f;\n        }\n        if(distribution.EffectivelySmooth())\n        {\n            return 0.f;\n        }\n\n        float3 wm = wo + wi;\n\n        if(LengthSquared(wm) == 0)\n        {\n            return 0.f;\n        }\n\n        wm = Faceforward(normalize(wm), float3(0, 0, 1));\n        return distribution.Pdf(wo, wm) / (4 * abs(dot(wo, wm)));\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample;\n        bsdf_sample.Init();\n\n        if(!(flags & SampleFlags_Reflection))\n        {\n            return bsdf_sample;\n        }\n\n        if(distribution.EffectivelySmooth())\n        {\n            float3 wi = float3(-wo.x, -wo.y, wo.z);\n            \n            bsdf_sample.f = R * FresnelConductor(AbsCosTheta(wi), eta, k) / AbsCosTheta(wi);\n            bsdf_sample.wi = wi;\n            bsdf_sample.pdf = 1;\n            bsdf_sample.flags = BSDF_SpecularReflection;\n            bsdf_sample.eta = 1;\n\n            return bsdf_sample;\n        }\n\n        if(wo.z == 0)\n        {\n            return bsdf_sample;\n        }\n\n        float3 wm = distribution.SampleWm(wo, u);\n        float3 wi = Reflect(wo, wm);\n\n        if(!SameHemisphere(wo, wi))\n        {\n            return bsdf_sample;\n        }\n\n        float cos_theta_o = AbsCosTheta(wo);\n        float cos_theta_i = AbsCosTheta(wi);\n        if(cos_theta_i == 0 || cos_theta_o == 0)\n        {\n           return bsdf_sample;\n        }\n\n        float3 F = FresnelConductor(abs(dot(wo, wm)), eta, k);\n\n        bsdf_sample.f = R * distribution.D(wm) * F * distribution.G(wo, wi) / (4 * cos_theta_i * cos_theta_o);\n        bsdf_sample.wi = wi;\n        bsdf_sample.pdf = distribution.Pdf(wo, wm) / (4 * abs(dot(wo, wm)));\n        bsdf_sample.flags = BSDF_GlossyReflection;\n        bsdf_sample.eta = 1;\n\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/DielectricBSDF.hlsli",
    "content": "#ifndef DIELECTRIC_BSDF_HLSLI\n#define DIELECTRIC_BSDF_HLSLI\n\n#include \"BSDF.hlsli\"\n#include \"../Scattering.hlsli\"\n#include \"../Fresnel.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct DielectricBSDF\n{\n    float3 R;\n    float3 T;\n    float eta;\n    TrowbridgeReitzDistribution distribution;\n\n    void Init(float3 R_, float3 T_, float ior_, float roughness)\n    {\n        R = R_;\n        T = T_;\n        eta = ior_;\n\n        distribution.alpha_x = roughness;\n        distribution.alpha_y = roughness;\n        distribution.sample_visible_area = true;\n    }\n\n    uint Flags()\n    {\n        uint flags = (eta == 1.f? BSDF_Transmission : BSDF_Reflection | BSDF_Transmission);\n        return flags | (distribution.EffectivelySmooth()? BSDF_Specular : BSDF_Glossy);\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        if(eta == 1.f || distribution.EffectivelySmooth())\n        {\n            return 0.f;\n        }\n\n        float cos_theta_o = CosTheta(wo);\n        float cos_theta_i = CosTheta(wi);\n        bool reflection = cos_theta_o * cos_theta_i > 0;\n        float etap = 1;\n        if(!reflection)\n        {\n            etap = cos_theta_o > 0.f ? eta : (1 / eta);\n        }\n\n        float3 wm = wi * etap + wo;\n\n        if(cos_theta_i == 0 || cos_theta_o == 0 || LengthSquared(wm) == 0)\n        {\n            return 0.f;\n        }\n\n        wm = FaceForward(normalize(wm), float3(0, 0, 1));\n\n        if(dot(wm, wi) * cos_theta_i < 0 || dot(wm, wo) * cos_theta_o < 0)\n        {\n            return 0.f;\n        }\n\n        float F = FresnelDielectric(dot(wo, wm), eta);\n\n        if(reflection)\n        {\n            return R * distribution.D(wm) * distribution.G(wo, wi) * F / \n                abs(4 * cos_theta_i * cos_theta_o);            \n        }\n        else\n        {\n            float denom = Sqr(dot(wi, wm) + dot(wo, wm) / etap) * cos_theta_i * cos_theta_o;\n            float3 ft = T * distribution.D(wm) * (1.f - F) * distribution.G(wo, wi) * \n                abs(dot(wi, wm) * dot(wo, wm) / denom);\n            if(mode == TransportMode_Radiance)\n            {\n                ft /= Sqr(etap);\n            }\n            return ft;\n        }\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        if(eta == 1.f || distribution.EffectivelySmooth())\n        {\n            return 0.f;\n        }\n\n        float cos_theta_o = CosTheta(wo);\n        float cos_theta_i = CosTheta(wi);\n        bool reflection = cos_theta_o * cos_theta_i > 0;\n        float etap = 1;\n        if(!reflection)\n        {\n            etap = cos_theta_o > 0.f ? eta : 1 / eta;\n        }\n\n        float3 wm = wi * etap + wo;\n\n        if(cos_theta_i == 0 || cos_theta_o == 0 || LengthSquared(wm) == 0)\n        {\n            return 0.f;\n        }\n\n        wm = FaceForward(normalize(wm), float3(0, 0, 1));\n\n        if(dot(wm, wi) * cos_theta_i < 0 || dot(wm, wo) * cos_theta_o < 0)\n        {\n            return 0.f;\n        }\n\n        float pr = FresnelDielectric(dot(wo, wm), eta);\n        float pt = 1.f - pr;\n\n        if(!(flags & SampleFlags_Reflection))\n        {\n            pr = 0;\n        }\n        if(!(flags & SampleFlags_Transmission))\n        {\n            pt = 0;\n        }\n        if(pr == 0 && pt == 0)\n        {\n            return 0.f;\n        }\n\n        float pdf = 0.f;\n        if(reflection)\n        {\n            pdf = distribution.Pdf(wo, wm) / (4.0 * abs(dot(wo, wm))) * pr / (pr + pt);\n        }\n        else\n        {\n            float denom = Sqr(dot(wi, wm) + dot(wo, wm) / etap);\n            float dwm_dwi = abs(dot(wi, wm)) / denom;\n            pdf = distribution.Pdf(wo, wm) * dwm_dwi * pt / (pr + pt);\n        }\n\n        return pdf;\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample;\n        bsdf_sample.Init();\n\n        if(eta == 1 || distribution.EffectivelySmooth())\n        {\n            // Smooth Dielectric\n            float F = FresnelDielectric(CosTheta(wo), eta);\n            float pr = F;\n            float pt = 1.f - F;\n            if(!(flags & SampleFlags_Reflection))\n            {\n                pr = 0.f;\n            }\n            if(!(flags & SampleFlags_Transmission))\n            {\n                pt = 0.f;\n            }\n            if(pr == 0.f && pt == 0.f)\n            {\n                return bsdf_sample;\n            }\n\n            if(uc < pr / (pr + pt))\n            {\n                float3 wi = float3(-wo.x, -wo.y, wo.z);\n                float3 fr = R * F / abs(CosTheta(wi));\n                \n                bsdf_sample.f = fr;\n                bsdf_sample.wi = wi;\n                bsdf_sample.pdf = pr / (pr + pt);\n                bsdf_sample.flags = BSDF_SpecularReflection;\n                bsdf_sample.eta = 1;\n\n                return bsdf_sample;\n            }\n            else\n            {\n                float etap = 0.f;\n                float3 wi;\n                if (!Refract(wo, float3(0.0, 0.0, 1.0), eta, etap, wi))\n                {\n                    return bsdf_sample;\n                }\n\n                float3 ft = (1.f - F) * T / abs(CosTheta(wi));\n                if(mode == TransportMode_Radiance)\n                {\n                    ft /= Sqr(etap);\n                }\n\n                bsdf_sample.f = ft;\n                bsdf_sample.wi = wi;\n                bsdf_sample.pdf = pt / (pr + pt);\n                bsdf_sample.flags = BSDF_SpecularTransmission;\n                bsdf_sample.eta = etap;\n\n                return bsdf_sample;\n            }\n        }\n        else\n        {\n            // Rough Dielectric\n            float3 wm = distribution.SampleWm(wo, u);\n            float F = FresnelDielectric(CosTheta(wo), eta);\n            float pr = F;\n            float pt = 1.f - F;\n\n            if(!(flags & SampleFlags_Reflection))\n            {\n                pr = 0.f;\n            }\n            if(!(flags & SampleFlags_Transmission))\n            {\n                pt = 0.f;\n            }\n            if(pr == 0.f && pt == 0.f)\n            {\n                return bsdf_sample;\n            }\n\n            if (uc < pr / (pr + pt))\n            {\n                float3 wi = Reflect(wo, wm);\n                if(!SameHemisphere(wo, wi))\n                {\n                    return bsdf_sample;\n                }\n\n                bsdf_sample.f = distribution.D(wm) * distribution.G(wo, wi) * R * F / (4.f * CosTheta(wi) * CosTheta(wo));\n                bsdf_sample.wi = wi;\n                bsdf_sample.pdf = distribution.Pdf(wo, wm) / (4.f * abs(dot(wo, wm))) * pr / (pr + pt);\n                bsdf_sample.flags = BSDF_GlossyReflection;\n                bsdf_sample.eta = 1.f;\n\n                return bsdf_sample;\n            }\n            else\n            {\n                float etap;\n                float3 wi;\n                if(!Refract(wo, Faceforward(wm, float3(0, 0, 1)), eta, etap, wi))\n                {\n                    return bsdf_sample;\n                }\n\n                float denom = Sqr(dot(wi, wm) + dot(wo, wm) / etap);\n                float dwm_dwi = abs(dot(wi, wm)) / denom;\n                float3 ft = T * (1.f - F) * distribution.D(wm) * distribution.G(wo, wi) * \n                        abs(dot(wi, wm) * dot(wo, wm) / \n                        (CosTheta(wi) * CosTheta(wo) * denom));\n\n                if(mode == TransportMode_Radiance)\n                {\n                    ft /= Sqr(etap);\n                }\n\n                bsdf_sample.f = ft;\n                bsdf_sample.wi = wi;\n                bsdf_sample.pdf = distribution.Pdf(wo, wm) * dwm_dwi * pt / (pr + pt);\n                bsdf_sample.flags = BSDF_GlossyTransmission;\n                bsdf_sample.eta = etap;\n\n                return bsdf_sample;\n            }\n        }\n\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/DiffuseBSDF.hlsli",
    "content": "#ifndef DIFFUSE_BSDF_HLSLI\n#define DIFFUSE_BSDF_HLSLI\n\n#include \"BSDF.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct DiffuseBSDF\n{\n    float3 R;\n\n    void Init(float3 R_)\n    {\n        R = R_;\n    }\n    \n    uint Flags()\n    {\n        return BSDF_DiffuseReflection;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        if (!SameHemisphere(wo, wi))\n        {\n            return 0.f;\n        }\n        \n        return R * InvPI;\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        if (!(flags & SampleFlags_Reflection) || !SameHemisphere(wo, wi))\n        {\n            return 0.f;\n        }\n        \n        return AbsCosTheta(wi) * InvPI;\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample;\n        \n        bsdf_sample.Init();\n        \n        if (!(flags & SampleFlags_Reflection))\n        {\n            return bsdf_sample;\n        }\n\n        float3 wi = SampleCosineHemisphere(u);\n        \n        if (wo.z < 0.f)\n        {\n            wi.z *= -1.f;\n        }\n\n        bsdf_sample.f = Eval(wo, wi, mode);\n        bsdf_sample.wi = wi;\n        bsdf_sample.pdf = PDF(wo, wi, mode, flags);\n        bsdf_sample.flags = BSDF_DiffuseReflection;\n        bsdf_sample.eta = 1;\n\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/DisneyBSDF.hlsli",
    "content": "#ifndef DISNEY_BSDF_HLSLI\n#define DISNEY_BSDF_HLSLI\n\n#include \"BSDF.hlsli\"\n#include \"../Scattering.hlsli\"\n#include \"../Fresnel.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Common.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nfloat2 CalculateAnisotropicRoughness(float anisotropic, float roughness)\n{\n    float rough2 = Sqr(roughness);\n    if (anisotropic == 0)\n    {\n        float a = max(0.001, rough2);\n        return a;\n    }\n    float aspect = sqrt(1.0 - 0.9 * anisotropic);\n    return float2(max(0.001, rough2 / aspect), max(0.001, rough2 * aspect));\n}\n\n// Schlick Fresnel Approximation\nfloat SchlickWeight(float cos_theta)\n{\n    float m = clamp(1 - cos_theta, 0.0, 1.0);\n    return pow(m, 5.0);\n}\n\nfloat FrSchlick(float R0, float cos_theta)\n{\n    return lerp(R0, 1.0, SchlickWeight(cos_theta));\n}\n\nfloat3 FrSchlick(float3 R0, float cos_theta)\n{\n    return lerp(R0, float3(1.0, 1.0, 1.0), SchlickWeight(cos_theta));\n}\n\nfloat SchlickR0FromEta(float eta)\n{\n    return ((eta - 1.0) * (eta - 1.0)) / ((eta + 1.0) * (eta + 1.0));\n}\n\n// Diffuse\nfloat3 DisneyDiffuse(float3 base_color, float3 wo, float3 wi)\n{\n    float Fo = SchlickWeight(AbsCosTheta(wo));\n    float Fi = SchlickWeight(AbsCosTheta(wi));\n    return base_color * InvPI * (1 - Fo / 2) * (1 - Fi / 2);\n}\n\n// Fake subsurface\nfloat3 DisneyFakeSS(float3 base_color, float roughness, float3 wo, float3 wi)\n{\n    float3 wh = wi + wo;\n    if (IsBlack(wh))\n    {\n        return 0.f;\n    }\n    wh = normalize(wh);\n    float cos_theta_d = dot(wi, wh);\n    float Fss90 = cos_theta_d * cos_theta_d * roughness;\n    float Fo = SchlickWeight(AbsCosTheta(wo));\n    float Fi = SchlickWeight(AbsCosTheta(wi));\n    float Fss = lerp(1.0, Fss90, Fo) * lerp(1.0, Fss90, Fi);\n    float ss = 1.25f * (Fss * (1 / (AbsCosTheta(wo) + AbsCosTheta(wi)) - 0.5) + 0.5f);\n\n    return base_color * InvPI * ss;\n}\n\n// Retro\nfloat3 DisneyRetro(float3 base_color, float roughness, float3 wo, float3 wi)\n{\n    float3 wh = wi + wo;\n    if (IsBlack(wh))\n    {\n        return 0.f;\n    }\n    wh = normalize(wh);\n    float cos_theta_d = dot(wi, wh);\n    float Fo = SchlickWeight(AbsCosTheta(wo));\n    float Fi = SchlickWeight(AbsCosTheta(wi));\n    float Rr = 2 * roughness * cos_theta_d * cos_theta_d;\n\n    return base_color * InvPI * Rr * (Fo + Fi + Fo * Fi * (Rr - 1));\n}\n\n// Sheen\nfloat3 DisneySheen(float3 base_color, float lum, float sheen_tint, float3 wo, float3 wi)\n{\n    float3 wh = wi + wo;\n    if (IsBlack(wh))\n    {\n        return 0.f;\n    }\n    wh = normalize(wh);\n    float cos_theta_d = dot(wi, wh);\n\n    float3 c_tint = lum > 0 ? base_color / lum : 1;\n    float3 c_sheen = (1 - sheen_tint) + sheen_tint * c_tint;\n\n    return c_sheen * SchlickWeight(cos_theta_d);\n}\n\nfloat GTR1(float cos_theta, float alpha)\n{\n    float alpha2 = alpha * alpha;\n    return (alpha2 - 1) / (PI * log(alpha2) * (1 + (alpha2 - 1) * cos_theta * cos_theta));\n}\n\nfloat SmithG_GGX(float cos_theta, float alpha)\n{\n    float alpha2 = alpha * alpha;\n    float cos_theta_2 = cos_theta * cos_theta;\n    return 1 / (cos_theta + sqrt(alpha2 + cos_theta_2 - alpha2 * cos_theta_2));\n}\n\n// Clearcoat\nfloat3 DisneyClearcoat(float gloss, float3 wo, float3 wi)\n{\n    float3 wh = wi + wo;\n    if (IsBlack(wh))\n    {\n        return 0.f;\n    }\n    wh = normalize(wh);\n    float cos_theta_i = AbsCosTheta(wi);\n    float cos_theta_o = AbsCosTheta(wo);\n    float Dcc = GTR1(AbsCosTheta(wh), lerp(0.1f, 0.001f, gloss));\n    float Fcc = FrSchlick(0.04, dot(wo, wh));\n    float Gcc = SmithG_GGX(AbsCosTheta(wo), 0.25) * SmithG_GGX(AbsCosTheta(wi), 0.25);\n\n    return Fcc * Dcc * Gcc / (4 * cos_theta_i * cos_theta_o);\n}\n\nfloat DisneyClearcoatPdf(float gloss, float3 wo, float3 wi)\n{\n    float3 wh = wi + wo;\n    if (IsBlack(wh))\n    {\n        return 0.f;\n    }\n    wh = normalize(wh);\n    float Dr = GTR1(AbsCosTheta(wh), lerp(0.1f, 0.001f, gloss));\n    return Dr * AbsCosTheta(wh) / (4 * dot(wo, wh));\n}\n\nfloat3 DisneyClearcoatSample(float gloss, float3 wo, float2 u)\n{\n    if (wo.z == 0)\n    {\n        return 0.f;\n    }\n\n    float alpha2 = gloss * gloss;\n    float cos_theta = sqrt(max(0, (1 - pow(alpha2, 1 - u.x)) / (1 - alpha2)));\n    float sin_theta = sqrt(max(0, 1 - cos_theta * cos_theta));\n    float phi = 2 * PI * u.y;\n    float3 wh = SphericalDirection(sin_theta, cos_theta, phi);\n    if (!SameHemisphere(wo, wh))\n    {\n        wh = -wh;\n    }\n\n    float3 wi = Reflect(wo, wh);\n\n    return wi;\n}\n\nstruct DisneyBSDF\n{\n    float3 base_color;\n    float roughness;\n    float anisotropic;\n    float spec_trans;\n    float eta;\n    float sheen;\n    float sheen_tint;\n    float specular;\n    float spec_tint;\n    float metallic;\n    float clearcoat;\n    float clearcoat_gloss;\n    float subsurface;\n    float3 emissive;\n    bool twoside;\n    float2 alpha;\n\n    void Init(\n        float3 base_color_,\n        float roughness_,\n        float anisotropic_,\n        float spec_trans_,\n        float eta_,\n        float sheen_,\n        float sheen_tint_,\n        float specular_,\n        float spec_tint_,\n        float metallic_,\n        float clearcoat_,\n        float clearcoat_gloss_,\n        float subsurface_,\n        float3 emissive_,\n        bool twoside_)\n    {\n        base_color = base_color_;\n        roughness = roughness_;\n        anisotropic = anisotropic_;\n        spec_trans = spec_trans_;\n        eta = eta_;\n        sheen = sheen_;\n        sheen_tint = sheen_tint_;\n        specular = specular_;\n        spec_tint = spec_tint_;\n        metallic = metallic_;\n        clearcoat = clearcoat_;\n        clearcoat_gloss = clearcoat_gloss_;\n        subsurface = subsurface_;\n        emissive = emissive_;\n        twoside = twoside_;\n    }\n\n    uint Flags()\n    {\n        return BSDF_Diffuse | BSDF_Glossy | BSDF_Specular | BSDF_Reflection | BSDF_Transmission;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        float3 f = 0.f;\n\n        float cos_theta_i = CosTheta(wi);\n        float cos_theta_o = CosTheta(wo);\n\n        float brdf = (1.f - metallic) * (1.f - spec_trans);\n        float bsdf = (1.f - metallic) * spec_trans;\n\n        bool has_reflect = (cos_theta_i * cos_theta_o > 0.f);\n        bool has_refract = (cos_theta_i * cos_theta_o < 0.f);\n\n        float etap = 1;\n        if (has_refract)\n        {\n            etap = cos_theta_o > 0.f ? eta : (1 / eta);\n        }\n\n        float3 wm = wi * etap + wo;\n\n        if (cos_theta_i == 0 || cos_theta_o == 0 || LengthSquared(wm) == 0)\n        {\n            return 0.f;\n        }\n\n        wm = FaceForward(normalize(wm), float3(0, 0, 1));\n\n        bool front_side = cos_theta_o > 0.f || twoside;\n\n        float F_dielectric = FresnelDielectric(CosTheta(wo), eta);\n\n        bool has_sheen = (sheen > 0.f) && has_reflect && (1.f - metallic > 0.f) && front_side;\n        bool has_diffuse = (brdf > 0.f) && has_reflect && front_side;\n        bool has_spec_reflect = has_reflect && (F_dielectric > 0.f);\n        bool has_clearcoat = has_reflect && (clearcoat > 0.f) && front_side;\n        bool has_spec_trans = (bsdf > 0.f) && has_refract && (F_dielectric < 1.f);\n\n        float roughness2 = Sqr(roughness);\n        alpha = max(0.001, roughness2);\n        if (anisotropic > 0)\n        {\n            float aspect = sqrt(1.f - 0.9f * anisotropic);\n            alpha.x = max(0.001, roughness2 / aspect);\n            alpha.y = max(0.001, roughness2 * aspect);\n        }\n        TrowbridgeReitzDistribution spec_dist;\n        spec_dist.alpha_x = alpha.x;\n        spec_dist.alpha_y = alpha.y;\n        spec_dist.sample_visible_area = true;\n\n        float D = spec_dist.D(wm);\n        float G = spec_dist.G1(wo) * spec_dist.G1(wi);\n        float lum = Luminance(base_color);\n\n        if (has_diffuse)\n        {\n            float3 f_diff = DisneyDiffuse(base_color, wo, wi);\n            float3 f_retro = DisneyRetro(base_color, roughness, wo, wi);\n\n            if (subsurface > 0)\n            {\n                float3 f_ss = DisneyFakeSS(base_color, roughness, wo, wi);\n                f += brdf * lerp(f_diff + f_retro, f_ss, subsurface);\n            }\n            else\n            {\n                f += brdf * f_diff + f_retro;\n            }\n        }\n\n        if (has_sheen)\n        {\n            f += sheen * (1.f - metallic) * DisneySheen(base_color, lum, sheen_tint, wo, wi);\n        }\n\n        if (has_clearcoat)\n        {\n            f += 0.25 * clearcoat * DisneyClearcoat(clearcoat_gloss, wo, wi);\n        }\n\n        if (has_spec_reflect)\n        {\n            float3 F_schlick = 0.f;\n            if (metallic > 0)\n            {\n                F_schlick += metallic * FrSchlick(base_color, cos_theta_o);\n            }\n            if (spec_tint > 0)\n            {\n                float3 c_tint = lum > 0.f ? base_color / lum : 1.f;\n                float3 F0_spec_tint = c_tint * SchlickR0FromEta(etap);\n            }\n            float3 F = front_side ?\n                base_color * (1.f - metallic) * (1.f - spec_tint) * F_dielectric + F_schlick :\n                bsdf * F_dielectric;\n            f += F * D * G / abs(4.f * cos_theta_i * cos_theta_o);\n        }\n\n        if (has_spec_trans)\n        {\n            float denom = Sqr(dot(wi, wm) + dot(wo, wm) / etap) * cos_theta_i * cos_theta_o;\n            float3 ft = sqrt(base_color) * bsdf * D * (1.f - F_dielectric) * G * abs(dot(wi, wm) * dot(wo, wm) / denom);\n            if (mode == TransportMode_Radiance)\n            {\n                ft /= Sqr(etap);\n            }\n            f += ft;\n        }\n\n        return f;\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        float cos_theta_i = CosTheta(wi);\n        float cos_theta_o = CosTheta(wo);\n\n        float brdf = (1.f - metallic) * (1.f - spec_trans);\n        float bsdf = (1.f - metallic) * spec_trans;\n\n        bool has_reflect = (cos_theta_i * cos_theta_o > 0.f);\n        bool has_refract = (cos_theta_i * cos_theta_o < 0.f);\n\n        float etap = 1;\n        if (has_refract)\n        {\n            etap = cos_theta_o > 0.f ? eta : (1 / eta);\n        }\n\n        float3 wm = wi * etap + wo;\n\n        if (cos_theta_i == 0 || cos_theta_o == 0 || LengthSquared(wm) == 0)\n        {\n            return 0.f;\n        }\n\n        wm = FaceForward(normalize(wm), float3(0, 0, 1));\n\n        bool front_side = cos_theta_o > 0.f || twoside;\n\n        float F_dielectric = FresnelDielectric(CosTheta(wo), eta);\n\n        bool has_sheen = (sheen > 0.f) && has_reflect && (1.f - metallic > 0.f) && front_side;\n        bool has_diffuse = (brdf > 0.f) && has_reflect && front_side;\n        bool has_spec_reflect = has_reflect && (F_dielectric > 0.f);\n        bool has_clearcoat = has_reflect && (clearcoat > 0.f) && front_side;\n        bool has_spec_trans = (bsdf > 0.f) && has_refract && (F_dielectric < 1.f);\n\n        float prob_spec_reflect = front_side ? 1.f - bsdf * (1.f - F_dielectric) : F_dielectric;\n        float prob_spec_trans = has_spec_trans ? (front_side ? bsdf * (1.f - F_dielectric) : 1.f - F_dielectric) : 0.f;\n        float prob_clearcoat = has_clearcoat ? (front_side ? 0.25f * clearcoat : 0.f) : 0.f;\n        float prob_diffuse = front_side ? brdf : 0.f;\n        float rcp_tot_prob = rcp(prob_spec_reflect + prob_spec_trans + prob_clearcoat + prob_diffuse);\n        \n        prob_spec_reflect *= rcp_tot_prob;\n        prob_spec_trans *= rcp_tot_prob;\n        prob_clearcoat *= rcp_tot_prob;\n        prob_diffuse *= rcp_tot_prob;\n\n        float roughness2 = Sqr(roughness);\n        float2 alpha = max(0.001, roughness2);\n        if (anisotropic > 0)\n        {\n            float aspect = sqrt(1.f - 0.9f * anisotropic);\n            alpha.x = max(0.001, roughness2 / aspect);\n            alpha.y = max(0.001, roughness2 * aspect);\n        }\n        TrowbridgeReitzDistribution spec_dist;\n        spec_dist.alpha_x = alpha.x;\n        spec_dist.alpha_y = alpha.y;\n        spec_dist.sample_visible_area = true;\n\n        float pdf = 0.f;\n\n        if (has_diffuse)\n        {\n            pdf += prob_diffuse * AbsCosTheta(wi) * InvPI;\n        }\n\n        if (has_clearcoat)\n        {\n            pdf += prob_clearcoat * DisneyClearcoatPdf(clearcoat_gloss, wo, wi);\n        }\n\n        if (has_spec_reflect)\n        {\n            pdf += prob_spec_reflect * spec_dist.Pdf(wo, wm) / (4.0 * abs(dot(wo, wm)));\n        }\n\n        if (has_spec_trans)\n        {\n            float denom = Sqr(dot(wi, wm) + dot(wo, wm) / etap);\n            float dwm_dwi = abs(dot(wi, wm)) / denom;\n            pdf += prob_spec_trans * spec_dist.Pdf(wo, wm) * dwm_dwi;\n        }\n        \n        return pdf;\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample;\n        bsdf_sample.Init();\n\n        float cos_theta_o = CosTheta(wo);\n\n        float brdf = (1.f - metallic) * (1.f - spec_trans);\n        float bsdf = (1.f - metallic) * spec_trans;\n\n        bool has_reflect = (flags & SampleFlags_Reflection);\n        bool has_refract = (flags & SampleFlags_Transmission);\n\n        bool front_side = cos_theta_o > 0.f || twoside;\n\n        float F_dielectric = FresnelDielectric(CosTheta(wo), eta);\n\n        bool has_sheen = (sheen > 0.f) && has_reflect && (1.f - metallic > 0.f) && front_side;\n        bool has_diffuse = (brdf > 0.f) && has_reflect && front_side;\n        bool has_spec_reflect = has_reflect && (F_dielectric > 0.f);\n        bool has_clearcoat = has_reflect && (clearcoat > 0.f) && front_side;\n        bool has_spec_trans = (bsdf > 0.f) && has_refract && (F_dielectric < 1.f);\n\n        float prob_spec_reflect = front_side ? 1.f - bsdf * (1.f - F_dielectric) : F_dielectric;\n        float prob_spec_trans = has_spec_trans ? (front_side ? bsdf * (1.f - F_dielectric) : 1.f - F_dielectric) : 0.f;\n        float prob_clearcoat = has_clearcoat ? (front_side ? 0.25f * clearcoat : 0.f) : 0.f;\n        float prob_diffuse = front_side ? brdf : 0.f;\n\n        float rcp_tot_prob = rcp(prob_spec_reflect + prob_spec_trans + prob_clearcoat + prob_diffuse);\n        prob_spec_reflect *= rcp_tot_prob;\n        prob_spec_trans *= rcp_tot_prob;\n        prob_clearcoat *= rcp_tot_prob;\n        prob_diffuse *= rcp_tot_prob;\n\n        if (uc < prob_spec_reflect)\n        {\n            float roughness2 = Sqr(roughness);\n            float2 alpha = max(0.001, roughness2);\n            if (anisotropic > 0)\n            {\n                float aspect = sqrt(1.f - 0.9f * anisotropic);\n                alpha.x = max(0.001, roughness2 / aspect);\n                alpha.y = max(0.001, roughness2 * aspect);\n            }\n            TrowbridgeReitzDistribution spec_dist;\n            spec_dist.alpha_x = alpha.x;\n            spec_dist.alpha_y = alpha.y;\n            spec_dist.sample_visible_area = true;\n\n            float3 wm = spec_dist.SampleWm(wo, u);\n\n            // Sample specular reflection\n            bsdf_sample.wi = Reflect(wo, FaceForward(wm, wo));\n            bsdf_sample.flags = BSDF_GlossyReflection;\n            bsdf_sample.eta = 1;\n        }\n        else if (uc < prob_spec_reflect + prob_spec_trans)\n        {\n            // Sample specular transmission\n            float roughness2 = Sqr(roughness);\n            float2 alpha = max(0.001, roughness2);\n            if (anisotropic > 0)\n            {\n                float aspect = sqrt(1.f - 0.9f * anisotropic);\n                alpha.x = max(0.001, roughness2 / aspect);\n                alpha.y = max(0.001, roughness2 * aspect);\n            }\n            TrowbridgeReitzDistribution spec_dist;\n            spec_dist.alpha_x = alpha.x;\n            spec_dist.alpha_y = alpha.y;\n            spec_dist.sample_visible_area = true;\n\n            float3 wm = spec_dist.SampleWm(wo, u);\n\n            float etap = 0.f;\n            float3 wi;\n            if (!Refract(wo, Faceforward(wm, float3(0, 0, 1)), eta, etap, wi))\n            {\n                return bsdf_sample;\n            }\n            bsdf_sample.wi = wi;\n            bsdf_sample.flags = BSDF_GlossyReflection;\n            bsdf_sample.eta = etap;\n        }\n        else if (uc < prob_spec_reflect + prob_spec_trans + prob_clearcoat)\n        {\n            // Sample clearcoat\n            bsdf_sample.wi = DisneyClearcoatSample(clearcoat_gloss, wo, u);\n            bsdf_sample.flags = BSDF_GlossyReflection;\n            bsdf_sample.eta = 1;\n        }\n        else\n        {\n            // Sample diffuse\n            bsdf_sample.wi = SampleCosineHemisphere(u);\n            bsdf_sample.flags = BSDF_DiffuseReflection;\n            bsdf_sample.eta = 1;\n        }\n\n        bsdf_sample.f = Eval(wo, bsdf_sample.wi, mode);\n        bsdf_sample.pdf = PDF(wo, bsdf_sample.wi, mode, flags);\n\n        return bsdf_sample;\n    }\n\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/LayeredBSDF.hlsli",
    "content": "#ifndef LAYERED_BSDF_HLSLI\n#define LAYERED_BSDF_HLSLI\n\n#include \"DiffuseBSDF.hlsli\"\n#include \"../../Random.hlsli\"\n\n#define TopBxDF DiffuseBSDF\n#define BottomBxDF DiffuseBSDF\n\n// template<typename TopBxDF, typename BottomBxDF>\nstruct TopOrBottomBSDF\n{\n    TopBxDF top;\n    BottomBxDF bottom;\n    bool has_top;\n\n    void SetTop(TopBxDF top_)\n    {\n        top = top_;\n        has_top = true;\n    }\n\n    void SetBottom(BottomBxDF bottom_)\n    {\n        bottom = bottom_;\n        has_top = false;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        return has_top ? top.Eval(wo, wi, mode) : bottom.Eval(wo, wi, mode);\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        return has_top ? top.PDF(wo, wi, mode, flags) : bottom.PDF(wo, wi, mode, flags);\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        return has_top ? top.Samplef(wo, uc, u, mode, flags) : bottom.Samplef(wo, uc, u, mode, flags);\n    }\n};\n\n// template<typename TopBxDF, typename BottomBxDF>\nstruct LayeredBSDF\n{\n    TopBxDF top;\n    BottomBxDF bottom;\n    bool two_side;\n\n    float thickness;\n    uint max_depth;\n    float3 albedo;\n    float g;\n    uint sample_count;\n\n    void Init()\n    {\n\n    }\n\n    uint Flags()\n    {\n        uint top_flags = top.Flags();\n        uint bottom_flags = bottom.Flags();\n        uint flags = BSDF_Reflection;\n \n        if(IsSpecular(top_flags))\n        {\n            flags |= BSDF_Specular;\n        }\n\n        if(IsDiffuse(top_flags) || IsDiffuse(bottom_flags) || !IsBlack(albedo))\n        {\n            flags |= BSDF_Glossy;\n        }\n\n        if(IsTransmissive(top_flags) && IsTransmissive(bottom_flags))\n        {\n            flags |= BSDF_Transmission;\n        }\n\n        return flags;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        float3 f = 0.f;\n        if(two_side && wo.z < 0)\n        {\n            wo = -wo;\n            wi = -wi;\n        }\n\n        // Entrance interface\n        TopOrBottomBSDF enter_interface;\n        bool entered_top = two_side || wo.z > 0;\n        if(entered_top)\n        {\n            enter_interface.SetTop(top);\n        }\n        else\n        {\n            enter_interface.SetBottom(bottom);\n        }\n\n        // Exit interface and exit Z\n        TopOrBottomBSDF exit_interface, non_exit_interface;\n        if(SameHemisphere(wo, wi) ^ entered_top)\n        {\n            exit_interface.SetBottom(bottom);\n            non_exit_interface.SetTop(top);\n        }\n        else\n        {\n            exit_interface.SetTop(top);\n            non_exit_interface.SetBottom(bottom);\n        }\n\n        float exit_z = (SameHemisphere(wo, wi) ^ entered_top) ? 0 : thickness;\n\n        // Setup RNG\n        PCGSampler rng;\n        rng.seed = HashCombine(Hash(wo), Hash(wi));\n\n        for(int s = 0; s < sample_count; s++)\n        {\n            // Random walk\n            float uc = rng.Get1D();\n            BSDFSample wos = enter_interface.Samplef(wo, uc, float2(rng.Get1D(), rng.Get1D()), mode, SampleFlags_Transmission);\n            if(wos.pdf == 0 || IsBlack(wos.f) || wos.wi || wos.wi.z == 0)\n            {\n                continue;\n            }\n\n            uc = rng.Get1D();\n            BSDFSample wis = enter_interface.Samplef(wi, uc, float2(rng.Get1D(), rng.Get1D()), !mode, SampleFlags_Transmission);\n            if(wis.pdf == 0 || IsBlack(wis.f) || wis.wi || wis.wi.z == 0)\n            {\n                continue;\n            }\n\n            float3 beta = wos.f * AbsCosTheta(wos.wi) / wos.pdf;\n            float z = entered_top ? thickness : 0;\n            float3 w = wos.wi;\n        }\n\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/BSDF/ThinDielectricBSDF.hlsli",
    "content": "#ifndef THIN_DIELECTRIC_BSDF_HLSLI\n#define THIN_DIELECTRIC_BSDF_HLSLI\n\n#include \"BSDF.hlsli\"\n#include \"../Scattering.hlsli\"\n#include \"../Fresnel.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct ThinDielectricBSDF\n{\n    float3 R;\n    float3 T;\n    float eta;\n\n    void Init(float3 R_, float3 T_, float eta_)\n    {\n        R = R_;\n        T = T_;\n        eta = eta_;\n    }\n\n    uint Flags()\n    {\n        return BSDF_Reflection | BSDF_Transmission | BSDF_Specular;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        return 0.f;\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        return 0.f;\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample;\n        bsdf_sample.Init();\n\n        float F = FresnelDielectric(AbsCosTheta(wo), eta);\n\n        if(F < 1)\n        {\n            F += Sqr(1 - F) * F / (1 - Sqr(F));\n        }\n\n        float pr = F;\n        float pt = 1 - F;\n\n        if(!(flags & BSDF_Reflection))\n        {\n            pr = 0.f;\n        }\n        if(!(flags & BSDF_Transmission))\n        {\n            pt = 0.f;\n        }\n        if(pr == 0 && pt == 0)\n        {\n            return bsdf_sample;\n        }\n\n        if(uc < pr / (pr + pt))\n        {\n            float3 wi = float3(-wo.x, -wo.y, wo.z);\n            \n            bsdf_sample.f = R * F / AbsCosTheta(wi);\n            bsdf_sample.wi = wi;\n            bsdf_sample.pdf = pr / (pr + pt);\n            bsdf_sample.flags = BSDF_SpecularReflection;\n            bsdf_sample.eta = 1;\n\n            return bsdf_sample;\n        }\n        else\n        {\n            float3 wi = -wo;\n\n            bsdf_sample.f = T * (1 - F) / AbsCosTheta(wi);\n            bsdf_sample.wi = wi;\n            bsdf_sample.pdf = pt / (pr + pt);\n            bsdf_sample.flags = BSDF_SpecularTransmission;\n            bsdf_sample.eta = 1;\n\n            return bsdf_sample;\n        }\n\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Fresnel.hlsli",
    "content": "#ifndef FRESNEL_HLSLI\n#define FRESNEL_HLSLI\n\n#include \"../Math.hlsli\"\n\nstruct FresnelOp\n{\n    float3 Eval(float cos_theta_i)\n    {\n        return 1.f;\n    }\n};\n\nfloat FresnelDielectric(float cos_theta_i, float eta)\n{\n   cos_theta_i = clamp(cos_theta_i, -1, 1);\n   // Potentially flip interface orientation for Fresnel equations\n   if (cos_theta_i < 0)\n   {\n       eta = 1 / eta;\n       cos_theta_i = -cos_theta_i;\n   }\n\n   // Compute $\\cos\\,\\theta_\\roman{t}$ for Fresnel equations using Snell's law\n   float sin2Theta_i = 1 - Sqr(cos_theta_i);\n   float sin2Theta_t = sin2Theta_i / Sqr(eta);\n   if (sin2Theta_t >= 1)\n   {\n       return 1.f;\n   }\n   float cos_theta_t = sqrt(1 - sin2Theta_t);\n\n   float r_parl = (eta * cos_theta_i - cos_theta_t) / (eta * cos_theta_i + cos_theta_t);\n   float r_perp = (cos_theta_i - eta * cos_theta_t) / (cos_theta_i + eta * cos_theta_t);\n   return (Sqr(r_parl) + Sqr(r_perp)) / 2;\n}\n\n// struct FresnelDielectric\n// {\n//     float eta_i;\n//     float eta_t;\n    \n//     float Eval(float cos_theta_i)\n//     {\n//         cos_theta_i = clamp(cos_theta_i, -1.0, 1.0);\n\n// \t    // Potentially swap indices of refraction\n//         if (cos_theta_i <= 0.f)\n//         {\n// \t\t// Swap\n//             float temp = eta_i;\n//             eta_i = eta_t;\n//             eta_t = temp;\n//             cos_theta_i = abs(cos_theta_i);\n//         }\n\n//         float sin_theta_i = sqrt(max(0.0, 1.0 - cos_theta_i * cos_theta_i));\n//         float sin_theta_t = eta_i / eta_t * sin_theta_i;\n//         if (sin_theta_t >= 1.0)\n//         {\n//             return 1.f;\n//         }\n\n//         float cos_theta_t = sqrt(max(0.0, 1.0 - sin_theta_t * sin_theta_t));\n//         float Rparl = ((eta_t * cos_theta_i) - (eta_i * cos_theta_t)) /\n// \t              ((eta_t * cos_theta_i) + (eta_i * cos_theta_t));\n//         float Rperp = ((eta_i * cos_theta_i) - (eta_t * cos_theta_t)) /\n// \t              ((eta_i * cos_theta_i) + (eta_t * cos_theta_t));\n\n//         return (Rparl * Rparl + Rperp * Rperp) * 0.5f;\n//     }\n// };\n\nfloat3 FresnelConductor(float cos_theta_i, float3 eta, float3 k)\n{\n    cos_theta_i = clamp(cos_theta_i, -1.0, 1.0);\n\n    float cos_theta_i2 = cos_theta_i * cos_theta_i;\n    float sin_theta_i2 = 1.0 - cos_theta_i2;\n    float3 eta2 = eta * eta;\n    float3 etak2 = k * k;\n\n    float3 t0 = eta2 - etak2 - sin_theta_i2;\n    float3 a2plusb2 = sqrt(t0 * t0 + 4.0 * eta2 * etak2);\n    float3 t1 = a2plusb2 + cos_theta_i2;\n    float3 a = sqrt(0.5 * (a2plusb2 + t0));\n    float3 t2 = 2.0 * cos_theta_i * a;\n    float3 Rs = (t1 - t2) / (t1 + t2);\n\n    float3 t3 = cos_theta_i2 * a2plusb2 + sin_theta_i2 * sin_theta_i2;\n    float3 t4 = t2 * sin_theta_i2;\n    float3 Rp = Rs * (t3 - t4) / (t3 + t4);\n\n    return 0.5 * (Rp + Rs);\n}\n\n//struct FresnelConductor\n//{\n//    float3 eta_i;\n//    float3 eta_t;\n//    float3 k;\n//        \n//    float3 Eval(float cos_theta_i)\n//    {\n//        cos_theta_i = clamp(cos_theta_i, -1.0, 1.0);\n//\n//        float3 eta = eta_t / eta_i;\n//        float3 etak = k / eta_i;\n//\n//        float cos_theta_i2 = cos_theta_i * cos_theta_i;\n//        float sin_theta_i2 = 1.0 - cos_theta_i2;\n//        float3 eta2 = eta * eta;\n//        float3 etak2 = etak * etak;\n//\n//        float3 t0 = eta2 - etak2 - sin_theta_i2;\n//        float3 a2plusb2 = sqrt(t0 * t0 + 4.0 * eta2 * etak2);\n//        float3 t1 = a2plusb2 + cos_theta_i2;\n//        float3 a = sqrt(0.5 * (a2plusb2 + t0));\n//        float3 t2 = 2.0 * cos_theta_i * a;\n//        float3 Rs = (t1 - t2) / (t1 + t2);\n//\n//        float3 t3 = cos_theta_i2 * a2plusb2 + sin_theta_i2 * sin_theta_i2;\n//        float3 t4 = t2 * sin_theta_i2;\n//        float3 Rp = Rs * (t3 - t4) / (t3 + t4);\n//\n//        return 0.5 * (Rp + Rs);\n//    }\n//};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/ConductorMaterial.hlsli",
    "content": "#ifndef CONDUCTOR_MATERIAL_HLSLI\n#define CONDUCTOR_MATERIAL_HLSLI\n\n#include \"../BSDF/ConductorBSDF.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct ConductorMaterial\n{\n    ConductorBSDF conductor;\n    Frame frame;\n\n    GBufferData GetGBufferData()\n    {\n        GBufferData data;\n        data.albedo = conductor.R;\n        data.metallic = 1.f;\n        data.roughness = conductor.distribution.alpha_x;\n        data.anisotropic = 0.f;\n        data.normal = frame.z;\n        data.emissive = 0.f;\n        return data;\n    }\n\n    void Init(float3 R, float roughness, float3 eta, float3 k, float3 normal)\n    {\n        conductor.Init(SRGBtoLINEAR(R), roughness, eta, k);\n        frame.FromZ(normal);\n    }\n    \n    uint Flags()\n    {\n        return conductor.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        return conductor.Eval(frame.ToLocal(woW), frame.ToLocal(wiW), mode) * abs(dot(wiW, frame.z));\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return conductor.PDF(frame.ToLocal(woW), frame.ToLocal(wiW), mode, flags);\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample = conductor.Samplef(frame.ToLocal(woW), uc, u, mode, flags);\n        bsdf_sample.wiW = frame.ToWorld(bsdf_sample.wi);\n        bsdf_sample.f *= abs(dot(bsdf_sample.wiW, frame.z));\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/DielectricMaterial.hlsli",
    "content": "#ifndef DIELECTRIC_MATERIAL_HLSLI\n#define DIELECTRIC_MATERIAL_HLSLI\n\n#include \"../BSDF/DielectricBSDF.hlsli\"\n\nstruct DielectricMaterial\n{\n    DielectricBSDF dielectric;\n    Frame frame;\n\n    GBufferData GetGBufferData()\n    {\n        GBufferData data;\n        data.albedo = dielectric.R;\n        data.metallic = 0.f;\n        data.roughness = dielectric.distribution.alpha_x;\n        data.anisotropic = 0.f;\n        data.normal = frame.z;\n        data.emissive = 0.f;\n        return data;\n    }\n\n    void Init(float3 R, float3 T, float ior, float roughness, float3 normal)\n    {\n        dielectric.Init(SRGBtoLINEAR(R), SRGBtoLINEAR(T), ior, roughness);\n        frame.FromZ(normal);\n    }\n\n    uint Flags()\n    {\n        return dielectric.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        return dielectric.Eval(frame.ToLocal(woW), frame.ToLocal(wiW), mode) * abs(dot(wiW, frame.z));\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return dielectric.PDF(frame.ToLocal(woW), frame.ToLocal(wiW), mode, flags);\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample = dielectric.Samplef(frame.ToLocal(woW), uc, u, mode, flags);\n        bsdf_sample.wiW = frame.ToWorld(bsdf_sample.wi);\n        bsdf_sample.f *= abs(dot(bsdf_sample.wiW, frame.z));\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/DiffuseMaterial.hlsli",
    "content": "#ifndef DIFFUSE_MATERIAL_HLSLI\n#define DIFFUSE_MATERIAL_HLSLI\n\n#include \"../BSDF/DiffuseBSDF.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct DiffuseMaterial\n{\n    DiffuseBSDF diffuse;\n    Frame frame;\n\n    GBufferData GetGBufferData()\n    {\n        GBufferData data;\n        data.albedo = diffuse.R;\n        data.metallic = 0.f;\n        data.roughness = 1.f;\n        data.anisotropic = 0.f;\n        data.normal = frame.z;\n        data.emissive = 0.f;\n        return data;\n    }\n    \n    void Init(float3 R, float3 normal)\n    {\n        diffuse.Init(SRGBtoLINEAR(R));\n        frame.FromZ(normal);\n    }\n    \n    uint Flags()\n    {\n        return diffuse.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n      //  return frame.z;\n        return diffuse.Eval(frame.ToLocal(woW), frame.ToLocal(wiW), mode) * abs(dot(wiW, frame.z));\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return diffuse.PDF(frame.ToLocal(woW), frame.ToLocal(wiW), mode, flags);\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample = diffuse.Samplef(frame.ToLocal(woW), uc, u, mode, flags);\n        bsdf_sample.wiW = frame.ToWorld(bsdf_sample.wi);\n        bsdf_sample.f *= abs(dot(bsdf_sample.wiW, frame.z));\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/DisneyMaterial.hlsli",
    "content": "#ifndef PRINCIPLED_MATERIAL_HLSLI\n#define PRINCIPLED_MATERIAL_HLSLI\n\n#include \"../BSDF/DisneyBSDF.hlsli\"\n#include \"../Scattering.hlsli\"\n#include \"../Fresnel.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Common.hlsli\"\n#include \"../../Interaction.hlsli\"\n\nstruct DisneyMaterial\n{\n    DisneyBSDF disney;\n    Frame frame;\n\n    void Init(\n        float3 base_color,\n        float metallic,\n        float roughness,\n        float anisotropic,\n        float sheen,\n        float sheen_tint,\n        float specular,\n        float spec_tint,\n        float clearcoat,\n        float clearcoat_gloss,\n        float flatness,\n        float spec_trans,\n        float eta,\n        float3 emissive,\n        bool twoside,\n        float3 normal)\n    {\n        frame.FromZ(normal);\n        disney.Init(base_color, roughness, anisotropic, \n            spec_trans, eta, sheen, sheen_tint, specular, spec_tint, metallic, clearcoat,\n            clearcoat_gloss, flatness, emissive, twoside);\n    }\n\n    GBufferData GetGBufferData()\n    {\n        GBufferData data;\n        data.albedo = disney.base_color;\n        data.metallic = disney.metallic;\n        data.roughness = disney.roughness;\n        data.anisotropic = disney.anisotropic;\n        data.normal = frame.z;\n        data.emissive = disney.emissive;\n        return data;\n    }\n\n    uint Flags()\n    {\n        return disney.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        return disney.Eval(frame.ToLocal(woW), frame.ToLocal(wiW), mode) * abs(dot(wiW, frame.z));\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return disney.PDF(frame.ToLocal(woW), frame.ToLocal(wiW), mode, flags);\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample = disney.Samplef(frame.ToLocal(woW), uc, u, mode, flags);\n        bsdf_sample.wiW = frame.ToWorld(bsdf_sample.wi);\n        bsdf_sample.f *= abs(dot(bsdf_sample.wiW, frame.z));\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/MaskedMaterial.hlsli",
    "content": "#ifndef MASK_MATERIAL_HLSLI\n#define MASK_MATERIAL_HLSLI\n\n#include \"../BSDF/BSDF.hlsli\"\n#include \"../Scattering.hlsli\"\n#include \"../Fresnel.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Interaction.hlsli\"\n\ntemplate<typename T>\nstruct MaskedMaterial\n{\n    T material;\n    float alpha;\n    float threshold;\n    \n    GBufferData GetGBufferData()\n    {\n        return material.GetGBufferData();\n    }\n\n    void Init(T material_, float alpha_, float threshold_)\n    {\n        material = material_;\n        alpha = alpha_;\n        threshold = threshold_;\n    }\n\n    uint Flags()\n    {\n        return threshold < alpha ? material.Flags() : BSDF_Transmission;\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        return threshold < alpha ?\n            material.Eval(woW, wiW, mode) :\n            1.f;\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return threshold < alpha ?\n            material.PDF(woW, wiW, mode, flags) :\n            1.f;\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample;\n        if(threshold < alpha)\n        {\n            bsdf_sample = material.Samplef(woW, uc, u, mode, flags);\n        }\n        else\n        {\n            float3 wi = material.frame.ToLocal(-woW);\n            bsdf_sample.f = 1.f;\n            bsdf_sample.wiW = -woW;\n            bsdf_sample.pdf = 1.f;\n            bsdf_sample.flags = BSDF_SpecularTransmission;\n            bsdf_sample.eta = 1.f;\n        }\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/MixMaterial.hlsli",
    "content": "#ifndef MIX_BSDF_HLSLI\n#define MIX_BSDF_HLSLI\n\n#include \"../BSDF/BSDF.hlsli\"\n#include \"../../Math.hlsli\"\n#include \"../../Random.hlsli\"\n#include \"../../Interaction.hlsli\"\n\ntemplate<typename T1, typename T2>\nstruct MixMaterial\n{\n    T1 material1;\n    T2 material2;\n    float weight;\n\n    GBufferData GetGBufferData()\n    {\n        GBufferData data1 = material1.GetGBufferData();\n        GBufferData data2 = material2.GetGBufferData();\n        GBufferData data;\n        data.normal = lerp(data1.normal, data2.normal, weight);\n        data.albedo = lerp(data1.albedo, data2.albedo, weight);\n        data.emissive = lerp(data1.emissive, data2.emissive, weight);\n        data.metallic = lerp(data1.metallic, data2.metallic, weight);\n        data.roughness = lerp(data1.roughness, data2.roughness, weight);\n        data.anisotropic = lerp(data1.anisotropic, data2.anisotropic, weight);\n        return data;\n\n    }\n\n    void Init(T1 material1_, T2 material2_, float weight_)\n    {\n        material1 = material1_;\n        material2 = material2_;\n        weight = weight_;\n    }\n\n    uint Flags()\n    {\n        return material1.Flags() | material2.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        if(weight <= 0)\n        {\n            return material1.Eval(woW, wiW, mode);\n        }\n        else if(weight >= 1)\n        {\n            return material2.Eval(woW, wiW, mode);\n        }\n        return lerp(material1.Eval(woW, wiW, mode), material2.Eval(woW, wiW, mode), weight);\n        // PCGSampler rng;\n        // rng.seed = HashCombine(Hash(woW), Hash(wiW));\n\n        // if(rng.Get1D() < weight)\n        // {\n        //     return material1.Eval(woW, wiW, mode);\n        // }\n        // else\n        // {\n        //     return material2.Eval(woW, wiW, mode);\n        // }\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        if(weight <= 0)\n        {\n            return material1.PDF(woW, wiW, mode, flags);\n        }\n        else if(weight >= 1)\n        {\n            return material2.PDF(woW, wiW, mode, flags);\n        }\n        return lerp(material1.PDF(woW, wiW, mode, flags), material2.PDF(woW, wiW, mode, flags), weight);\n\n        // PCGSampler rng;\n        // rng.seed = HashCombine(Hash(woW), Hash(wiW));\n\n        // if(rng.Get1D() < weight)\n        // {\n        //     return material1.PDF(woW, wiW, mode, flags);\n        // }\n        // else\n        // {\n        //     return material2.PDF(woW, wiW, mode, flags);\n        // }\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        if(weight <= 0)\n        {\n            return material1.Samplef(woW, uc, u, mode, flags);\n        }\n        else if(weight >= 1)\n        {\n            return material2.Samplef(woW, uc, u, mode, flags);\n        }\n\n        BSDFSample bsdf_sample;\n        bsdf_sample.Init();\n\n        if(uc < weight)\n        {\n            bsdf_sample = material1.Samplef(woW, uc, u, mode, flags);\n            bsdf_sample.pdf *= weight;\n        }\n        else\n        {\n            bsdf_sample = material2.Samplef(woW, uc, u, mode, flags);\n            bsdf_sample.pdf *= 1 - weight;\n        }\n\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material/ThinDielectricMaterial.hlsli",
    "content": "#ifndef THIN_DIELECTRIC_MATERIAL_HLSLI\n#define THIN_DIELECTRIC_MATERIAL_HLSLI\n\n#include \"../BSDF/ThinDielectricBSDF.hlsli\"\n\nstruct ThinDielectricMaterial\n{\n    ThinDielectricBSDF thin_dielectric;\n    Frame frame;\n\n    GBufferData GetGBufferData()\n    {\n        GBufferData data;\n        data.albedo = thin_dielectric.R;\n        data.metallic = 0.f;\n        data.roughness = 0.f;\n        data.anisotropic = 0.f;\n        data.normal = frame.z;\n        data.emissive = 0.f;\n        return data;\n    }\n\n    void Init(float3 R, float3 T, float eta, float3 normal)\n    {\n        thin_dielectric.Init(SRGBtoLINEAR(R), SRGBtoLINEAR(T), eta);\n        frame.FromZ(normal);\n    }\n\n    uint Flags()\n    {\n        return thin_dielectric.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        return thin_dielectric.Eval(frame.ToLocal(woW), frame.ToLocal(wiW), mode) * abs(dot(wiW, frame.z));\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return thin_dielectric.PDF(frame.ToLocal(woW), frame.ToLocal(wiW), mode, flags);\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample bsdf_sample = thin_dielectric.Samplef(frame.ToLocal(woW), uc, u, mode, flags);\n        bsdf_sample.wiW = frame.ToWorld(bsdf_sample.wi);\n        bsdf_sample.f *= abs(dot(bsdf_sample.wiW, frame.z));\n        return bsdf_sample;\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Material.hlsli",
    "content": "#ifndef MATERIAL_HLSLI\n#define MATERIAL_HLSLI\n\n#include \"BSDF/BSDF.hlsli\"\n#include \"../Interaction.hlsli\"\n\nstruct BSDF\n{\n    void Init()\n    {\n        \n    }\n    \n    uint Flags()\n    {\n        return 0;\n    }\n\n    float3 Eval(float3 wo, float3 wi, TransportMode mode)\n    {\n        return 0;\n    }\n\n    float PDF(float3 wo, float3 wi, TransportMode mode, SampleFlags flags)\n    {\n        return 0;\n    }\n\n    BSDFSample Samplef(float3 wo, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        BSDFSample sample_;\n        return sample_;\n    }\n    \n    // For GBuffer generation\n    GBufferData GetGBufferData()\n    {\n        GBufferData data;\n        data.normal = 0.f;\n        data.albedo = 0.f;\n        data.emissive = 0.f;\n        data.metallic = 0.f;\n        data.roughness = 0.f;\n        data.anisotropic = 0.f;\n        return data;\n    }\n};\n\nstruct Material\n{\n    BSDF bsdf;\n    \n    void Init(SurfaceInteraction surface_interaction)\n    {\n        bsdf.Init();\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Scattering.hlsli",
    "content": "#ifndef MICROFACET_HLSLI\n#define MICROFACET_HLSLI\n\n#include \"../Math.hlsli\"\n#include \"../Interaction.hlsli\"\n\n//bool Refract(float3 wi, float3 n, float eta, out float3 wt)\n//{\n//    float cos_theta_i = dot(wi, n);\n//    float sin_2_theta_i = max(0.0, 1.0 - cos_theta_i * cos_theta_i);\n//    float sin_2_theta_t = eta * eta * sin_2_theta_i;\n//\n//    if (sin_2_theta_t >= 1.0)\n//    {\n//        return false;\n//    }\n//\n//    float cos_theta_t = sqrt(1.0 - sin_2_theta_t);\n//\n//    wt = eta * (-wi) + (eta * cos_theta_i - cos_theta_t) * n;\n//\n//    return true;\n//}\n\nbool Refract(float3 wi, float3 n, float eta, out float etap, out float3 wt)\n{\n    float cos_theta_i = dot(n, wi);\n    // Potentially flip interface orientation for Snell's law\n    if (cos_theta_i < 0)\n    {\n        eta = 1 / eta;\n        cos_theta_i = -cos_theta_i;\n        n = -n;\n    }\n\n    // Compute $\\cos\\,\\theta_\\roman{t}$ using Snell's law\n    float sin2Theta_i = max(0, 1 - Sqr(cos_theta_i));\n    float sin2Theta_t = sin2Theta_i / Sqr(eta);\n    // Handle total internal reflection case\n    if (sin2Theta_t >= 1)\n    {\n        return false;\n    }\n    \n    float cos_theta_t = sqrt(1 - sin2Theta_t);\n\n    wt = -wi / eta + (cos_theta_i / eta - cos_theta_t) * n;\n    // Provide relative IOR along ray to caller\n    etap = eta;\n    \n    return true;\n}\n\nfloat3 Reflect(float3 wo, float3 n)\n{\n    return -wo + 2 * dot(wo, n) * n;\n}\n\n//float HenyeyGreenstein(float cos_theta, float g)\n//{\n//    float denom = 1 + Sqr(g) + 2 * g * cos_theta;\n//    return Inv4PI * (1 - Sqr(g)) / (denom * sqrt(denom));\n//}\n\n//float FresnelDielectric(float cos_theta_i, float eta)\n//{\n//    cos_theta_i = clamp(cos_theta_i, -1, 1);\n//    // Potentially flip interface orientation for Fresnel equations\n//    if (cos_theta_i < 0)\n//    {\n//        eta = 1 / eta;\n//        cos_theta_i = -cos_theta_i;\n//    }\n//\n//    // Compute $\\cos\\,\\theta_\\roman{t}$ for Fresnel equations using Snell's law\n//    float sin2Theta_i = 1 - Sqr(cos_theta_i);\n//    float sin2Theta_t = sin2Theta_i / Sqr(eta);\n//    if (sin2Theta_t >= 1)\n//    {\n//        return 1.f;\n//    }\n//    float cos_theta_t = sqrt(1 - sin2Theta_t);\n//\n//    float r_parl = (eta * cos_theta_i - cos_theta_t) / (eta * cos_theta_i + cos_theta_t);\n//    float r_perp = (cos_theta_i - eta * cos_theta_t) / (cos_theta_i + eta * cos_theta_t);\n//    return (Sqr(r_parl) + Sqr(r_perp)) / 2;\n//}\n//\n//float FresnelComplex(float cos_theta_i, Complex eta)\n//{\n//    Complex cos_theta_i_ = ComplexFromReal(clamp(cos_theta_i, 0, 1));\n//    // Compute complex $\\cos\\,\\theta_\\roman{t}$ for Fresnel equations using Snell's law\n//    Complex sin2Theta_i = Sub(ComplexFromReal(1), Mul(cos_theta_i_, cos_theta_i_));\n//    Complex sin2Theta_t = Div(sin2Theta_i, Mul(eta, eta));\n//    Complex cos_theta_t = Sqrt(Sub(ComplexFromReal(1), sin2Theta_t));\n//    \n//    Complex r_parl = Div(Sub(Mul(eta, cos_theta_i_), cos_theta_t), Add(Mul(eta, cos_theta_i_), cos_theta_t));\n//    Complex r_perp = Div(Sub(cos_theta_i_, Mul(eta, cos_theta_t)), Add(Mul(eta, cos_theta_t), cos_theta_i_));\n//\n//    return (Norm(r_parl) + Norm(r_perp)) / 2;\n//}\n//\n//float3 FresnelComplex(float cos_theta_i, float3 eta, float3 k)\n//{\n//    float3 result;\n//    result.x = FresnelComplex(cos_theta_i, CreateComplex(eta.x, k.x));\n//    result.y = FresnelComplex(cos_theta_i, CreateComplex(eta.y, k.y));\n//    result.z = FresnelComplex(cos_theta_i, CreateComplex(eta.z, k.z));\n//    return result;\n//}\n\n//struct TrowbridgeReitzDistribution\n//{\n//    float alpha_x, alpha_y;\n//    \n//    bool EffectivelySmooth()\n//    {\n//        return max(alpha_x, alpha_y) < 1e-3f;\n//    }\n//    \n//    void Init(float ax, float ay)\n//    {\n//        alpha_x = ax;\n//        alpha_y = ay;\n//        if (!EffectivelySmooth())\n//        {\n//            alpha_x = max(alpha_x, 1e-4f);\n//            alpha_y = max(alpha_y, 1e-4f);\n//        }\n//    }\n//    \n//    float D(float3 wm)\n//    {\n//        float tan_2_theta = Tan2Theta(wm);\n//        if (isinf(tan_2_theta))\n//        {\n//            return 0;\n//        }\n//        float cos_4_theta = Sqr(Cos2Theta(wm));\n//        if (cos_4_theta < 1e-16f)\n//        {\n//            return 0;\n//        }\n//        float e = tan_2_theta * (Sqr(CosPhi(wm) / alpha_x) + Sqr(SinPhi(wm) / alpha_y));\n//        return 1 / (PI * alpha_x * alpha_y * cos_4_theta * Sqr(1 + e));\n//    }\n//    \n//    float Lambda(float3 w)\n//    {\n//        float tan_2_theta = Tan2Theta(w);\n//        if (isinf(tan_2_theta))\n//        {\n//            return 0;\n//        }\n//        float alpha2 = Sqr(CosPhi(w) * alpha_x) + Sqr(SinPhi(w) * alpha_y);\n//        return (sqrt(1 + alpha2 * tan_2_theta) - 1) / 2;\n//    }\n//    \n//    float G1(float3 w)\n//    {\n//        return 1 / (1 + Lambda(w));\n//    }\n//    \n//    float G(float3 wo, float3 wi)\n//    {\n//        return 1 / (1 + Lambda(wo) + Lambda(wi));\n//    }\n//    \n//    float D(float3 w, float3 wm)\n//    {\n//        return G1(w) / AbsCosTheta(w) * D(wm) * abs(dot(w, wm));\n//    }\n//    \n//    float PDF(float3 w, float3 wm)\n//    {\n//        return D(w, wm);\n//    }\n//    \n//    float3 Sample_wm(float3 w, float2 u)\n//    {\n//        // Reference: https://jcgt.org/published/0007/04/01/paper.pdf\n//        float3 vh = normalize(float3(alpha_x * w.x, alpha_y * w.y, w.z));\n//        \n//        float len = vh.x * vh.x + vh.y * vh.y;\n//        float3 T1 = len > 0 ? float3(-vh.y, -vh.x, 0.f) / sqrt(len) : float3(1, 0, 0);\n//        float3 T2 = cross(vh, T1);\n//        \n//        float2 p = UniformSampleDisk(u);\n//        float s = 0.5 * (1.0 + vh.z);\n//        p.y = (1.0 - s) * sqrt(1.0 - p.x * p.x) + s * p.y;\n//        float3 nh = p.x * T1 + p.y * T2 + sqrt(max(0, 1.0 - p.x * p.x - p.y * p.y)) * vh;\n//        \n//        return normalize(float3(alpha_x * nh.x, alpha_y * nh.y, max(0, nh.z)));\n//    }\n//    \n//    float RoughnessToAlpha(float roughness)\n//    {\n//        return sqrt(roughness);\n//    }\n//    \n//    void Regularize()\n//    {\n//        if (alpha_x < 0.3f)\n//        {\n//            alpha_x = clamp(2 * alpha_x, 0.1f, 0.3f);\n//        }\n//        if (alpha_y < 0.3f)\n//        {\n//            alpha_y = clamp(2 * alpha_y, 0.1f, 0.3f);\n//        }\n//    }\n//};\n\n// Beckmann Distribution\nvoid BeckmannSample11(float cos_theta_i, float u1, float u2, out float slope_x, out float slope_y)\n{\n    if (cos_theta_i > .9999)\n    {\n        float r = sqrt(-log(1.0 - u1));\n        float sin_phi = sin(2 * PI * u2);\n        float cos_phi = cos(2 * PI * u2);\n        slope_x = r * cos_phi;\n        slope_y = r * sin_phi;\n        return;\n    }\n\n    float sin_theta_i = sqrt(max(0.0, 1.0 - cos_theta_i * cos_theta_i));\n    float tan_theta_i = sin_theta_i / cos_theta_i;\n    float cot_theta_i = 1.0 / tan_theta_i;\n\n    float a = -1.0;\n    float c = Erf(cot_theta_i);\n    float sample_x = max(u1, float(1e-6));\n\n    float theta_i = acos(cos_theta_i);\n    float fit = 1 + theta_i * (-0.876 + theta_i * (0.4265 - 0.0594 * theta_i));\n    float b = c - (1 + c) * pow(1 - sample_x, fit);\n\n    const float sqrt_inv_PI = 1.0 / sqrt(PI);\n    float normalization = 1.0 / (1.0 + c + sqrt_inv_PI * tan_theta_i * exp(-cot_theta_i * cot_theta_i));\n\n    int it = 0;\n    while (++it < 10)\n    {\n        if (!(b >= a && b <= c))\n        {\n            b = 0.5 * (a + c);\n        }\n\n        float inv_erf = ErfInv(b);\n        float value = normalization * (1 + b + sqrt_inv_PI * tan_theta_i * exp(-inv_erf * inv_erf)) - sample_x;\n        float derivative = normalization * (1 - inv_erf * tan_theta_i);\n\n        if (abs(value) < 1e-5)\n        {\n            break;\n        }\n\n        if (value > 0)\n        {\n            c = b;\n        }\n        else\n        {\n            a = b;\n        }\n\n        b -= value / derivative;\n    }\n\n    slope_x = ErfInv(b);\n    slope_y = ErfInv(2.0 * max(u2, float(1e-6)) - 1.0);\n}\n\nfloat3 BeckmannSample(float3 wi, float alpha_x, float alpha_y, float u1, float u2)\n{\n\t// stretch wi\n    float3 wiStretched = normalize(float3(alpha_x * wi.x, alpha_y * wi.y, wi.z));\n\n\t// simulate P22_{wi}(x_slope, y_slope, 1, 1)\n    float slope_x, slope_y;\n    BeckmannSample11(CosTheta(wiStretched), u1, u2, slope_x, slope_y);\n\n\t// rotate\n    float tmp = CosPhi(wiStretched) * slope_x - SinPhi(wiStretched) * slope_y;\n    slope_y = SinPhi(wiStretched) * slope_x + CosPhi(wiStretched) * slope_y;\n    slope_x = tmp;\n\n\t// unstretch\n    slope_x = alpha_x * slope_x;\n    slope_y = alpha_y * slope_y;\n\n\t// compute normal\n    return normalize(float3(-slope_x, -slope_y, 1.0));\n}\n\nstruct BeckmannDistribution\n{\n    float alpha_x;\n    float alpha_y;\n    bool sample_visible_area;\n\n    bool EffectivelySmooth() \n    { \n        return max(alpha_x, alpha_y) < 1e-3f; \n    }\n    \n    float D(float3 wm)\n    {\n        float tan_2_theta = Tan2Theta(wm);\n        if (isinf(tan_2_theta))\n        {\n            return 0.0;\n        }\n\n        float cos_4_theta = Cos2Theta(wm) * Cos2Theta(wm);\n        return exp(-tan_2_theta * (Cos2Phi(wm) / (alpha_x * alpha_x) + Sin2Phi(wm) / (alpha_y * alpha_y))) / (PI * alpha_x * alpha_y * cos_4_theta);\n    }\n    \n    float Lambda(float3 w)\n    {\n        float abs_tan_theta = abs(TanTheta(w));\n        if (isinf(abs_tan_theta))\n        {\n            return 0.;\n        }\n\n        float alpha = sqrt(Cos2Phi(w) * alpha_x * alpha_x + Sin2Phi(w) * alpha_y * alpha_y);\n        float a = 1.0 / (alpha * abs_tan_theta);\n        if (a >= 1.6)\n        {\n            return 0;\n        }\n        return (1.0 - 1.259 * a + 0.396 * a * a) / (3.535 * a + 2.181 * a * a);\n    }\n    \n    float G1(float3 w)\n    {\n        return 1.0 / (1.0 + Lambda(w));\n    }\n\n    float G(float3 wo, float3 wi)\n    {\n        return 1.0 / (1.0 + Lambda(wo) + Lambda(wi));\n    }\n    \n    float Pdf(float3 wo, float3 wm)\n    {\n        if (sample_visible_area)\n        {\n            return D(wm) * G1(wo) * abs(dot(wo, wm)) / AbsCosTheta(wo);\n        }\n        else\n        {\n            return D(wm) * AbsCosTheta(wm);\n        }\n    }\n    \n    float3 SampleWm(float3 wo, float2 u)\n    {\n        if (!sample_visible_area)\n        {\n            float tan_2_theta, phi;\n            if (alpha_x == alpha_y)\n            {\n                float log_sample = log(1 - u.x);\n                tan_2_theta = -alpha_x * alpha_x * log_sample;\n                phi = u.y * 2 * PI;\n            }\n            else\n            {\n                float log_sample = log(1 - u.x);\n                phi = atan(alpha_y / alpha_x * tan(2.0 * PI * u.y + 0.5 * PI));\n                if (u.y > 0.5)\n                {\n                    phi += PI;\n                }\n\n                float sin_phi = sin(phi);\n                float cos_phi = cos(phi);\n                float alphax2 = alpha_x * alpha_x;\n                float alphay2 = alpha_y * alpha_y;\n                tan_2_theta = -log_sample / (cos_phi * cos_phi / alphax2 + sin_phi * sin_phi / alphay2);\n            }\n\n            float cos_theta = 1.0 / sqrt(1.0 + tan_2_theta);\n            float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));\n            float3 wm = SphericalDirection(sin_theta, cos_theta, phi);\n            if (!SameHemisphere(wo, wm))\n            {\n                wm = -wm;\n            }\n            return wm;\n        }\n        else\n        {\n            float3 wm;\n            bool flip = wo.z < 0.0;\n            wm = BeckmannSample(flip ? -wo : wo, alpha_x, alpha_y, u.x, u.y);\n            if (flip)\n            {\n                wm = -wm;\n            }\n\n            return wm;\n        }\n\n        return float3(0.0, 0.0, 0.0);\n    }\n};\n\n// Trowbridge Reitz Distribution\nvoid TrowbridgeReitzSample11(float cos_theta, float u1, float u2, out float slope_x, out float slope_y)\n{\n    if (cos_theta > .9999)\n    {\n        float r = sqrt(u1 / (1 - u1));\n        float phi = 6.28318530718 * u2;\n        slope_x = r * cos(phi);\n        slope_y = r * sin(phi);\n        return;\n    }\n\n    float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));\n    float tan_theta = sin_theta / cos_theta;\n    float a = 1.0 / tan_theta;\n    float G1 = 2.0 / (1.0 + sqrt(1.0 + 1.0 / (a * a)));\n\n    float A = 2 * u1 / G1 - 1;\n    float tmp = 1.f / (A * A - 1.f);\n    if (tmp > 1e10)\n    {\n        tmp = 1e10;\n    }\n    float B = tan_theta;\n    float D = sqrt(max(float(B * B * tmp * tmp - (A * A - B * B) * tmp), float(0)));\n    float slope_x_1 = B * tmp - D;\n    float slope_x_2 = B * tmp + D;\n    slope_x = (A < 0 || slope_x_2 > 1.f / tan_theta) ? slope_x_1 : slope_x_2;\n\n    float S;\n    if (u2 > 0.5)\n    {\n        S = 1.0;\n        u2 = 2.0 * (u2 - 0.5);\n    }\n    else\n    {\n        S = -1.0;\n        u2 = 2.0 * (0.5 - u2);\n    }\n\n    float z =\n\t    (u2 * (u2 * (u2 * 0.27385 - 0.73369) + 0.46341)) /\n\t    (u2 * (u2 * (u2 * 0.093073 + 0.309420) - 1.000000) + 0.597999);\n\n    slope_y = S * z * sqrt(1.0 + slope_x * slope_x);\n}\n\nfloat3 TrowbridgeReitzSample(float3 wi, float alpha_x, float alpha_y, float u1, float u2)\n{\n\t// stretch wi\n    float3 wiStretched = normalize(float3(alpha_x * wi.x, alpha_y * wi.y, wi.z));\n\n\t// simulate P22_{wi}(x_slope, y_slope, 1, 1)\n    float slope_x, slope_y;\n    TrowbridgeReitzSample11(CosTheta(wiStretched), u1, u2, slope_x, slope_y);\n\n\t// rotate\n    float tmp = CosPhi(wiStretched) * slope_x - SinPhi(wiStretched) * slope_y;\n    slope_y = SinPhi(wiStretched) * slope_x + CosPhi(wiStretched) * slope_y;\n    slope_x = tmp;\n\n\t// unstretch\n    slope_x = alpha_x * slope_x;\n    slope_y = alpha_y * slope_y;\n\n\t// compute normal\n    return normalize(float3(-slope_x, -slope_y, 1.0));\n}\n\nstruct TrowbridgeReitzDistribution\n{\n    float alpha_x;\n    float alpha_y;\n    bool sample_visible_area;\n\n    bool EffectivelySmooth() \n    { \n        return max(alpha_x, alpha_y) < 1e-3f; \n    }\n    \n    static float RoughnessToAlpha(float roughness)\n    {\n        if(roughness <= float(1e-3))\n        {\n            return roughness;\n        }\n        roughness = max(roughness, (float) 1e-3);\n        float x = log(roughness);\n        return 1.62142f + 0.819955f * x + 0.1734f * x * x + 0.0171201f * x * x * x +\n           0.000640711f * x * x * x * x;\n    }\n    \n    float D(float3 wm)\n    {\n        float tan_2_theta = Tan2Theta(wm);\n\n        if (isinf(tan_2_theta))\n        {\n            return 0.0;\n        }\n        const float cos_4_theta = Cos2Theta(wm) * Cos2Theta(wm);\n\n        float e = (Cos2Phi(wm) / (alpha_x * alpha_x) + Sin2Phi(wm) / (alpha_y * alpha_y)) * tan_2_theta;\n        return 1 / (PI * alpha_x * alpha_y * cos_4_theta * (1 + e) * (1 + e));\n    }\n    \n    float3 SampleWm(float3 wo, float2 u)\n    {\n        float3 wm = 0.f;\n\n        if (!sample_visible_area)\n        {\n            float cos_theta = 0.0;\n            float phi = 2.0 * PI * u.y;\n\n            if (alpha_x == alpha_y)\n            {\n                float tan_theta_2 = alpha_x * alpha_x * u.x * (1.0 - u.x);\n                cos_theta = 1.0 / sqrt(1.0 + tan_theta_2);\n            }\n            else\n            {\n                phi = atan(alpha_y / alpha_x * tan(2.0 * PI * u.y + 0.5 * PI));\n                if (u.y > 0.5)\n                {\n                    phi += PI;\n                }\n                float sin_phi = sin(phi);\n                float cos_phi = cos(phi);\n\n                const float alpha_x2 = alpha_x * alpha_x;\n                const float alpha_y2 = alpha_y * alpha_y;\n\n                const float alpha_2 = 1.0 / (cos_phi * cos_phi / alpha_x2 + sin_phi * sin_phi / alpha_y2);\n                float tan_theta_2 = alpha_2 * u.x / (1.0 - u.x);\n                cos_theta = 1.0 / sqrt(1 + tan_theta_2);\n            }\n\n            float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));\n            float3 wm = SphericalDirection(sin_theta, cos_theta, phi);\n            if (!SameHemisphere(wo, wm))\n            {\n                wm = -wm;\n            }\n        }\n        else\n        {\n            bool flip = wo.z < 0.0;\n            wm = TrowbridgeReitzSample(flip ? -wo : wo, alpha_x, alpha_y, u.x, u.y);\n            if (flip)\n            {\n                wm = -wm;\n            }\n        }\n        return wm;\n    }\n\n    float Lambda(float3 w)\n    {\n        float abs_tan_theta = abs(TanTheta(w));\n        if (isinf(abs_tan_theta))\n        {\n            return 0.;\n        }\n        float alpha = sqrt(Cos2Phi(w) * alpha_x * alpha_x + Sin2Phi(w) * alpha_y * alpha_y);\n        float alpha_2_tan_2_theta = (alpha * abs_tan_theta) * (alpha * abs_tan_theta);\n        return (-1.0 + sqrt(1.0 + alpha_2_tan_2_theta)) / 2.0;\n    }\n\n    float G1(float3 w)\n    {\n        return 1.0 / (1.0 + Lambda(w));\n    }\n\n    float G(float3 wo, float3 wi)\n    {\n        return 1.0 / (1.0 + Lambda(wo) + Lambda(wi));\n    }\n\n    float Pdf(float3 wo, float3 wm)\n    {\n        if (sample_visible_area)\n        {\n            return D(wm) * G1(wo) * abs(dot(wo, wm)) / AbsCosTheta(wo);\n        }\n        else\n        {\n            return D(wm) * AbsCosTheta(wm);\n        }\n    }\n};\n\nstruct DisneyMicrofacetDistribution\n{\n    float alpha_x;\n    float alpha_y;\n    bool sample_visible_area;\n\n    bool EffectivelySmooth() \n    { \n        return max(alpha_x, alpha_y) < 1e-3f; \n    }\n    \n    float D(float3 wh)\n    {\n        float tan_2_theta = Tan2Theta(wh);\n\n        if (isinf(tan_2_theta))\n        {\n            return 0.0;\n        }\n        const float cos_4_theta = Cos2Theta(wh) * Cos2Theta(wh);\n\n        float e = (Cos2Phi(wh) / (alpha_x * alpha_x) + Sin2Phi(wh) / (alpha_y * alpha_y)) * tan_2_theta;\n        return 1 / (PI * alpha_x * alpha_y * cos_4_theta * (1 + e) * (1 + e));\n    }\n    \n    float3 SampleWh(float3 wo, float2 u)\n    {\n        float3 wh = float3(0.0, 0.0, 0.0);\n        \n        if (!sample_visible_area)\n        {\n            float cos_theta = 0.0;\n            float phi = 2.0 * PI * u.y;\n\n            if (alpha_x == alpha_y)\n            {\n                float tan_theta_2 = alpha_x * alpha_x * u.x * (1.0 - u.y);\n                cos_theta = 1.0 / sqrt(1.0 + tan_theta_2);\n            }\n            else\n            {\n                phi = atan(alpha_y / alpha_x * tan(2.0 * PI * u.y + 0.5 * PI));\n                if (u.y > 0.5)\n                {\n                    phi += PI;\n                }\n                float sin_phi = sin(phi);\n                float cos_phi = cos(phi);\n\n                const float alpha_x2 = alpha_x * alpha_x;\n                const float alpha_y2 = alpha_y * alpha_y;\n\n                const float alpha_2 = 1.0 / (cos_phi * cos_phi / alpha_x2 + sin_phi * sin_phi / alpha_y2);\n                float tan_theta_2 = alpha_2 * u.x / (1.0 - u.x);\n                cos_theta = 1.0 / sqrt(1 + tan_theta_2);\n            }\n\n            float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));\n            float3 wh = SphericalDirection(sin_theta, cos_theta, phi);\n            if (!SameHemisphere(wo, wh))\n            {\n                wh = -wh;\n            }\n        }\n        else\n        {\n            bool flip = wo.z < 0.0;\n            wh = TrowbridgeReitzSample(flip ? -wo : wo, alpha_x, alpha_y, u.x, u.y);\n            if (flip)\n            {\n                wh = -wh;\n            }\n        }\n        return wh;\n    }\n\n    float Lambda(float3 w)\n    {\n        float abs_tan_theta = abs(TanTheta(w));\n        if (isinf(abs_tan_theta))\n        {\n            return 0.;\n        }\n        float alpha = sqrt(Cos2Phi(w) * alpha_x * alpha_x + Sin2Phi(w) * alpha_y * alpha_y);\n        float alpha_2_tan_2_theta = (alpha * abs_tan_theta) * (alpha * abs_tan_theta);\n        return (-1.0 + sqrt(1.0 + alpha_2_tan_2_theta)) / 2.0;\n    }\n\n    float G1(float3 w)\n    {\n        return 1.0 / (1.0 + Lambda(w));\n    }\n\n    float G(float3 wo, float3 wi)\n    {\n        return G1(wo) * G1(wi);\n    }\n\n    float Pdf(float3 wo, float3 wh)\n    {\n        if (sample_visible_area)\n        {\n            return D(wh) * G1(wo) * abs(dot(wo, wh)) / AbsCosTheta(wo);\n        }\n        else\n        {\n            return D(wh) * AbsCosTheta(wh);\n        }\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material/Template.material.hlsli",
    "content": "#ifndef MATERIAL_HLSLI\n#define MATERIAL_HLSLI\n\n#include \"../Attribute.hlsli\"\n#include \"../Random.hlsli\"\n\n#include \"BSDF/BSDF.hlsli\"\n\n{{#Textures}}\nTexture2D<float4> {{Texture}};\n{{/Textures}}\n\n{{#Samplers}}\nSamplerState {{Sampler}};\n{{/Samplers}}\n\nstruct BSDF\n{\n    {{&BxDFType\n}} {{&BxDFName}}\n\nvoid Init()\n{\n        {{#Initializations}}\n        {{ & Initialization\n                }\n            }\n        {{ / Initializations\n                }\n            }\n        }\n\n        float3 Eval\n        (\n        float3 wo, float3 wi, TransportMode\n        mode)\n    {\n            return {{ & BxDFName\n                }\n            }.\n            Eval(wo, wi, mode);\n        }\n\n        float PDF\n        (\n        float3 wo, float3 wi, TransportMode\n        mode, SampleFlags\n        flags)\n    {\n            return {{ & BxDFName\n                }\n            }.\n            PDF(wo, wi, mode, flags);\n        }\n\n        BSDFSample Samplef\n        (\n        float3 wo, float uc, float2 u, TransportMode\n        mode, SampleFlags\n        flags)\n    {\n            return {{ & BxDFName\n                }\n            }.\n            Samplef(wo, uc, u, mode, flags);\n        }\n    }\n\nstruct Material\n{\n    BSDF bsdf;\n\n    void Init()\n    {\n        bsdf.Init();\n    }\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/Material.hlsli",
    "content": "#ifndef MATERIAL_HLSLI\n#define MATERIAL_HLSLI\n\n#include \"Attribute.hlsli\"\n#include \"Random.hlsli\"\n#include \"Interaction.hlsli\"\n#include \"MaterialResource.hlsli\"\n\n#include \"Material/BSDF/BSDF.hlsli\"\n\n{{#MaterialHeaders}}\n{{&MaterialHeader}}\n{{/MaterialHeaders}}\n\nstruct MaterialData\n{\n    {{#Textures}}\n    uint {{Texture}};\n    {{/Textures}}\n    {{#Samplers}}\n    uint {{Sampler}};\n    {{/Samplers}}\n};\n\nstruct BSDF\n{\n    {{&BxDFType}} {{&BxDFName}};\n\n    void Init(SurfaceInteraction surface_interaction)\n    {\n        MaterialData material_data = GetMaterialData < MaterialData > (surface_interaction.material);\n        {{#Initializations}}\n        {{&Initialization}}\n        {{/Initializations}}\n    }\n        \n     uint Flags()\n     {\n        return {{&BxDFName}}.Flags();\n    }\n\n    float3 Eval(float3 woW, float3 wiW, TransportMode mode)\n    {\n        return {{&BxDFName}}.Eval(woW, wiW, mode);\n    }\n\n    float PDF(float3 woW, float3 wiW, TransportMode mode, SampleFlags flags)\n    {\n        return {{&BxDFName}}.PDF(woW, wiW, mode, flags);\n    }\n\n    BSDFSample Samplef(float3 woW, float uc, float2 u, TransportMode mode, SampleFlags flags)\n    {\n        return {{&BxDFName}}.Samplef(woW, uc, u, mode, flags);\n    }\n\n    GBufferData GetGBufferData()\n    {\n        return {{&BxDFName}}.GetGBufferData();\n    }\n};\n\nstruct Material\n{\n    BSDF bsdf;\n\n    void Init(SurfaceInteraction surface_interaction)\n    {\n        bsdf.Init(surface_interaction);\n    }\n};\n\n#endif"
  },
  {
    "path": "Source/Shaders/MaterialResource.hlsli",
    "content": "#ifndef MATERIAL_RESOURCE_HLSLI\n#define MATERIAL_RESOURCE_HLSLI\n\n#include \"Interaction.hlsli\"\n\nTexture2D<float4> Textures[] : register(s996);\nSamplerState Samplers[] : register(s997);\nStructuredBuffer<uint> MaterialOffsets : register(t998);\nByteAddressBuffer MaterialBuffer : register(t999);\n\nfloat4 SampleTexture2D(uint texture_id, uint sampler_id, float2 uv, float2 duvdx, float2 duvdy)\n{\n    if (texture_id == ~0U)\n    {\n        return 0.f;\n    }\n    \n#ifdef RASTERIZATION_PIPELINE\n    return Textures[texture_id].Sample(Samplers[sampler_id], uv);\n#else\n    return Textures[texture_id].SampleGrad(Samplers[sampler_id], uv, duvdx, duvdy);\n#endif\n}\n\ntemplate<typename T>\nT GetMaterialData(uint material_id)\n{\n    if (material_id == ~0U)\n    {\n        T data;\n        return data;\n    }\n    return MaterialBuffer.Load<T>(MaterialOffsets[material_id]);\n}\n\nfloat3 ExtractNormalMap(SurfaceInteraction interaction, float3 normal_vector)\n{\n    float3 T, B;\n    Frame frame;\n    if(IsBlack(interaction.isect.nt))\n    {\n        frame.FromZ(interaction.isect.n);\n    }\n    else\n    {\n        frame.FromXZ(interaction.isect.nt, interaction.isect.n);\n    }\n    normal_vector = normal_vector * 2.0 - 1.0;\n    normal_vector = normalize(normal_vector);\n    return normalize(frame.ToWorld(normal_vector));\n    \n    \n    //Frame frame;\n    //frame.FromZ(interaction.isect.n);\n    //float3x3 TBN = float3x3(frame.x, frame.y, frame.z);\n    //normal_vector = normalize(normal_vector * 2.0 - 1.0);\n    //float3 normal = normalize(mul(normal_vector, TBN));\n    //interaction.isect.n = dot(interaction.isect.n, normal) <= 0.0 ? normal : -normal;\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/Math.hlsli",
    "content": "#ifndef MATH_HLSLI\n#define MATH_HLSLI\n\n#include \"Complex.hlsli\"\n\nstatic const float PI = 3.14159265358979323846f;\nstatic const float InvPI = 0.31830988618379067154f;\nstatic const float Inv2PI = 0.15915494309189533577f;\nstatic const float Inv4PI = 0.07957747154594766788f;\nstatic const float PIOver2 = 1.57079632679489661923f;\nstatic const float PIOver4 = 0.78539816339744830961f;\nstatic const float Sqrt2 = 1.41421356237309504880f;\n\nstatic const float ShadowEpsilon = 0.0001f;\n\nstatic const float Infinity = 1e32;\n\nvoid CoordinateSystem(float3 v1, out float3 v2, out float3 v3)\n{\n    const float3 ref = abs(dot(v1, float3(0, 1, 0))) > 0.99f ? float3(0, 0, 1) : float3(0, 1, 0);\n    v2 = normalize(cross(ref, v1));\n    v3 = cross(v1, v2);\n    //float sign = v1.z / abs(v1.z);\n    //float a = -1 / (sign + v1.z);\n    //float b = v1.x * v1.y * a;\n    //v2 = float3(1 + sign * v1.x * v1.x * a, sign * b, -sign * v1.x);\n    //v3 = float3(b, sign + v1.y * v1.y * a, -v1.y);\n}\n\nfloat Sqr(float x)\n{\n    return x * x;\n}\n\nfloat LengthSquared(float2 x)\n{\n    return Sqr(x.x) + Sqr(x.y);\n}\n\nfloat LengthSquared(float3 x)\n{\n    return Sqr(x.x) + Sqr(x.y) + Sqr(x.z);\n}\n\nfloat DistanceSquared(float3 v1, float3 v2)\n{\n    float3 v = v1 - v2;\n    return dot(v, v);\n}\n\nfloat3 FaceForward(float3 v1, float3 v2)\n{\n    return dot(v1, v2) > 0 ? v1 : -v1;\n}\n\n// Sampling Disk\n// Polar Mapping\nfloat2 UniformSampleDisk(float2 u)\n{\n    float r = sqrt(u.x);\n    float theta = 2 * PI * u.y;\n    return r * float2(cos(theta), sin(theta));\n}\n\n// Concentric Mapping\nfloat2 SampleConcentricDisk(float2 u)\n{\n    float2 uOffset = 2.0 * u - 1.0;\n\n    if (uOffset.x == 0 && uOffset.y == 0)\n    {\n        return float2(0.0, 0.0);\n    }\n\n    float theta, r;\n    if (abs(uOffset.x) > abs(uOffset.y))\n    {\n        r = uOffset.x;\n        theta = PIOver4 * (uOffset.y / uOffset.x);\n    }\n    else\n    {\n        r = uOffset.y;\n        theta = PIOver2 - PIOver4 * (uOffset.x / uOffset.y);\n    }\n\n    return r * float2(cos(theta), sin(theta));\n}\n\n// Sampling Hemisphere\nfloat3 UniformSampleHemisphere(float2 u)\n{\n    float z = u.x;\n    float r = sqrt(max(0.0, 1.0 - z * z));\n    float phi = 2 * PI * u.y;\n    return float3(r * cos(phi), r * sin(phi), z);\n}\n\nfloat3 UniformSampleSphere(float2 u)\n{\n    float z = 1.0 - 2.0 * u.x;\n    float r = sqrt(max(0.0, 1.0 - z * z));\n    float phi = 2 * PI * u.y;\n    return float3(r * cos(phi), r * sin(phi), z);\n}\n\nfloat UniformHemispherePdf()\n{\n    return Inv2PI;\n}\n\nfloat UniformSpherePdf()\n{\n    return Inv4PI;\n}\n\nfloat3 SampleCosineHemisphere(float2 u)\n{\n    float2 d = SampleConcentricDisk(u);\n    float z = sqrt(max(0, 1 - d.x * d.x - d.y * d.y));\n    return float3(d.x, d.y, z);\n}\n\nfloat CosineHemispherePdf(float cosTheta)\n{\n    return cosTheta * InvPI;\n}\n\n// Multiple Importance Sampling\nfloat BalanceHeuristic(int nf, float fPdf, int ng, float gPdf)\n{\n    return (nf * fPdf) / (nf * fPdf + ng * gPdf);\n}\n\nfloat PowerHeuristic(int nf, float fPdf, int ng, float gPdf)\n{\n    float f = nf * fPdf;\n    float g = ng * gPdf;\n    return (f * f) / (f * f + g * g);\n}\n\nfloat SphericalPhi(float3 v)\n{\n    float p = atan2(v.y, v.x);\n    return p < 0 ? (p + 2 * PI) : p;\n}\n\nfloat SphericalTheta(float3 v)\n{\n    return acos(clamp(v.z, -1.0, 1.0));\n}\n\nfloat ErfInv(float x)\n{\n    float w, p;\n    x = clamp(x, -.99999, .99999);\n    w = -log((1 - x) * (1 + x));\n    if (w < 5)\n    {\n        w = w - 2.5;\n        p = 2.81022636e-08;\n        p = 3.43273939e-07 + p * w;\n        p = -3.5233877e-06 + p * w;\n        p = -4.39150654e-06 + p * w;\n        p = 0.00021858087 + p * w;\n        p = -0.00125372503 + p * w;\n        p = -0.00417768164 + p * w;\n        p = 0.246640727 + p * w;\n        p = 1.50140941 + p * w;\n    }\n    else\n    {\n        w = sqrt(w) - 3;\n        p = -0.000200214257;\n        p = 0.000100950558 + p * w;\n        p = 0.00134934322 + p * w;\n        p = -0.00367342844 + p * w;\n        p = 0.00573950773 + p * w;\n        p = -0.0076224613 + p * w;\n        p = 0.00943887047 + p * w;\n        p = 1.00167406 + p * w;\n        p = 2.83297682 + p * w;\n    }\n    return p * x;\n}\n\nfloat Erf(float x)\n{\n\t// constants\n    float a1 = 0.254829592f;\n    float a2 = -0.284496736f;\n    float a3 = 1.421413741f;\n    float a4 = -1.453152027f;\n    float a5 = 1.061405429f;\n    float p = 0.3275911f;\n\n\t// Save the sign of x\n    int sign = 1;\n    if (x < 0)\n    {\n        sign = -1;\n    }\n    x = abs(x);\n\n\t// A&S formula 7.1.26\n    float t = 1 / (1 + p * x);\n    float y = 1 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x * x);\n\n    return sign * y;\n}\n\nfloat AbsCosTheta(float3 w)\n{\n    return abs(w.z);\n}\n\nfloat CosTheta(float3 w)\n{\n    return w.z;\n}\n\nfloat Cos2Theta(float3 w)\n{\n    return w.z * w.z;\n}\n\nfloat Sin2Theta(float3 w)\n{\n    return max(0.0, 1.0 - Cos2Theta(w));\n}\n\nfloat Tan2Theta(float3 w)\n{\n    return Sin2Theta(w) / Cos2Theta(w);\n}\n\nfloat SinTheta(float3 w)\n{\n    return sqrt(Sin2Theta(w));\n}\n\nfloat SinPhi(float3 w)\n{\n    float sinTheta = SinTheta(w);\n    return sinTheta == 0.0 ? 0.0 : clamp(w.y / sinTheta, -1.0, 1.0);\n}\n\nfloat Sin2Phi(float3 w)\n{\n    return SinPhi(w) * SinPhi(w);\n}\n\nfloat CosPhi(float3 w)\n{\n    float sinTheta = SinTheta(w);\n    return sinTheta == 0.0 ? 1.0 : clamp(w.x / sinTheta, -1.0, 1.0);\n}\n\nfloat Cos2Phi(float3 w)\n{\n    return CosPhi(w) * CosPhi(w);\n}\n\nfloat TanTheta(float3 w)\n{\n    return SinTheta(w) / CosTheta(w);\n}\n\nfloat3 SphericalDirection(float sinTheta, float cosTheta, float phi)\n{\n    return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);\n}\n\nfloat3 Faceforward(float3 v, float3 v2)\n{\n    return dot(v, v2) < 0.0 ? -v : v;\n}\n\nbool SameHemisphere(float3 w, float3 wp)\n{\n    return w.z * wp.z > 0;\n}\n\nfloat Radians(float deg)\n{\n    return PI / 180.0 * deg;\n}\n\nfloat Degrees(float rad)\n{\n    return rad * 180.0 / PI;\n}\n\nbool IsBlack(float3 v)\n{\n    return v.x == 0.0 && v.y == 0.0 && v.z == 0.0;\n}\n\n/*https://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/*/\nfloat AreaIntegration(float x, float y)\n{\n    return atan2(sqrt(x * x + y * y + 1), x * y);\n}\n\nfloat CalculateSolidAngle(uint x, uint y, uint width, uint height)\n{\n    float u = 2.0 * (float(x) + 0.5) / float(width) - 1.0;\n    float v = 2.0 * (float(y) + 0.5) / float(height) - 1.0;\n\n    float x0 = u - 1.0 / float(width);\n    float x1 = u + 1.0 / float(width);\n    float y0 = v - 1.0 / float(height);\n    float y1 = v + 1.0 / float(height);\n\n    return AreaIntegration(x0, y0) - AreaIntegration(x0, y1) - AreaIntegration(x1, y0) + AreaIntegration(x1, y1);\n}\n\nfloat3 CalculateCubemapDirection(uint face_idx, uint face_x, uint face_y, uint width, uint height)\n{\n    float u = 2.0 * (float(face_x) + 0.5) / float(width) - 1.0;\n    float v = 2.0 * (float(face_y) + 0.5) / float(height) - 1.0;\n    float x, y, z;\n\n    // POSITIVE_X 0\n    // NEGATIVE_X 1\n    // POSITIVE_Y 2\n    // NEGATIVE_Y 3\n    // POSITIVE_Z 4\n    // NEGATIVE_Z 5\n    \n    switch (face_idx)\n    {\n        case 0:\n            x = 1;\n            y = -v;\n            z = -u;\n            break;\n        case 1:\n            x = -1;\n            y = -v;\n            z = u;\n            break;\n        case 2:\n            x = u;\n            y = 1;\n            z = v;\n            break;\n        case 3:\n            x = u;\n            y = -1;\n            z = -v;\n            break;\n        case 4:\n            x = u;\n            y = -v;\n            z = 1;\n            break;\n        case 5:\n            x = -u;\n            y = -v;\n            z = -1;\n            break;\n    }\n\n    return normalize(float3(x, y, z));\n}\n\nuint HashCombine(uint hash1, uint hash2)\n{\n\thash1 ^= hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2);\n    return hash1;\n}\n\nuint Hash(uint a)\n{\n    a = (a + 0x7ed55d16) + (a << 12);\n    a = (a ^ 0xc761c23c) ^ (a >> 19);\n    a = (a + 0x165667b1) + (a << 5);\n    a = (a + 0xd3a2646c) ^ (a << 9);\n    a = (a + 0xfd7046c5) + (a << 3);\n    a = (a ^ 0xb55a4f09) ^ (a >> 16);\n    return a;\n}\n\nuint Hash(float a)\n{\n    return Hash(asuint(a));\n}\n\nuint Hash(float3 a)\n{\n    return HashCombine(HashCombine(Hash(a.x), Hash(a.y)), Hash(a.z));\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/PostProcess/Bloom.hlsl",
    "content": "#include \"../Common.hlsli\"\n\nstruct Config\n{\n    float threshold;\n    float radius;\n    float intensity;\n};\n\nConstantBuffer<Config> ConfigBuffer;\n\nstatic const float blur_weights[5] = { 0.2734375, 0.21875, 0.109375, 0.03125, 0.00390625 };\n\ngroupshared uint3 shared_cache[128];\ngroupshared float3 shared_tile[64];\n\nfloat3 BlurPixels(float3 a, float3 b, float3 c, float3 d, float3 e, float3 f, float3 g, float3 h, float3 i)\n{\n    return blur_weights[0] * e + blur_weights[1] * (d + f) + blur_weights[2] * (c + g) + blur_weights[3] * (b + h) + blur_weights[4] * (a + i);\n}\n\nvoid Store2Pixels(uint index, float3 pixel1, float3 pixel2)\n{\n    shared_cache[index] = f32tof16(pixel1) | f32tof16(pixel2) << 16;\n}\n\nvoid Load2Pixels(uint index, out float3 pixel1, out float3 pixel2)\n{\n    pixel1 = float3(f16tof32(shared_cache[index]));\n    pixel2 = float3(f16tof32(shared_cache[index] >> 16));\n}\n\nvoid Store1Pixels(uint index, float3 pixel)\n{\n    shared_cache[index] = asuint(pixel);\n}\n\nvoid Load1Pixels(uint index, out float3 pixel)\n{\n    pixel = asfloat(shared_cache[index]);\n}\n\nvoid BlurHorizontally(uint index, uint start)\n{\n    float3 pixels[10];\n    Load2Pixels(start + 0, pixels[0], pixels[1]);\n    Load2Pixels(start + 1, pixels[2], pixels[3]);\n    Load2Pixels(start + 2, pixels[4], pixels[5]);\n    Load2Pixels(start + 3, pixels[6], pixels[7]);\n    Load2Pixels(start + 4, pixels[8], pixels[9]);\n\n    Store1Pixels(index, BlurPixels(pixels[0], pixels[1], pixels[2], pixels[3], pixels[4], pixels[5], pixels[6], pixels[7], pixels[8]));\n    Store1Pixels(index + 1, BlurPixels(pixels[1], pixels[2], pixels[3], pixels[4], pixels[5], pixels[6], pixels[7], pixels[8], pixels[9]));\n}\n\nfloat3 BlurVertically(uint start)\n{\n    float3 pixels[9];\n    Load1Pixels(start, pixels[0]);\n    Load1Pixels(start + 8, pixels[1]);\n    Load1Pixels(start + 16, pixels[2]);\n    Load1Pixels(start + 24, pixels[3]);\n    Load1Pixels(start + 32, pixels[4]);\n    Load1Pixels(start + 40, pixels[5]);\n    Load1Pixels(start + 48, pixels[6]);\n    Load1Pixels(start + 56, pixels[7]);\n    Load1Pixels(start + 64, pixels[8]);\n    \n    return BlurPixels(pixels[0], pixels[1], pixels[2], pixels[3], pixels[4], pixels[5], pixels[6], pixels[7], pixels[8]);\n}\n\n///////////////////////// Bloom Mask /////////////////////////////\n\nTexture2D<float4> BloomMaskInput;\nRWTexture2D<float4> BloomMaskOutput;\n\n[numthreads(8, 8, 1)]\nvoid BloomMask(CSParam param)\n{\n    uint2 extent;\n    BloomMaskInput.GetDimensions(extent.x, extent.y);\n    \n    if (param.DispatchThreadID.x > extent.x || param.DispatchThreadID.y > extent.y)\n    {\n        return;\n    }\n    \n    float3 color = BloomMaskInput.Load(uint3(param.DispatchThreadID.xy, 0)).rgb;\n    float lum = Luminance(color);\n\n    BloomMaskOutput[param.DispatchThreadID.xy] = float4(clamp(lum - ConfigBuffer.threshold, 0.0, 1.0) * color, 1.0);\n}\n\n///////////////////////// Bloom Down Sampling /////////////////////////////\n\nTexture2D<float4> BloomDownSamplingInput;\nRWTexture2D<float4> BloomDownSamplingOutput;\nSamplerState BloomDownSampleSampler;\n\n[numthreads(8, 8, 1)]\nvoid BloomDownSampling(CSParam param)\n{\n    uint2 extent;\n    BloomDownSamplingOutput.GetDimensions(extent.x, extent.y);\n    \n    if (param.DispatchThreadID.x >= extent.x || param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    float2 uv = (float2(param.DispatchThreadID.xy) + float2(0.5, 0.5)) / float2(extent);\n    float3 avg_color = BloomDownSamplingInput.SampleLevel(BloomDownSampleSampler, uv, 0.0).rgb;\n    BloomDownSamplingOutput[param.DispatchThreadID.xy] = float4(avg_color, 1.0);\n}\n\n///////////////////////// Bloom Blur /////////////////////////////\n\nTexture2D<float4> BloomBlurInput;\nRWTexture2D<float4> BloomBlurOutput;\n\n[numthreads(8, 8, 1)]\nvoid BloomBlur(CSParam param)\n{\n    int2 GroupUL = (param.GroupID.xy << 3) - 4;\n    int2 ThreadUL = (param.GroupThreadID.xy << 1) + GroupUL;\n    \n    int start = param.GroupThreadID.x + (param.GroupThreadID.y << 4);\n    \n    Store2Pixels(\n        start + 0,\n        BloomBlurInput.Load(uint3(ThreadUL + uint2(0, 0), 0)).rgb,\n        BloomBlurInput.Load(uint3(ThreadUL + uint2(1, 0), 0)).rgb\n    );\n    \n    Store2Pixels(\n        start + 8,\n        BloomBlurInput.Load(uint3(ThreadUL + uint2(0, 1), 0)).rgb,\n        BloomBlurInput.Load(uint3(ThreadUL + uint2(1, 1), 0)).rgb\n    );\n    \n    GroupMemoryBarrierWithGroupSync();\n    \n    uint row = param.GroupThreadID.y << 4;\n    BlurHorizontally(row + (param.GroupThreadID.x << 1), row + param.GroupThreadID.x + (param.GroupThreadID.x & 4));\n    \n    GroupMemoryBarrierWithGroupSync();\n    \n    BloomBlurOutput[param.DispatchThreadID.xy] = float4(BlurVertically((param.GroupThreadID.y << 3) + param.GroupThreadID.x), 1.0);\n}\n\n///////////////////////// Bloom Up Sampling /////////////////////////////\n\nTexture2D BloomUpSamplingLow;\nTexture2D BloomUpSamplingHigh;\nRWTexture2D<float4> BloomUpSamplingOutput;\n\n[numthreads(8, 8, 1)]\nvoid BloomUpSampling(CSParam param)\n{\n    // TODO : Some bug here\n    uint2 extent;\n    BloomUpSamplingHigh.GetDimensions(extent.x, extent.y);\n    \n    float2 pixel_size = 1.0 / float2(extent);\n        \n    int2 GroupUL = (param.GroupID.xy << 3) - 4;\n    int2 ThreadUL = (param.GroupThreadID.xy << 1) + GroupUL;\n    \n    int start = param.GroupThreadID.x + (param.GroupThreadID.y << 4);\n    \n    Store2Pixels(\n        start + 0,\n        lerp(\n            BloomUpSamplingHigh.Load(uint3(ThreadUL + uint2(0, 0), 0), 0.0).rgb,\n            BloomUpSamplingLow.Load(uint3((ThreadUL + uint2(0, 0)) / 2, 0), 0.0).rgb,\n            ConfigBuffer.radius\n        ),\n        lerp(\n            BloomUpSamplingHigh.Load(uint3(ThreadUL + uint2(1, 0), 0), 0.0).rgb,\n            BloomUpSamplingLow.Load(uint3((ThreadUL + uint2(1, 0)) / 2, 0), 0.0).rgb,\n            ConfigBuffer.radius\n        )\n    );\n    \n    Store2Pixels(\n        start + 8,\n        lerp(\n            BloomUpSamplingHigh.Load(uint3(ThreadUL + uint2(0, 1), 0), 0.0).rgb,\n            BloomUpSamplingLow.Load(uint3((ThreadUL + uint2(0, 1)) / 2, 0), 0.0).rgb,\n            ConfigBuffer.radius\n        ),\n        lerp(\n            BloomUpSamplingHigh.Load(uint3(ThreadUL + uint2(1, 1), 0), 0.0).rgb,\n            BloomUpSamplingLow.Load(uint3((ThreadUL + uint2(1, 1)) / 2, 0), 0.0).rgb,\n            ConfigBuffer.radius\n        )\n    );\n        \n    GroupMemoryBarrierWithGroupSync();\n    \n    uint row = param.GroupThreadID.y << 4;\n    BlurHorizontally(row + (param.GroupThreadID.x << 1), row + param.GroupThreadID.x + (param.GroupThreadID.x & 4));\n    \n    GroupMemoryBarrierWithGroupSync();\n    \n    BloomUpSamplingOutput[param.DispatchThreadID.xy] = float4(BlurVertically((param.GroupThreadID.y << 3) + param.GroupThreadID.x), 1.0);\n}\n\n///////////////////////// Bloom Blend /////////////////////////////\n\nTexture2D BloomBlendBloom;\nTexture2D BloomBlendInput;\nRWTexture2D<float4> BloomBlendOutput;\n\n[numthreads(8, 8, 1)]\nvoid BloomBlend(CSParam param)\n{\n    uint2 extent;\n    BloomBlendOutput.GetDimensions(extent.x, extent.y);\n    \n    if (param.DispatchThreadID.x >= extent.x || param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    float2 uv = (float2(param.DispatchThreadID.xy) + float2(0.5, 0.5)) / float2(extent);\n    \n    BloomBlendOutput[param.DispatchThreadID.xy] = float4(BloomBlendInput.Load(uint3(param.DispatchThreadID.xy, 0), 0.0).rgb + ConfigBuffer.intensity * BloomBlendBloom.Load(uint3(param.DispatchThreadID.xy / 2, 0), 0.0).rgb, 1.0);\n}"
  },
  {
    "path": "Source/Shaders/PostProcess/FXAA.hlsl",
    "content": "#include \"../Common.hlsli\"\n\nstruct Config\n{\n    float fixed_threshold;\n    float relative_threshold;\n    float subpixel_blending;\n};\n\nTexture2D Input;\nSamplerState Sampler;\nRWTexture2D<float4> Output;\nConstantBuffer<Config> ConfigBuffer;\n\n#ifdef FXAA_QUALITY_LOW\n#define EXTRA_EDGE_STEPS 3\n#define EDGE_STEP_SIZES 1.5, 2.0, 2.0\n#define LAST_EDGE_STEP_GUESS 8.0\n#elif FXAA_QUALITY_MEDIUM\n#define EXTRA_EDGE_STEPS 8\n#define EDGE_STEP_SIZES 1.5, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4.0\n#define LAST_EDGE_STEP_GUESS 8.0\n#else   // FXAA_QUALITY_HIGH\n#define EXTRA_EDGE_STEPS 10\n#define EDGE_STEP_SIZES 1.0, 1.0, 1.0, 1.0, 1.5, 2.0, 2.0, 2.0, 2.0, 4.0\n#define LAST_EDGE_STEP_GUESS 8.0\n#endif\n\nstatic const float edgeStepSizes[EXTRA_EDGE_STEPS] = { EDGE_STEP_SIZES };\n\nfloat GetLuma(float2 uv, float2 offset, float2 texel_size)\n{\n    uv += float2(offset) * texel_size;\n    return sqrt(Luminance(Input.SampleLevel(Sampler, uv, 0.0).rgb));\n}\n\n// +1  NW   N     NE\n// +0  W     M      E\n// -1   SW    S      SE\n//      -1      +0    +1\nstruct LumaNeighborhood\n{\n    float m, n, e, s, w, ne, se, sw, nw;\n    float highest, lowest, range;\n};\n\nstruct FXAAEdge\n{\n    bool is_horizontal;\n    float pixel_step;\n    float luma_gradient, luma;\n};\n\nLumaNeighborhood GetLumaNeighborhood(float2 uv, float2 texel_size)\n{\n    LumaNeighborhood luma;\n    luma.m = GetLuma(uv, float2(0.0, 0.0), texel_size);\n    luma.n = GetLuma(uv, float2(0.0, 1.0), texel_size);\n    luma.e = GetLuma(uv, float2(1.0, 0.0), texel_size);\n    luma.s = GetLuma(uv, float2(0.0, -1.0), texel_size);\n    luma.w = GetLuma(uv, float2(-1.0, 0.0), texel_size);\n    luma.ne = GetLuma(uv, float2(1.0, 1.0), texel_size);\n    luma.se = GetLuma(uv, float2(1.0, -1.0), texel_size);\n    luma.sw = GetLuma(uv, float2(-1.0, -1.0), texel_size);\n    luma.nw = GetLuma(uv, float2(-1.0, 1.0), texel_size);\n    luma.highest = max(luma.m, max(luma.n, max(luma.e, max(luma.s, luma.w))));\n    luma.lowest = min(luma.m, min(luma.n, min(luma.e, min(luma.s, luma.w))));\n    luma.range = luma.highest - luma.lowest;\n    return luma;\n}\n\nfloat GetSubpixelBlendFactor(LumaNeighborhood luma)\n{\n    float filter = luma.n + luma.e + luma.s + luma.w;\n    filter = 2.0 * filter + luma.ne + luma.se + luma.sw + luma.nw;\n    filter *= 1.0 / 12.0;\n    filter = saturate(filter / luma.range);\n    filter = smoothstep(0.0, 1.0, filter);\n    return filter * filter * ConfigBuffer.subpixel_blending;\n}\n\nbool FXAASkip(LumaNeighborhood luma)\n{\n    return luma.range < max(ConfigBuffer.fixed_threshold, ConfigBuffer.relative_threshold * luma.highest);\n}\n\nbool IsHorizontalEdge(LumaNeighborhood luma)\n{\n    float horizontal = 2.0 * abs(luma.n + luma.s - 2.0 * luma.m) + abs(luma.nw + luma.sw - 2.0 * luma.w) + abs(luma.ne + luma.se - 2.0 * luma.e);\n    float vertical = 2.0 * abs(luma.e + luma.w - 2.0 * luma.m) + abs(luma.ne + luma.nw - 2.0 * luma.n) + abs(luma.se + luma.sw - 2.0 * luma.s);\n    return horizontal >= vertical;\n}\n\nFXAAEdge GetFXAAEdge(LumaNeighborhood luma, float2 texel_size)\n{\n    FXAAEdge edge;\n    edge.is_horizontal = IsHorizontalEdge(luma);\n    float lumaP, lumaN;\n    if (edge.is_horizontal)\n    {\n        edge.pixel_step = texel_size.y;\n        lumaP = luma.n;\n        lumaN = luma.s;\n    }\n    else\n    {\n        edge.pixel_step = texel_size.x;\n        lumaP = luma.e;\n        lumaN = luma.w;\n    }\n    \n    float gradientP = abs(lumaP - luma.m);\n    float gradientN = abs(lumaN - luma.m);\n    \n    if (gradientP < gradientN)\n    {\n        edge.pixel_step = -edge.pixel_step;\n        edge.luma_gradient = gradientN;\n        edge.luma = lumaN;\n    }\n    else\n    {\n        edge.luma_gradient = gradientP;\n        edge.luma = lumaP;\n    }\n    \n    return edge;\n}\n\nfloat GetEdgeBlendFactor(LumaNeighborhood luma, FXAAEdge edge, float2 uv, float2 texel_size)\n{\n    float2 edge_uv = uv;\n    float2 uv_step = float2(0.0, 0.0);\n    \n    if (edge.is_horizontal)\n    {\n        edge_uv.y += 0.5 * edge.pixel_step;\n        uv_step.x = texel_size.x;\n    }\n    else\n    {\n        edge_uv.x += 0.5 * edge.pixel_step;\n        uv_step.y = texel_size.y;\n    }\n    \n    float edge_luma = 0.5 * (luma.m + edge.luma);\n    float gradient_threshold = 0.25 * edge.luma_gradient;\n    \n    float2 uvP = edge_uv + uv_step;\n    float luma_deltaP = GetLuma(uvP, float2(0, 0), texel_size) - edge_luma;\n    bool atP = abs(luma_deltaP) >= gradient_threshold;\n    \n    for (int i = 0; i < EXTRA_EDGE_STEPS && !atP; i++)\n    {\n        uvP += uv_step * edgeStepSizes[i];\n        luma_deltaP = GetLuma(uvP, float2(0, 0), texel_size) - edge_luma;\n        atP = abs(luma_deltaP) >= gradient_threshold;\n    }\n    if (!atP)\n    {\n        uvP += uv_step * LAST_EDGE_STEP_GUESS;\n    }\n    \n    float2 uvN = edge_uv - uv_step;\n    float luma_deltaN = GetLuma(uvN, float2(0, 0), texel_size) - edge_luma;\n    bool atN = abs(luma_deltaN) >= gradient_threshold;\n    \n    for (int i = 0; i < EXTRA_EDGE_STEPS && !atN; i++)\n    {\n        uvN -= uv_step * edgeStepSizes[i];\n        luma_deltaN = GetLuma(uvN, float2(0, 0), texel_size) - edge_luma;\n        atN = abs(luma_deltaN) >= gradient_threshold;\n    }\n    if (!atN)\n    {\n        uvN -= uv_step * LAST_EDGE_STEP_GUESS;\n    }\n    \n    float dist_to_P, dist_to_N;\n    if (edge.is_horizontal)\n    {\n        dist_to_P = uvP.x - uv.x;\n        dist_to_N = uv.x - uvN.x;\n    }\n    else\n    {\n        dist_to_P = uvP.y - uv.y;\n        dist_to_N = uv.y - uvN.y;\n    }\n    \n    float dist;\n    bool delta_sign;\n    \n    if (dist_to_P <= dist_to_N)\n    {\n        dist = dist_to_P;\n        delta_sign = luma_deltaP >= 0;\n    }\n    else\n    {\n        dist = dist_to_N;\n        delta_sign = luma_deltaN >= 0;\n    }\n    \n    if (delta_sign == (luma.m - edge_luma) > 0)\n    {\n        return 0.0;\n    }\n    \n    return 0.5 - dist / (dist_to_N + dist_to_P);\n}\n\n[numthreads(8, 8, 1)]\nvoid CSmain(CSParam param)\n{\n    uint2 extent;\n    Input.GetDimensions(extent.x, extent.y);\n    float2 texel_size = 1.0 / float2(extent);\n    \n    float2 uv = (float2(param.DispatchThreadID.xy) + float2(0.5, 0.5)) * texel_size;\n    \n    if (param.DispatchThreadID.x >= extent.x || param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    LumaNeighborhood luma = GetLumaNeighborhood(uv, texel_size);\n    \n    if (FXAASkip(luma))\n    {\n        Output[param.DispatchThreadID.xy] = float4(Input[param.DispatchThreadID.xy].rgb, 1.0);\n        return;\n    }\n    \n    FXAAEdge edge = GetFXAAEdge(luma, texel_size);\n    float blend_factor = max(GetSubpixelBlendFactor(luma), GetEdgeBlendFactor(luma, edge, uv, texel_size));\n    \n    if (edge.is_horizontal)\n    {\n        uv.y += blend_factor * edge.pixel_step;\n    }\n    else\n    {\n        uv.x += blend_factor * edge.pixel_step;\n    }\n    \n    Output[param.DispatchThreadID.xy] = float4(Input.SampleLevel(Sampler, uv, 0.0).rgb, 1.0);\n}"
  },
  {
    "path": "Source/Shaders/PostProcess/Tonemapping.hlsl",
    "content": "#define TONEMAP_UNCHARTED\n#include \"../Tonemapper.hlsli\"\n\nstruct UniformBlock\n{\n    float brightness;\n    float contrast;\n    float saturation;\n    float vignette;\n    float avgLum;\n    int autoExposure;\n    float Ywhite; // Burning white\n    float key; // Log-average luminance\n};\n\nTexture2D Input;\nSamplerState TexSampler;\nRWTexture2D<float4> Output;\nConstantBuffer<UniformBlock> UniformBuffer;\n\nstruct CSParam\n{\n    uint3 DispatchThreadID : SV_DispatchThreadID;\n};\n\n// http://www.thetenthplanet.de/archives/5367\n// Apply dithering to hide banding artifacts.\nfloat3 Dither(float3 linear_color, float3 noise, float quant)\n{\n    float3 c0 = floor(LinearTosRGB(linear_color) / quant) * quant;\n    float3 c1 = c0 + quant;\n    float3 discr = lerp(sRGBToLinear(c0), sRGBToLinear(c1), noise);\n    return lerp(c0, c1, float3(1.0, 1.0, 1.0) - step(linear_color, discr));\n}\n\n// http://user.ceng.metu.edu.tr/~akyuz/files/hdrgpu.pdf\nstatic const float3x3 RGB2XYZ = float3x3(0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.0721750, 0.0193339, 0.1191920, 0.9503041);\nfloat Luminance(float3 color)\n{\n    return dot(color, float3(0.2126f, 0.7152f, 0.0722f)); //color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;\n}\n\nfloat3 ToneExposure(float3 RGB, float logAvgLum)\n{\n    float3 XYZ = mul(RGB2XYZ, RGB);\n    float Y = (UniformBuffer.key / logAvgLum) * XYZ.y;\n    float Yd = (Y * (1.0 + Y / (UniformBuffer.Ywhite * UniformBuffer.Ywhite))) / (1.0 + Y);\n    return RGB / XYZ.y * Yd;\n}\n\nfloat3 ToneLocalExposure(float3 RGB, float logAvgLum, float2 uvCoords)\n{\n    float3 XYZ = mul(RGB2XYZ, RGB);\n    float Y = (UniformBuffer.key / logAvgLum) * XYZ.y;\n    float La; // local adaptation luminance\n    float factor = UniformBuffer.key / logAvgLum;\n    float epsilon = 0.05, phi = 2.0;\n    float scale[7] = { 1, 2, 4, 8, 16, 32, 64 };\n    for (int i = 0; i < 7; ++i)\n    {\n        float v1 = Luminance(Input.SampleLevel(TexSampler, uvCoords, i).rgb) * factor;\n        float v2 = Luminance(Input.SampleLevel(TexSampler, uvCoords, i + 1).rgb) * factor;\n        if (abs(v1 - v2) / ((UniformBuffer.key * pow(2, phi) / (scale[i] * scale[i])) + v1) > epsilon)\n        {\n            La = v1;\n            break;\n        }\n        else\n            La = v2;\n    }\n    float Yd = Y / (1.0 + La);\n    return RGB / XYZ.y * Yd;\n}\n\nuint3 pcg3d(uint3 v)\n{\n    v = v * 1664525u + uint3(1013904223u, 1013904223u, 1013904223u);\n    v.x += v.y * v.z;\n    v.y += v.z * v.x;\n    v.z += v.x * v.y;\n    v ^= v >> uint3(16u, 16u, 16u);\n    v.x += v.y * v.z;\n    v.y += v.z * v.x;\n    v.z += v.x * v.y;\n    return v;\n}\n\n[numthreads(8, 8, 1)]\nvoid CSmain(CSParam param)\n{\n    uint2 TexSize;\n    Input.GetDimensions(TexSize.x, TexSize.y);\n    float2 uvCoords = (float2(param.DispatchThreadID.xy) + float2(0.5, 0.5)) / float2(TexSize);\n    float4 hdr = Input.SampleLevel(TexSampler, uvCoords, 0).rgba;\n    \n    if (((UniformBuffer.autoExposure >> 0) & 1) == 1)\n    {\n        float4 avg = Input.SampleLevel(TexSampler, float2(0.5, 0.5), 20).rgba; // Get the average value of the image\n        float avgLum2 = Luminance(avg.rgb); // Find the luminance\n        if (((UniformBuffer.autoExposure >> 1) & 1) == 1)\n        {\n            hdr.rgb = ToneLocalExposure(hdr.rgb, avgLum2, uvCoords); // Adjust exposure\n        }\n        else\n        {\n            hdr.rgb = ToneExposure(hdr.rgb, avgLum2); // Adjust exposure\n        }\n    }\n\n    // Tonemap + Linear to sRgb\n    float3 color = ToneMap(hdr.rgb, UniformBuffer.avgLum);\n\n    // Remove banding\n    uint3 r = pcg3d(uint3(param.DispatchThreadID.xy, 0));\n    float3 noise = asfloat(0x3f800000 | (r >> 9)) - 1.0f;\n    color = Dither(sRGBToLinear(color), noise, 1. / 255.);\n\n    //contrast\n    color = clamp(lerp(float3(0.5, 0.5, 0.5), color, UniformBuffer.contrast), 0, 1);\n    // brighness\n    float inv_brightness = 1.0 / UniformBuffer.brightness;\n    color = pow(color, float3(inv_brightness, inv_brightness, inv_brightness));\n    // saturation\n    float s = dot(color, float3(0.299, 0.587, 0.114));\n    float3 i = float3(s, s, s);\n    color = lerp(i, color, UniformBuffer.saturation);\n    // vignette\n    float2 uv = (uvCoords - 0.5) * 2.0;\n    color *= 1.0 - dot(uv, uv) * UniformBuffer.vignette;\n\n    Output[int2(param.DispatchThreadID.xy)] = float4(color, hdr.a);\n}"
  },
  {
    "path": "Source/Shaders/PreProcess/EquirectangularToCubemap.hlsl",
    "content": "Texture2D InputTexture;\nSamplerState TexSampler;\n\nstatic const float PI = 3.14159265358979323846f;\nstatic const float4x4 InvViewProjections[6] =\n{\n    // +X\n    float4x4(\n        -0, 0, -0, 1,\n        0, 1, 0, -0,\n        1, 0, -0, 0,\n        0, -0, -4.95, 5.0499997\n    ),\n    // -X\n    float4x4(\n        -0, 0, -0, -1,\n        0, 1, 0, -0,\n        -1, 0, -0, 0,\n        0, -0, -4.95, 5.0499997\n    ),\n    // +Y\n    float4x4(\n        1, 0, -0, 0,\n        0, -0, 0, 1,\n        -0, 1, -0, 0,\n        0, -0, -4.95, 5.0499997\n    ),\n    // -Y\n    float4x4(\n        1, 0, 0, 0,\n        0, -0, 0, -1,\n        -0, -1, -0, 0,\n        0, -0, -4.95, 5.0499997\n    ),\n    // +Z\n    float4x4(\n        1, 0, -0, 0,\n        0, 1, 0, -0,\n        -0, 0, -0, -1,\n        0, -0, -4.95, 5.0499997\n    ),\n    // -Z\n    float4x4(\n        -1, 0, -0, 0,\n        0, 1, 0, -0,\n        -0, -0, -0, 1,\n        0, -0, -4.95, 5.0499997\n    )\n};\n\nstruct VSInput\n{\n    uint VertexID : SV_VertexID;\n    uint InstanceID : SV_InstanceID;\n};\n\nstruct VSOutput\n{\n    float3 Pos : POSITION0;\n    float2 UV : TEXCOORD0;\n    float4 Position : SV_POSITION;\n    uint Layer : SV_RenderTargetArrayIndex;\n};\n\nstruct FSInput\n{\n    float3 Pos : POSITION0;\n    float2 UV : TEXCOORD0;\n};\n\nstruct FSOutput\n{\n    float4 Color : SV_Target0;\n};\n\nfloat2 SampleSphericalMap(float3 v)\n{\n    float2 uv = float2(atan2(v.x, v.z), asin(v.y));\n    uv.x /= 2 * PI;\n    uv.y /= PI;\n    uv += 0.5;\n    uv.y = 1.0 - uv.y;\n    return uv;\n}\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output = (VSOutput) 0;\n    \n    output.UV = float2((input.VertexID << 1) & 2, input.VertexID & 2);\n    output.Position = float4(output.UV * 2.0 - 1.0, 1.0, 1.0);\n    output.Pos = mul(InvViewProjections[input.InstanceID], output.Position).xyz;\n    output.Layer = input.InstanceID;\n\n    return output;\n}\n\nFSOutput PSmain(FSInput input)\n{\n    FSOutput output;\n    \n    float2 UV = SampleSphericalMap(normalize(input.Pos));\n    output.Color = float4(InputTexture.Sample(TexSampler, UV).rgb, 1.0);\n    // output.Color = float4(UV, 0.0, 1.0);\n    \n    return output;\n}"
  },
  {
    "path": "Source/Shaders/PreProcess/GGXBRDFLUT.hlsl",
    "content": "#include \"../Random.hlsli\"\n#include \"../Common.hlsli\"\n\n#define LOCAL_SIZE 8\n#define SAMPLE_COUNT 32\n#define LUT_SIZE 512\n\nRWTexture2D<float2> Output;\n\nfloat3 ImportanceSampleGGX(float2 Xi, float3 N, float roughness)\n{\n    float alpha = roughness * roughness;\n\n    float theta = atan(alpha * sqrt(Xi.x) / sqrt(1 - Xi.x));\n    float phi = 2.0 * PI * Xi.y;\n\n    float3 H = float3(\n        sin(theta) * cos(phi),\n        sin(theta) * sin(phi),\n        cos(theta)\n    );\n\n    float3 Up = N.z > 0.99 ? float3(0.0, 1.0, 0.0) : float3(0.0, 0.0, 1.0);\n    float3 T = normalize(cross(N, Up));\n    float3 B = normalize(cross(N, T));\n\n    return T * H.x + B * H.y + N * H.z;\n}\n\nfloat Conv(in float kernel[9], in float data[9], in float denom, in float offset)\n{\n    float res = 0.0;\n    for (int i = 0; i < 9; ++i)\n    {\n        res += kernel[i] * data[i];\n    }\n    return saturate(res / denom + offset);\n}\n\nfloat GeometrySchlickGGX(float NoV, float roughness)\n{\n    float alpha = roughness;\n    float k = alpha * alpha / 2.0;\n\n    return NoV / (NoV * (1.0 - k) + k);\n}\n\nfloat GeometrySmith(float roughness, float NoV, float NoL)\n{\n    return GeometrySchlickGGX(NoV, roughness) * GeometrySchlickGGX(NoL, roughness);\n}\n\nfloat2 IntegrateBRDF(float NoV, float roughness)\n{\n    float3 V;\n    V.x = sqrt(1.0 - NoV * NoV);\n    V.y = 0.0;\n    V.z = NoV;\n\n    float A = 0.0;\n    float B = 0.0;\n\n    float3 N = float3(0.0, 0.0, 1.0);\n\n    for (uint i = 0; i < SAMPLE_COUNT; i++)\n    {\n        float2 Xi = Hammersley(i, SAMPLE_COUNT);\n        float3 H = ImportanceSampleGGX(Xi, N, roughness);\n        float3 L = normalize(H * 2.0 * dot(V, H) - V);\n\n        float NoL = clamp(dot(N, L), 0.0, 1.0);\n        float NoH = clamp(dot(N, H), 0.0, 1.0);\n        float VoH = clamp(dot(V, H), 0.0, 1.0);\n\n        if (NoL > 0.0)\n        {\n            float G = GeometrySmith(roughness, NoV, NoL);\n            float w = VoH * G / (NoV * NoH);\n            float Fc = pow(1.0 - VoH, 5.0);\n\n            A += (1.0 - Fc) * w;\n            B += Fc * w;\n        }\n    }\n\n    return float2(A, B) / float(SAMPLE_COUNT);\n}\n\n[numthreads(LOCAL_SIZE, LOCAL_SIZE, 1)]\nvoid CSmain(CSParam param)\n{\n    float2 tex_coord = float2(float2(param.DispatchThreadID.xy) + float2(0.5, 0.5)) / float(LUT_SIZE);\n    float2 brdf = IntegrateBRDF(tex_coord.x, tex_coord.y);\n\n    Output[int2(param.DispatchThreadID.xy)] = brdf;\n}"
  },
  {
    "path": "Source/Shaders/Random.hlsli",
    "content": "#ifndef __RANDOM_HLSL__\n#define __RANDOM_HLSL__\n\n#include \"Math.hlsli\"\n\nstruct PCGSampler\n{\n    uint seed;\n    \n    void Init(uint2 resolution, uint2 screen_coord, uint frame)\n    {\n        uint v0 = screen_coord.y * resolution.x + screen_coord.x;\n        uint v1 = frame;\n        uint s0 = 0;\n\n        for (uint n = 0; n < 16; n++)\n        {\n            s0 += 0x9e3779b9;\n            v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);\n            v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);\n        }\n        \n        seed = v0;\n    }\n    \n    float Get1D()\n    {\n        // https://www.pcg-random.org/\n        uint prev = seed * 747796405u + 2891336453u;\n        uint word = ((prev >> ((prev >> 28u) + 4u)) ^ prev) * 277803737u;\n        seed = prev;\n        uint r = (word >> 22u) ^ word;\n        return asfloat(0x3f800000 | (r >> 9)) - 1.0f;\n    }\n    \n    float2 Get2D()\n    {\n        float x = Get1D();\n        float y = Get1D();\n        return float2(x, y);\n    }\n    \n    float3 Get3D()\n    {\n        float x = Get1D();\n        float y = Get1D();\n        float z = Get1D();\n        return float3(x, y, z);\n    }\n};\n\nfloat Rand1To1(float x)\n{\n    return frac(sin(x) * 43758.5453123);\n}\n\nfloat Rand2To1(float2 uv)\n{\n    return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);\n}\n\nfloat Rand3To1(float3 uvw)\n{\n    return frac(sin(dot(uvw, float3(12.9898, 78.233, 144.7272))) * 43758.5453);\n}\n\nfloat2 PoissonDiskSamples2D(float2 seed, int samples_num, int rings_num, int step)\n{\n    float angle = Rand2To1(seed) * PI * 2.0 + step * PI * 2.0 * float(rings_num) / float(samples_num);\n    float radius = (float(step) + 1.0) / float(samples_num);\n    return float2(cos(angle) * sin(angle), cos(angle)) * pow(radius, 0.75);\n}\n\nfloat3 PoissonDiskSamples3D(float3 seed, int samples_num, int rings_num, float2 step)\n{\n    float2 angle = Rand3To1(seed) * PI * 2.0 + step * PI * 2.0 * float(rings_num) / float(samples_num);\n    float radius = (length(step) + 1.0) / float(samples_num);\n    return float3(sin(angle.x) * cos(angle.y), sin(angle.x) * sin(angle.y), cos(angle.x)) * pow(radius, 0.75);\n}\n\nfloat2 UniformDiskSamples2D(float2 seed)\n{\n    float rand_num = Rand2To1(seed);\n    float sample_x = Rand1To1(rand_num);\n    float sample_y = Rand1To1(sample_x);\n\n    float radius = sqrt(sample_x);\n    float angle = sample_y * PI * 2;\n\n    return float2(radius * cos(angle), radius * sin(angle));\n}\n\nfloat3 UniformDiskSamples3D(float3 seed)\n{\n    float sample_x = Rand3To1(seed);\n    float sample_y = Rand1To1(sample_x);\n    float sample_z = Rand1To1(sample_y);\n\n    float radius = sqrt(sample_x);\n    float2 angle = float2(sample_y * PI * 2, sample_z * PI * 2);\n\n    return float3(sin(angle.y) * cos(angle.x), sin(angle.y) * sin(angle.x), cos(angle.y)) * radius;\n}\n\nfloat RadicalInverse_VdC(uint bits)\n{\n    bits = (bits << 16u) | (bits >> 16u);\n    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\n    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\n    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\n    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\n    return float(bits) * 2.3283064365386963e-10; // / 0x100000000\n}\n\nfloat2 Hammersley(uint i, uint N)\n{\n    return float2(float(i) / float(N), RadicalInverse_VdC(i));\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/RayTracing/BidirectionalPathTracing.hlsl",
    "content": ""
  },
  {
    "path": "Source/Shaders/RayTracing/PathTracing.hlsl",
    "content": "#include \"../Interaction.hlsli\"\n#include \"../Math.hlsli\"\n#include \"../Common.hlsli\"\n#include \"../Light.hlsli\"\n#include \"../Random.hlsli\"\n\nstruct Config\n{\n    uint max_bounce;\n    uint max_spp;\n    uint frame_count;\n    float clamp_threshold;\n    uint anti_aliasing;\n};\n\nRaytracingAccelerationStructure TopLevelAS;\nStructuredBuffer<Instance> InstanceBuffer;\nStructuredBuffer<Vertex> VertexBuffer[];\nStructuredBuffer<uint> IndexBuffer[];\nConstantBuffer<View> ViewBuffer;\nConstantBuffer<Config> ConfigBuffer;\nStructuredBuffer<PointLight> PointLightBuffer;\nStructuredBuffer<SpotLight> SpotLightBuffer;\nStructuredBuffer<DirectionalLight> DirectionalLightBuffer;\nStructuredBuffer<RectLight> RectLightBuffer;\nConstantBuffer<LightInfo> LightInfoBuffer;\nRWTexture2D<float4> Output;\n\n#ifndef RAYTRACING_PIPELINE\n#define RAYGEN_SHADER\n#define CLOSESTHIT_SHADER\n#define MISS_SHADER\n#include \"../Material/Material.hlsli\"\n#endif\n\n#ifdef USE_SKYBOX\nTextureCube<float4> Skybox;\nSamplerState SkyboxSampler;\n#endif\n\nstruct PayLoad\n{\n    SurfaceInteraction interaction;\n    \n    RayDiff ray_diff;\n\n    PCGSampler rng;\n    \n    float3 wi;\n    float pdf;\n    float eta;\n    float3 radiance;\n    float3 throughout;\n    bool terminate;\n    bool visible;\n    \n    void Init()\n    {\n        radiance = 0.f;\n        pdf = 1.f;\n        eta = 1.f;\n        throughout = 1.f;\n        terminate = false;\n    }\n};\n\nstruct Light\n{\n    PointLight point_light;\n    SpotLight spot_light;\n    DirectionalLight directional_light;\n    RectLight rect_light;\n    uint light_type;\n    \n    void Init(uint light_id)\n    {\n        uint point_light_offset = 0;\n        uint spot_light_offset = LightInfoBuffer.point_light_count;\n        uint directional_light_offset = spot_light_offset + LightInfoBuffer.spot_light_count;\n        uint rectangle_light_offset = directional_light_offset + LightInfoBuffer.directional_light_count;\n        uint light_count = rectangle_light_offset + LightInfoBuffer.rect_light_count;\n        \n        if (light_id < spot_light_offset)\n        {\n            light_type = POINT_LIGHT;\n            point_light = PointLightBuffer[light_id];\n            return;\n        }\n        else if (light_id < directional_light_offset)\n        {\n            light_type = SPOT_LIGHT;\n            spot_light = SpotLightBuffer[light_id - spot_light_offset];\n            return;\n        }\n        else if (light_id < rectangle_light_offset)\n        {\n            light_type = DIRECTIONAL_LIGHT;\n            directional_light = DirectionalLightBuffer[light_id - directional_light_offset];\n            return;\n        }\n        else if (light_id < light_count)\n        {\n            light_type = RECT_LIGHT;\n            rect_light = RectLightBuffer[light_id - rectangle_light_offset];\n            return;\n        }\n    }\n    \n    LightLiSample SampleLi(LightSampleContext ctx, float2 u)\n    {\n        switch (light_type)\n        {\n            case POINT_LIGHT:\n                return point_light.SampleLi(ctx, u);\n            case SPOT_LIGHT:\n                return spot_light.SampleLi(ctx, u);\n            case DIRECTIONAL_LIGHT:\n                return directional_light.SampleLi(ctx, u);\n            case RECT_LIGHT:\n                return rect_light.SampleLi(ctx, u);\n        }\n        \n        LightLiSample light_sample;\n        return light_sample;\n    }\n\n    float PDF_Li(LightSampleContext ctx, float3 wi)\n    {\n        switch (light_type)\n        {\n            case POINT_LIGHT:\n                return point_light.PDF_Li(ctx, wi);\n            case SPOT_LIGHT:\n                return spot_light.PDF_Li(ctx, wi);\n        }\n        \n        return 0;\n    }\n    \n    bool IsDelta()\n    {\n        switch (light_type)\n        {\n            case POINT_LIGHT:\n                return point_light.IsDelta();\n            case SPOT_LIGHT:\n                return spot_light.IsDelta();\n            case DIRECTIONAL_LIGHT:\n                return directional_light.IsDelta();\n            case RECT_LIGHT:\n                return rect_light.IsDelta();\n        }\n        return false;\n    }\n};\n\nbool SceneIntersection(RayDesc ray, out PayLoad pay_load)\n{\n    pay_load.visible = true;\n    TraceRay(\n        TopLevelAS, // RaytracingAccelerationStructure\n        RAY_FLAG_NONE, // RayFlags\n        0xFF, // InstanceInclusionMask\n        0, // RayContributionToHitGroupIndex\n        1, // MultiplierForGeometryContributionToHitGroupIndex\n        0, // MissShaderIndex\n        ray, // Ray\n        pay_load // Payload\n    );\n    \n    return pay_load.visible;\n}\n\nbool Unoccluded(SurfaceInteraction surface_interaction, Interaction isect)\n{\n    float3 direction = normalize(isect.p - surface_interaction.isect.p);\n    RayDesc shadow_ray = surface_interaction.isect.SpawnRay(direction);\n    shadow_ray.TMin = 0.0;\n    shadow_ray.TMax = distance(isect.p, surface_interaction.isect.p);\n    \n    PayLoad pay_load;\n    pay_load.visible = true;\n    \n    TraceRay(\n        TopLevelAS, // RaytracingAccelerationStructure\n        RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER, // RayFlags\n        0xFF, // InstanceInclusionMask\n        0, // RayContributionToHitGroupIndex\n        1, // MultiplierForGeometryContributionToHitGroupIndex\n        0, // MissShaderIndex\n        shadow_ray, // Ray\n        pay_load // Payload\n    );\n    \n    return !pay_load.visible;\n}\n\nuint hash(uint a)\n{\n    a = (a + 0x7ed55d16) + (a << 12);\n    a = (a ^ 0xc761c23c) ^ (a >> 19);\n    a = (a + 0x165667b1) + (a << 5);\n    a = (a + 0xd3a2646c) ^ (a << 9);\n    a = (a + 0xfd7046c5) + (a << 3);\n    a = (a ^ 0xb55a4f09) ^ (a >> 16);\n    return a;\n}\n\nfloat3 GetColor(uint v)\n{\n    uint mhash = hash(v);\n    return float3(float(mhash & 255), float((mhash >> 8) & 255), float((mhash >> 16) & 255)) / 255.0;\n}\n\n#ifdef RAYGEN_SHADER\n[shader(\"raygeneration\")]\nvoid RayGenMain()\n{\n    uint2 launch_index = DispatchRaysIndex().xy;\n    uint2 launch_dims = DispatchRaysDimensions().xy;\n    \n    PayLoad pay_load;\n    pay_load.rng.Init(launch_dims, launch_index, ConfigBuffer.frame_count);\n    pay_load.Init();\n    \n    const float2 pixel_pos = float2(launch_index.xy) + (pay_load.rng.Get2D() - float2(0.5, 0.5)) * ConfigBuffer.anti_aliasing + 0.5;\n    const float2 scene_uv = pixel_pos / float2(launch_dims.xy) * 2.0 - 1.0;\n    \n    RayDesc ray;\n    ViewBuffer.CastRay(scene_uv, (float2) launch_dims, ray, pay_load.ray_diff);\n    \n    uint bounce = 0;\n    \n    for (bounce = 0; bounce < ConfigBuffer.max_bounce && !pay_load.terminate; bounce++)\n    {\n        if (!SceneIntersection(ray, pay_load))\n        {\n            // Sample environment light\n#ifdef USE_SKYBOX\n            // Environment Sampling (HDR)\n            // See:  https://arxiv.org/pdf/1901.05423.pdf\n            float pdf = 1.0;\n            float3 wi = normalize(ray.Direction);\n            pay_load.radiance += Skybox.SampleLevel(SkyboxSampler, wi, 0.0).rgb * pay_load.throughout;\n#else\n            float pdf = 1.0;\n#endif\n            break;\n        }\n           \n        ray = pay_load.interaction.isect.SpawnRay(pay_load.wi);\n        \n        // Russian roulette\n        float3 rrBeta = pay_load.throughout * pay_load.eta;\n        float max_cmpt = max(rrBeta.x, max(rrBeta.y, rrBeta.z));\n        if (max_cmpt < 1.0 && bounce > 1)\n        {\n            float q = max(0.0, 1.0 - max_cmpt);\n            if (pay_load.rng.Get1D() < q)\n            {\n                break;\n            }\n            pay_load.throughout /= 1.0 - q;\n        }\n    }\n    \n    // Clamp firefly\n    float lum = Luminance(pay_load.radiance);\n    if (lum > ConfigBuffer.clamp_threshold)\n    {\n        pay_load.radiance *= ConfigBuffer.clamp_threshold / lum;\n    }\n    \n    int2 launch_id = int2(launch_index.x, launch_dims.y - launch_index.y);\n    \n    // Temporal Accumulation\n    if (ConfigBuffer.frame_count == 0)\n    {\n        Output[launch_id] = float4(pay_load.radiance, 1.f);\n    }\n    else\n    {\n        float3 prev_color = Output[launch_id].rgb;\n        float4 accumulated_color = 0.f;\n        if ((isnan(prev_color.x) || isnan(prev_color.y) || isnan(prev_color.z)))\n        {\n            accumulated_color = float4(pay_load.radiance, 1.f);\n        }\n        else\n        {\n            accumulated_color = float4(lerp(prev_color, pay_load.radiance, 1.0 / float(ConfigBuffer.frame_count + 1)), 1.f);\n        }\n        \n        Output[launch_id] = accumulated_color;\n    }\n}\n#endif\n\n#ifdef CLOSESTHIT_SHADER\n\nfloat3 SampleLd(PayLoad pay_load, Material material)\n{\n    uint flags = material.bsdf.Flags();\n    //if(IsReflective(flags)&&!IsTransmissive(flags))\n    //{\n    //    OffsetRayOrigin(pay_load.interaction.isect.wo, pay_load.interaction.isect.n);\n    //}\n    \n    uint light_count = LightInfoBuffer.point_light_count + LightInfoBuffer.spot_light_count + LightInfoBuffer.directional_light_count + LightInfoBuffer.rect_light_count;\n    \n    // Uniformly sample one light\n    if (light_count > 0)\n    {\n        uint light_id = (uint) min(light_count - 1, pay_load.rng.Get1D() * (float) light_count);\n        float light_select_pdf = 1.0 / (float) light_count;\n        \n        Light light;\n        light.Init(light_id);\n        \n        LightSampleContext sample_context;\n        sample_context.n = pay_load.interaction.isect.n;\n        sample_context.ns = pay_load.interaction.shading_n;\n        sample_context.p = pay_load.interaction.isect.p;\n        \n        LightLiSample light_sample = light.SampleLi(sample_context, pay_load.rng.Get2D());\n        \n        float3 wo = pay_load.interaction.isect.wo;\n        float3 f = material.bsdf.Eval(wo, light_sample.wi, TransportMode_Radiance);\n        \n        if (IsBlack(light_sample.L) || IsBlack(f) || !Unoccluded(pay_load.interaction, light_sample.isect))\n        {\n            return 0.f;\n        }\n        \n        float p_l = light_select_pdf * light_sample.pdf;\n        \n        if (light.IsDelta())\n        {\n            return light_sample.L * f / p_l;\n        }\n        else\n        {\n            float p_b = material.bsdf.PDF(wo, light_sample.wi, TransportMode_Radiance, BSDF_All);\n            float w_l = PowerHeuristic(1, p_l, 1, p_b);\n            return w_l * light_sample.L * f / p_l;\n        }\n    }\n    return 0.f;\n}\n#include \"../Material/Scattering.hlsli\"\n[shader(\"closesthit\")]\nvoid ClosesthitMain(inout PayLoad pay_load : SV_RayPayload, BuiltInTriangleIntersectionAttributes attributes)\n{\n    pay_load.visible = true;\n    \n    SurfaceInteraction surface_interaction;\n    \n    const uint instance_id = InstanceIndex();\n    const uint primitve_id = PrimitiveIndex();\n    const float3 bary = float3(1.0 - attributes.barycentrics.x - attributes.barycentrics.y, attributes.barycentrics.x, attributes.barycentrics.y);\n    \n    Instance instance = InstanceBuffer[instance_id];\n\n    Vertex v0 = VertexBuffer[instance.mesh_id][IndexBuffer[instance.mesh_id][primitve_id * 3]];\n    Vertex v1 = VertexBuffer[instance.mesh_id][IndexBuffer[instance.mesh_id][primitve_id * 3 + 1]];\n    Vertex v2 = VertexBuffer[instance.mesh_id][IndexBuffer[instance.mesh_id][primitve_id * 3 + 2]];\n    \n    surface_interaction.isect.p = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();\n    surface_interaction.isect.uv = v0.texcoord0.xy * bary.x + v1.texcoord0.xy * bary.y + v2.texcoord0.xy * bary.z;\n    surface_interaction.isect.n = v0.normal.xyz * bary.x + v1.normal.xyz * bary.y + v2.normal.xyz * bary.z;\n    surface_interaction.isect.n = normalize(mul(WorldToObject4x3(), normalize(surface_interaction.isect.n)).xyz);\n    surface_interaction.isect.nt = v0.tangent.xyz * bary.x + v1.tangent.xyz * bary.y + v2.tangent.xyz * bary.z;\n    surface_interaction.isect.nt = normalize(mul(WorldToObject4x3(), normalize(surface_interaction.isect.nt)).xyz);\n    surface_interaction.shading_n = dot(surface_interaction.isect.n, -WorldRayDirection()) <= 0 ? -surface_interaction.isect.n : surface_interaction.isect.n;\n    surface_interaction.isect.wo = -normalize(WorldRayDirection());\n    surface_interaction.isect.t = RayTCurrent();\n    surface_interaction.material = instance.material_id;\n    \n    float3 edge01 = mul(v1.position - v0.position, (float3x3) ObjectToWorld4x3()).xyz;\n    float3 edge02 = mul(v2.position - v0.position, (float3x3) ObjectToWorld4x3()).xyz;\n    float3 wgeom_normal = cross(edge01, edge02);\n    \n    // Compute Differential\n    pay_load.ray_diff.Propagate(normalize(WorldRayDirection()), RayTCurrent(), surface_interaction.shading_n);\n    \n    float3 nu = cross(edge02, wgeom_normal);\n    float3 nv = cross(edge01, wgeom_normal);\n    float3 lu = nu / (dot(nu, edge01));\n    float3 lv = nv / (dot(nv, edge02));\n\n    float2 dBarydx = float2(dot(lu, pay_load.ray_diff.dOdx), dot(lv, pay_load.ray_diff.dOdx));\n    float2 dBarydy = float2(dot(lu, pay_load.ray_diff.dOdy), dot(lv, pay_load.ray_diff.dOdy));\n    \n    float2 deltaUV1 = v1.texcoord0 - v0.texcoord0;\n    float2 deltaUV2 = v2.texcoord0 - v0.texcoord0;\n    \n    surface_interaction.duvdx = dBarydx.x * deltaUV1 + dBarydx.y * deltaUV2;\n    surface_interaction.duvdy = dBarydy.x * deltaUV1 + dBarydy.y * deltaUV2;\n    \n    Material material;\n    material.Init(surface_interaction);\n\n    // Sample emissive\n    pay_load.radiance += material.bsdf.GetGBufferData().emissive * pay_load.throughout;\n    \n    pay_load.interaction = surface_interaction;\n    float3 wo = surface_interaction.isect.wo;\n    \n    if (IsNonSpecular(material.bsdf.Flags()))\n    {\n        uint flags = material.bsdf.Flags();\n        float3 Ld = SampleLd(pay_load, material);\n        pay_load.radiance = pay_load.radiance.rgb + pay_load.throughout * Ld;\n    }\n    \n    // Sample BSDF to get new path direction\n    uint sample_type;\n    BSDFSample bs = material.bsdf.Samplef(wo, pay_load.rng.Get1D(), pay_load.rng.Get2D(), TransportMode_Radiance, BSDF_All);\n   \n    if (IsBlack(bs.f) || bs.pdf == 0.0)\n    {\n        pay_load.terminate = true;\n        return;\n    }\n    \n    pay_load.throughout *= bs.f / bs.pdf;\n    pay_load.pdf = bs.pdfIsProportional ? material.bsdf.PDF(wo, bs.wiW, TransportMode_Radiance, BSDF_All) : bs.pdf;\n    bool specular_bounce = bs.IsSpecular();\n    if (bs.IsTransmission())\n    {\n        pay_load.eta *= Sqr(bs.eta);\n    }\n\n    pay_load.wi = bs.wiW;\n}\n#endif\n\n#ifdef MISS_SHADER\n[shader(\"miss\")]\nvoid MissMain(inout PayLoad pay_load : SV_RayPayload)\n{\n    pay_load.visible = false;\n}\n#endif\n"
  },
  {
    "path": "Source/Shaders/Reflection/RayTracedReflection.hlsl",
    "content": ""
  },
  {
    "path": "Source/Shaders/RenderPath/VisibilityBufferVisualization.hlsl",
    "content": "#include \"../Common.hlsli\"\n\nTexture2D<uint> VisibilityBuffer;\nTexture2D<float> DepthBuffer;\nRWTexture2D<float4> InstanceID;\nRWTexture2D<float4> PrimitiveID;\n\nuint hash(uint a)\n{\n    a = (a + 0x7ed55d16) + (a << 12);\n    a = (a ^ 0xc761c23c) ^ (a >> 19);\n    a = (a + 0x165667b1) + (a << 5);\n    a = (a + 0xd3a2646c) ^ (a << 9);\n    a = (a + 0xfd7046c5) + (a << 3);\n    a = (a ^ 0xb55a4f09) ^ (a >> 16);\n    return a;\n}\n\n[numthreads(32, 32, 1)]\nvoid CSmain(CSParam param)\n{\n    uint2 extent;\n    VisibilityBuffer.GetDimensions(extent.x, extent.y);\n    \n    if (extent.x < param.DispatchThreadID.x || extent.y < param.DispatchThreadID.y)\n    {\n        return;\n    }\n    \n    if (DepthBuffer.Load(int3(param.DispatchThreadID.xy, 0)).r > 3e38f)\n    {\n        InstanceID[param.DispatchThreadID.xy] = 0.f;\n        PrimitiveID[param.DispatchThreadID.xy] = 0.f;\n        return;\n    }\n    \n    uint vbuffer = VisibilityBuffer.Load(int3(param.DispatchThreadID.xy, 0));\n    uint instance_id = 0;\n    uint primitive_id = 0;\n    uint mesh_type = 0;\n    \n    UnPackVisibilityBuffer(vbuffer, mesh_type, instance_id, primitive_id);\n    \n    uint mhash = hash(instance_id);\n    InstanceID[param.DispatchThreadID.xy] = float4(float3(float(mhash & 255), float((mhash >> 8) & 255), float((mhash >> 16) & 255)) / 255.0, 1.0);\n    \n    mhash = hash(primitive_id);\n    PrimitiveID[param.DispatchThreadID.xy] = float4(float3(float(mhash & 255), float((mhash >> 8) & 255), float((mhash >> 16) & 255)) / 255.0, 1.0);\n}"
  },
  {
    "path": "Source/Shaders/RenderPath/VisibilityGeometryPass.hlsl",
    "content": "#include \"../Common.hlsli\"\n\nStructuredBuffer<Instance> InstanceBuffer;\nStructuredBuffer<Meshlet> MeshletBuffer[];\nStructuredBuffer<uint> MeshletDataBuffer[];\nStructuredBuffer<uint> IndexBuffer[];\nConstantBuffer<View> ViewBuffer;\n\n#ifdef HAS_SKINNED\nStructuredBuffer<SkinnedVertex> VertexBuffer[];\nStructuredBuffer<float4x4> BoneMatrices[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    int4 Bones0 : BLENDINDICES0;\n    int4 Bones1 : BLENDINDICES1;\n    float4 Weights0 : BLENDWEIGHT0;\n    float4 Weights1 : BLENDWEIGHT1;\n    uint InstanceID : SV_InstanceID;\n};\n#else\nStructuredBuffer<Vertex> VertexBuffer[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    uint InstanceID : SV_InstanceID;\n};\n#endif\n\nstruct VertexOut\n{\n    float4 Position : SV_Position;\n    float2 Texcoord : TEXCOORD0;\n    uint InstanceID : COLOR0;\n};\n\nstruct PrimitiveOut\n{\n    uint InstanceID : COLOR1;\n    uint PrimitiveID : COLOR2;\n};\n\nstruct PayLoad\n{\n    uint MeshletIndices[32];\n    uint InstanceIndices[32];\n};\n\ngroupshared PayLoad s_payload;\n\n[numthreads(32, 1, 1)]\nvoid ASmain(CSParam param)\n{\n    bool visible = false;\n    \n    uint instance_id = param.DispatchThreadID.y;\n    uint meshlet_id = param.DispatchThreadID.x;\n    \n    uint instance_count = 0;\n    uint instance_stride = 0;\n    InstanceBuffer.GetDimensions(instance_count, instance_stride);\n    \n    if (instance_id < instance_count)\n    {\n        Instance instance = InstanceBuffer[instance_id];\n        \n        uint meshlet_count = 0;\n        uint meshlet_stride = 0;\n        MeshletBuffer[instance.mesh_id].GetDimensions(meshlet_count, meshlet_stride);\n        \n        if (meshlet_id < meshlet_count)\n        {\n#ifdef HAS_SKINNED\n            visible = true;\n#else\n            Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n            visible = ViewBuffer.IsVisible(meshlet, instance.transform);\n#endif\n        }\n    }\n\n    if (visible)\n    {\n        uint index = WavePrefixCountBits(visible);\n        s_payload.InstanceIndices[index] = instance_id;\n        s_payload.MeshletIndices[index] = meshlet_id;\n    }\n    \n    uint visible_count = WaveActiveCountBits(visible);\n    \n    DispatchMesh(visible_count, 1, 1, s_payload);\n}\n\n[outputtopology(\"triangle\")]\n[numthreads(32, 1, 1)]\nvoid MSmain(CSParam param, in payload PayLoad pay_load, out vertices VertexOut verts[64], out indices uint3 tris[124], out primitives PrimitiveOut prims[124])\n{\n    uint instance_id = pay_load.InstanceIndices[param.GroupID.x];\n    uint meshlet_id = pay_load.MeshletIndices[param.GroupID.x];\n    \n    Instance instance = InstanceBuffer[instance_id];\n    Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n    \n    uint meshlet_vertices_count = meshlet.vertex_count;\n    uint meshlet_triangle_count = meshlet.triangle_count;\n    \n    SetMeshOutputCounts(meshlet_vertices_count, meshlet_triangle_count);\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_vertices_count; i += 32)\n    {\n        uint vertex_id = MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + i];\n        \n#ifdef HAS_SKINNED\n        SkinnedVertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        if (instance.animation_id != ~0U)\n        {\n            uint bone_count = 0;\n            uint bone_stride = 0;\n            BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n            float4 total_position = 0.f;\n            for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n            {\n                if (vertex.bones[i] == -1)\n                {\n                    continue;\n                }\n                if (vertex.bones[i] >= bone_count)\n                {\n                    total_position = float4(vertex.position, 1.0f);\n                    break;\n                }\n                float4 local_position = mul(BoneMatrices[instance.animation_id][vertex.bones[i]], float4(vertex.position, 1.0f));\n                total_position += local_position * vertex.weights[i];\n            }\n            verts[i].Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(total_position.xyz, 1.0)));\n        }\n        else\n        {\n            verts[i].Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vertex.position.xyz, 1.0)));\n        }\n        \n        verts[i].Texcoord = vertex.texcoord0.xy;\n#else\n        Vertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        verts[i].Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vertex.position.xyz, 1.0)));\n        verts[i].Texcoord = vertex.texcoord0.xy;\n#endif\n    }\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_triangle_count; i += 32)\n    {\n        uint primitive_id = MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + meshlet.vertex_count + i];\n        \n        prims[i].InstanceID = instance_id;\n        prims[i].PrimitiveID = primitive_id;\n        \n        uint v0, v1, v2;\n        UnPackTriangle(MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + meshlet.vertex_count + meshlet.triangle_count + i], v0, v1, v2);\n        \n        tris[i] = uint3(v0, v1, v2);\n    }\n}\n\nuint PSmain(VertexOut vert, PrimitiveOut prim) : SV_TARGET0\n{\n    return PackVisibilityBuffer(\n#ifdef HAS_SKINNED\n        SKINNED_MESH_TYPE,\n#else\n        MESH_TYPE,\n#endif\n        prim.InstanceID, \n        prim.PrimitiveID);\n}\n\nvoid VSmain(in VertexIn vert_in, out VertexOut vert_out, out PrimitiveOut prim)\n{\n    Instance instance = InstanceBuffer[vert_in.InstanceID];\n    \n#ifdef HAS_SKINNED\n    if (instance.animation_id != ~0U)\n    {\n        uint bone_count = 0;\n        uint bone_stride = 0;\n        BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n        float4 total_position = 0.f;\n        for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n        {\n            int bone = -1;\n            float weight = 0.f;\n            \n            if (i < 4)\n            {\n                bone = vert_in.Bones0[i];\n                weight = vert_in.Weights0[i];\n            }\n            else\n            {\n                bone = vert_in.Bones1[i - 4];\n                weight = vert_in.Weights1[i - 4];\n            }\n            \n            if (bone == -1)\n            {\n                continue;\n            }\n            if (bone >= bone_count)\n            {\n                total_position = float4(vert_in.Position, 1.0f);\n                break;\n            }\n\n            float4 local_position = mul(BoneMatrices[instance.animation_id][bone], float4(vert_in.Position, 1.0f));\n            total_position += local_position * weight;\n        }\n        vert_out.Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(total_position.xyz, 1.0)));\n    }\n    else\n    {\n        vert_out.Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n    }\n#else\n    vert_out.Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n#endif\n    \n    vert_out.Texcoord = vert_in.Texcoord0.xy;\n    vert_out.InstanceID = vert_in.InstanceID;\n}\n\nuint FSmain(VertexOut vert, uint PrimitiveID : SV_PrimitiveID) : SV_Target0\n{\n    return PackVisibilityBuffer(\n#ifdef HAS_SKINNED\n        SKINNED_MESH_TYPE,\n#else\n        MESH_TYPE,\n#endif\n        vert.InstanceID,\n        PrimitiveID);\n}"
  },
  {
    "path": "Source/Shaders/RenderPath/VisibilityLightingPass.hlsl",
    "content": "#include \"../Common.hlsli\"\n#include \"../Random.hlsli\"\n#include \"../SphericalHarmonic.hlsli\"\n\n#define PREFILTER_MIP_LEVELS 5\n\n#ifndef RUNTIME\n#define HAS_MESH\n#define HAS_SKINNED_MESH\n#define HAS_POINT_LIGHT\n#define HAS_SPOT_LIGHT\n#define HAS_DIRECTIONAL_LIGHT\n#define HAS_RECT_LIGHT\n#define HAS_ENV_LIGHT\n#define HAS_SHADOW_MAP\n#define HAS_CASCADE_SHADOW_MAP\n#define HAS_OMNI_SHADOW_MAP\n#define HAS_IRRADIANCE_SH\n#define HAS_PREFILTER_MAP\n#define SHADOW_FILTER_NONE\n#define SHADOW_FILTER_HARD\n#define SHADOW_FILTER_PCF\n#define SHADOW_FILTER_PCSS\n#endif\n\nTexture2D<uint> VisibilityBuffer;\nTexture2D<float> DepthBuffer;\n\n#ifdef HAS_MESH\nStructuredBuffer<Instance> MeshInstanceBuffer;\n#endif\n#ifdef HAS_SKINNED_MESH\nStructuredBuffer<Instance> SkinnedMeshInstanceBuffer;\n#endif\n\nRWStructuredBuffer<uint> MaterialCountBuffer;\n\n[numthreads(8, 8, 1)]\nvoid CollectMaterialCount(CSParam param)\n{\n    uint2 dispatch_id = param.DispatchThreadID.xy;\n    \n    uint2 extent;\n    VisibilityBuffer.GetDimensions(extent.x, extent.y);\n    \n    if (dispatch_id.x >= extent.x ||\n        dispatch_id.y >= extent.y ||\n        DepthBuffer.Load(int3(dispatch_id, 0)).r > 3e38f)\n    {\n        return;\n    }\n    \n    uint mesh_type, instance_id, primitive_id;\n    UnPackVisibilityBuffer(VisibilityBuffer.Load(uint3(dispatch_id, 0)), mesh_type, instance_id, primitive_id);\n    \n    uint material_id = ~0;\n#ifdef HAS_MESH\n    if (mesh_type == MESH_TYPE)\n    {\n        material_id = MeshInstanceBuffer.Load(instance_id).material_id;\n    }\n#endif\n#ifdef HAS_SKINNED_MESH\n    if (mesh_type == SKINNED_MESH_TYPE)\n    {\n        material_id = SkinnedMeshInstanceBuffer.Load(instance_id).material_id;\n    }\n#endif\n    \n    if (material_id != ~0)\n    {\n        uint temp = 0;\n        InterlockedAdd(MaterialCountBuffer[material_id], 1, temp);\n    }\n}\n\nRWStructuredBuffer<uint> MaterialOffsetBuffer;\n\ngroupshared uint shared_data[256];\n\n[numthreads(128, 1, 1)]\nvoid CalculateMaterialOffset(CSParam param)\n{\n    uint id = param.GroupThreadID.x;\n    \n    uint material_count, temp;\n    MaterialCountBuffer.GetDimensions(material_count, temp);\n    \n    uint range = (1u << (uint(log2(material_count)) + 1u));\n    \n    if (id < material_count)\n    {\n        shared_data[id] = MaterialCountBuffer[id];\n    }\n    else\n    {\n        shared_data[id] = 0;\n    }\n    \n    GroupMemoryBarrierWithGroupSync();\n    \n    if (id >= range - 1)\n    {\n        return;\n    }\n    \n    uint steps = uint(log2(id + 1)) + 1u;\n    \n    for (uint step = 0; step < steps; step++)\n    {\n        uint rd_id = range - 2u - id;\n        uint wd_id = range - 2u - id + (1u << step);\n        shared_data[wd_id] += shared_data[rd_id];\n        GroupMemoryBarrierWithGroupSync();\n    }\n    \n    if (id < material_count - 1)\n    {\n        MaterialOffsetBuffer[id + 1] = shared_data[id];\n    }\n}\n\nRWStructuredBuffer<DispatchIndirectCommand> IndirectCommandBuffer;\nRWStructuredBuffer<uint> MaterialPixelBuffer;\n\n[numthreads(8, 8, 1)]\nvoid CalculatePixelBuffer(CSParam param)\n{\n    uint2 dispatch_id = param.DispatchThreadID.xy;\n    \n    uint2 extent;\n    VisibilityBuffer.GetDimensions(extent.x, extent.y);\n    \n    if (DepthBuffer.Load(int3(dispatch_id, 0)).r >= 3e38f ||\n        dispatch_id.x >= extent.x ||\n        dispatch_id.y >= extent.y)\n    {\n        return;\n    }\n    \n    uint mesh_type, instance_id, primitive_id;\n    UnPackVisibilityBuffer(VisibilityBuffer.Load(uint3(dispatch_id, 0)), mesh_type, instance_id, primitive_id);\n    \n    uint material_id = ~0;\n    \n#ifdef HAS_MESH\n    if (mesh_type == MESH_TYPE)\n    {\n        material_id = MeshInstanceBuffer.Load(instance_id).material_id;\n    }\n#endif\n    \n#ifdef HAS_SKINNED_MESH\n    if (mesh_type == SKINNED_MESH_TYPE)\n    {\n        material_id = SkinnedMeshInstanceBuffer.Load(instance_id).material_id;\n    }\n#endif\n    \n    uint idx;\n    InterlockedAdd(IndirectCommandBuffer[material_id].x, 1, idx);\n    MaterialPixelBuffer[idx + MaterialOffsetBuffer[material_id]] = PackXY(dispatch_id.x, dispatch_id.y);\n}\n\n[numthreads(8, 1, 1)]\nvoid CalculateIndirectArgument(CSParam param)\n{\n    uint dispatch_id = param.DispatchThreadID.x;\n    \n    uint material_count, temp;\n    IndirectCommandBuffer.GetDimensions(material_count, temp);\n    \n    if (dispatch_id >= material_count)\n    {\n        return;\n    }\n    \n    IndirectCommandBuffer[dispatch_id].x = (IndirectCommandBuffer[dispatch_id].x + 8 - 1) / 8;\n    IndirectCommandBuffer[dispatch_id].y = 1;\n    IndirectCommandBuffer[dispatch_id].z = 1;\n}\n\n#ifndef DISPATCH_INDIRECT\n#define MATERIAL_ID 0\n#include \"../Material/Material.hlsli\"\n#endif\n\n#include \"../Light.hlsli\"\n\nRWTexture2D<float4> LightDirectIllumination;\nRWTexture2D<float4> EnvDirectIllumination;\nRWTexture2D<float4> PositionDepth;\nRWTexture2D<float4> NormalRoughness;\nRWTexture2D<float4> AlbedoMetallic;\n\nConstantBuffer<View> ViewBuffer;\nConstantBuffer<LightInfo> LightInfoBuffer;\n\n#if defined(HAS_SHADOW_MAP) || defined(HAS_CASCADE_SHADOW_MAP) || defined(HAS_OMNI_SHADOW_MAP)\nSamplerState ShadowMapSampler;\n#endif\n\n#ifdef HAS_POINT_LIGHT\nStructuredBuffer<PointLight> PointLightBuffer;\n#ifdef HAS_OMNI_SHADOW_MAP\nTextureCubeArray<float> PointLightShadow;\n#endif\n#endif\n\n#ifdef HAS_SPOT_LIGHT\nStructuredBuffer<SpotLight> SpotLightBuffer;\n#ifdef HAS_SHADOW_MAP\nTexture2DArray<float> SpotLightShadow;\n#endif\n#endif\n\n#ifdef HAS_DIRECTIONAL_LIGHT\nStructuredBuffer<DirectionalLight> DirectionalLightBuffer;\n#ifdef HAS_CASCADE_SHADOW_MAP\nTexture2DArray<float> DirectionalLightShadow;\n#endif\n#endif\n\n#ifdef HAS_RECT_LIGHT\nStructuredBuffer<RectLight> RectLightBuffer;\n#endif\n\n#ifdef HAS_MESH\nStructuredBuffer<Vertex> MeshVertexBuffer[];\nStructuredBuffer<uint> MeshIndexBuffer[];\n#endif\n\n#ifdef HAS_SKINNED_MESH\nStructuredBuffer<SkinnedVertex> SkinnedMeshVertexBuffer[];\nStructuredBuffer<uint> SkinnedMeshIndexBuffer[];\nStructuredBuffer<float4x4> BoneMatrices[];\n#endif\n\n#ifdef HAS_ENV_LIGHT\n#ifdef HAS_IRRADIANCE_SH\nRWTexture2D<float4> IrradianceSH;\n#endif\n#ifdef HAS_PREFILTER_MAP\nSamplerState PrefilterMapSampler;\nTextureCube<float4> PrefilterMap;\nTexture2D<float2> GGXPreintegration;\n#endif\n#endif\n\nuint hash(uint a)\n{\n    a = (a + 0x7ed55d16) + (a << 12);\n    a = (a ^ 0xc761c23c) ^ (a >> 19);\n    a = (a + 0x165667b1) + (a << 5);\n    a = (a + 0xd3a2646c) ^ (a << 9);\n    a = (a + 0xfd7046c5) + (a << 3);\n    a = (a ^ 0xb55a4f09) ^ (a >> 16);\n    return a;\n}\n\nfloat3 GetColor(uint v)\n{\n    uint mhash = hash(v);\n    return float3(float(mhash & 255), float((mhash >> 8) & 255), float((mhash >> 16) & 255)) / 255.0;\n}\n\nvoid CalculateBarycentre(float4x4 transform, float2 pixel, uint2 extent, float3 v0, float3 v1, float3 v2, out float3 bary, out float3 bary_ddx, out float3 bary_ddy)\n{\n    float4 clip_pos0 = mul(ViewBuffer.view_projection_matrix, mul(transform, float4(v0.xyz, 1.0)));\n    float4 clip_pos1 = mul(ViewBuffer.view_projection_matrix, mul(transform, float4(v1.xyz, 1.0)));\n    float4 clip_pos2 = mul(ViewBuffer.view_projection_matrix, mul(transform, float4(v2.xyz, 1.0)));\n        \n    float2 p0 = clip_pos1.xy - clip_pos0.xy;\n    float2 p1 = clip_pos0.xy - clip_pos2.xy;\n        \n    // Calculate barycentric\n    float3 inv_w = rcp(float3(clip_pos0.w, clip_pos1.w, clip_pos2.w));\n        \n    float3 ndc0 = clip_pos0.xyz / clip_pos0.w;\n    float3 ndc1 = clip_pos1.xyz / clip_pos1.w;\n    float3 ndc2 = clip_pos2.xyz / clip_pos2.w;\n    float2 ndc = (float2(pixel) + float2(0.5, 0.5)) / float2(extent);\n    ndc = ndc * 2 - 1.0;\n    ndc.y *= -1;\n        \n    float3 pos_120_x = float3(ndc1.x, ndc2.x, ndc0.x);\n    float3 pos_120_y = float3(ndc1.y, ndc2.y, ndc0.y);\n    float3 pos_201_x = float3(ndc2.x, ndc0.x, ndc1.x);\n    float3 pos_201_y = float3(ndc2.y, ndc0.y, ndc1.y);\n        \n    float3 C_dx = pos_201_y - pos_120_y;\n    float3 C_dy = pos_120_x - pos_201_x;\n     \n    float3 C = C_dx * (ndc.x - pos_120_x) + C_dy * (ndc.y - pos_120_y);\n    float3 G = C * inv_w;\n    \n    float H = dot(C, inv_w);\n    float rcpH = rcp(H);\n        \n    bary = G * rcpH;\n        \n    float3 G_dx = C_dx * inv_w;\n    float3 G_dy = C_dy * inv_w;\n\n    float H_dx = dot(C_dx, inv_w);\n    float H_dy = dot(C_dy, inv_w);\n        \n    bary_ddx = (G_dx * H - G * H_dx) * (rcpH * rcpH) * (2.0f / float(extent.x));\n    bary_ddy = (G_dy * H - G * H_dy) * (rcpH * rcpH) * (-2.0f / float(extent.y));\n}\n\n#if defined(HAS_SHADOW_MAP) || defined(HAS_CASCADE_SHADOW_MAP) || defined(HAS_OMNI_SHADOW_MAP)\nfloat LinearizeDepth(float depth, float znear, float zfar)\n{\n    float z = depth * 2.0 - 1.0;\n    return znear * zfar / (zfar + depth * (znear - zfar));\n}\n\nfloat FindBlock(Texture2DArray<float> shadowmap, float4 shadow_coord, float layer, float filter_scale, uint filter_sample)\n{\n    uint2 tex_dim;\n    uint layers;\n    shadowmap.GetDimensions(tex_dim.x, tex_dim.y, layers);\n\n\t// Find blocker\n    float z_blocker = 0.0;\n    float num_blockers = 0.0;\n    float2 offset = float2(0.0, 0.0);\n    for (int i = 0; i < filter_sample; i++)\n    {\n        offset = PoissonDiskSamples2D(shadow_coord.xy + offset, filter_sample, 10, i);\n        offset = offset * filter_scale / float2(tex_dim);\n        float dist = shadowmap.SampleLevel(ShadowMapSampler, float3(shadow_coord.xy + offset, layer), 0.0).r;\n        if (dist < shadow_coord.z)\n        {\n            num_blockers += 1.0;\n            z_blocker += dist;\n        }\n    }\n\n    if (num_blockers == 0.0)\n    {\n        return 0.0;\n    }\n\n    return num_blockers == 0.0 ? 0.0 : z_blocker / num_blockers;\n}\n\nfloat FindBlockCube(TextureCubeArray<float> shadowmap, float3 L, float layer, float filter_scale, uint filter_sample)\n{\n    uint2 tex_dim;\n    uint layers;\n    shadowmap.GetDimensions(tex_dim.x, tex_dim.y, layers);\n\n    float light_depth = length(L);\n\n\t// Find blocker\n    float z_blocker = 0.0;\n    float num_blockers = 0.0;\n    float disk_radius = filter_scale / float(max(tex_dim.x, tex_dim.y));\n    float3 offset = float3(0.0, 0.0, 0.0);\n    \n    int x = int(sqrt(filter_sample));\n    int y = filter_sample / x;\n    for (int i = 0; i < x; i++)\n    {\n        for (int j = 0; j < y; j++)\n        {\n            // Poisson sampling\n            offset = PoissonDiskSamples3D(L + offset, x * y, 10, float2(i, j)) * disk_radius;\n            float dist = shadowmap.SampleLevel(ShadowMapSampler, float4(L + offset, layer), 0.0).r;\n            if (light_depth > dist)\n            {\n                num_blockers += 1.0;\n                z_blocker += dist;\n            }\n        }\n    }\n\n    if (num_blockers == 0.0)\n    {\n        return 0.0;\n    }\n\n    return num_blockers == 0.0 ? 0.0 : z_blocker / num_blockers;\n}\n\n// Sample shadow map\nfloat SampleShadowmap(Texture2DArray<float> shadowmap, float4 shadow_coord, float layer, float2 offset)\n{\n    float shadow = 1.0;\n\n    if (shadow_coord.z > -1.0 && shadow_coord.z < 1.0)\n    {\n        float dist = shadowmap.SampleLevel(ShadowMapSampler, float3(shadow_coord.xy + offset, layer), 0.0).r;\n        if (shadow_coord.w > 0.0 && dist < shadow_coord.z)\n        {\n            shadow = 0.0;\n        }\n    }\n    return shadow;\n}\n\n// Sample shadow map via PCF\nfloat SampleShadowmapPCF(Texture2DArray<float> shadowmap, float4 shadow_coord, float layer, uint filter_sample, float filter_scale)\n{\n    uint2 tex_dim;\n    uint layers;\n    shadowmap.GetDimensions(tex_dim.x, tex_dim.y, layers);\n\n    float shadow_factor = 0.0;\n\n    float2 offset = float2(0.0, 0.0);\n    for (int i = 0; i < filter_sample; i++)\n    {\n        offset = PoissonDiskSamples2D(shadow_coord.xy + offset, filter_sample, 10, i);\n        offset = offset * filter_scale / float2(tex_dim);\n        shadow_factor += SampleShadowmap(shadowmap, shadow_coord, layer, offset);\n    }\n\n    return shadow_factor / float(filter_sample);\n}\n\n// Sample shadow map via PCSS\nfloat SampleShadowmapPCSS(Texture2DArray<float> shadowmap, float4 shadow_coord, float layer, uint filter_sample, float filter_scale, float light_scale)\n{\n    uint2 tex_dim;\n    uint layers;\n    shadowmap.GetDimensions(tex_dim.x, tex_dim.y, layers);\n\n    float z_receiver = shadow_coord.z * shadow_coord.w;\n\n\t// Penumbra size\n    float z_blocker = LinearizeDepth(FindBlock(shadowmap, shadow_coord, layer, filter_scale, filter_sample), 0.01, 1000.0);\n    float w_light = 0.1;\n    float w_penumbra = (z_receiver - z_blocker) * light_scale / z_blocker;\n\n\t// Filtering\n    float shadow_factor = 0.0;\n    float2 offset = float2(0.0, 0.0);\n    for (int i = 0; i < filter_sample; i++)\n    {\n        offset = PoissonDiskSamples2D(shadow_coord.xy + offset, filter_sample, 10, i);\n        offset = offset * w_penumbra / float2(tex_dim);\n        shadow_factor += SampleShadowmap(shadowmap, shadow_coord, layer, offset);\n    }\n\n    return shadow_factor / float(filter_sample);\n}\n\n// Sample shadow cubemap\nfloat SampleShadowmapCube(TextureCubeArray<float> shadowmap, float3 L, float layer, float3 offset)\n{\n    float shadow = 1.0;\n    float light_depth = length(L);\n    L.z = -L.z;\n\t// Reconstruct depth\n    float dist = shadowmap.SampleLevel(ShadowMapSampler, float4(L + offset, layer), 0.0).r;\n    dist *= 100.0;\n\n    if (light_depth > dist)\n    {\n        shadow = 0.0;\n    }\n\n    return shadow;\n}\n\n// Sample shadow cubemap via PCF\nfloat SampleShadowmapCubePCF(TextureCubeArray<float> shadowmap, float3 L, float layer, float filter_scale, uint filter_sample)\n{\n    uint2 tex_dim;\n    uint layers;\n    shadowmap.GetDimensions(tex_dim.x, tex_dim.y, layers);\n\n    float shadow_factor = 0.0;\n    float light_depth = length(L);\n\n    float disk_radius = filter_scale / float(max(tex_dim.x, tex_dim.y));\n\n    float3 offset = float3(0.0, 0.0, 0.0);\n    int count = 0;\n    int x = int(sqrt(filter_sample));\n    int y = filter_sample / x;\n    count = x * y;\n    for (int i = 0; i < x; i++)\n    {\n        for (int j = 0; j < y; j++)\n        {\n            // Poisson sampling\n            offset = PoissonDiskSamples3D(L + offset, count, 10, float2(i, j)) * disk_radius;\n            shadow_factor += SampleShadowmapCube(shadowmap, L, layer, offset);\n        }\n    }\n    return shadow_factor / float(count);\n}\n\n// Sample shadow cubemap via PCSS\nfloat SampleShadowmapCubePCSS(TextureCubeArray<float> shadowmap, float3 L, float layer, float filter_scale, uint filter_sample, float light_scale)\n{\n    uint2 tex_dim;\n    uint layers;\n    shadowmap.GetDimensions(tex_dim.x, tex_dim.y, layers);\n\n    float light_depth = length(L);\n    float z_receiver = light_depth;\n\n\t// Penumbra size\n    float z_blocker = LinearizeDepth(FindBlockCube(shadowmap, L, layer, filter_scale, filter_sample), 0.01, 1000.0);\n    float w_light = 0.1;\n    float w_penumbra = (z_receiver - z_blocker) * light_scale / z_blocker;\n\n\t// Filtering\n    float shadow_factor = 0.0;\n    float3 offset = float3(0.0, 0.0, 0.0);\n    float disk_radius = filter_scale / float(max(tex_dim.x, tex_dim.y));\n    int count = 0;\n    int x = int(sqrt(filter_sample));\n    int y = filter_sample / x;\n    count = x * y;\n    for (int i = 0; i < x; i++)\n    {\n        for (int j = 0; j < y; j++)\n        {\n            // Poisson sampling\n            offset = PoissonDiskSamples3D(L + offset, count, 10, float2(i, j)) * w_penumbra / float(tex_dim.x);\n            shadow_factor += SampleShadowmapCube(shadowmap, L, layer, offset);\n        }\n    }\n    return shadow_factor / float(filter_sample);\n}\n#endif\n\n#ifdef HAS_POINT_LIGHT\nfloat CalculatePointLightShadow(PointLight light, uint idx, SurfaceInteraction interaction)\n{\n    float3 L = interaction.isect.p - light.position;\n    \n#ifdef HAS_OMNI_SHADOW_MAP\n#ifdef SHADOW_FILTER_NONE\n    return 1.f;\n#endif\n    \n#ifdef SHADOW_FILTER_HARD\n    return SampleShadowmapCube(PointLightShadow, L, idx, float3(0.0, 0.0, 0.0));\n#endif\n    \n#ifdef SHADOW_FILTER_PCF\n    return SampleShadowmapCubePCF(PointLightShadow, L, idx, light.filter_scale, light.filter_sample);\n#endif\n    \n#ifdef SHADOW_FILTER_PCSS\n    return SampleShadowmapCubePCSS(PointLightShadow, L, idx, light.filter_scale, light.filter_sample, light.light_scale);\n#endif\n    \n#else\n    return 1.f;\n#endif\n}\n#endif\n\n#ifdef HAS_SPOT_LIGHT\nfloat CalculateSpotLightShadow(SpotLight light, uint idx, SurfaceInteraction interaction)\n{\n    float4 shadow_clip = mul(light.view_projection, float4(interaction.isect.p, 1.0));\n    float4 shadow_coord = float4(shadow_clip.xyz / shadow_clip.w, shadow_clip.w);\n    shadow_coord.xy = shadow_coord.xy * 0.5 + 0.5;\n    shadow_coord.y = 1.0 - shadow_coord.y;\n\n#ifdef HAS_OMNI_SHADOW_MAP\n#ifdef SHADOW_FILTER_NONE\n    return 1.f;\n#endif\n    \n#ifdef SHADOW_FILTER_HARD\n    return SampleShadowmap(SpotLightShadow, shadow_coord, idx, float2(0.0, 0.0));\n#endif\n    \n#ifdef SHADOW_FILTER_PCF\n    return SampleShadowmapPCF(SpotLightShadow, shadow_coord, idx, light.filter_sample, light.filter_scale);\n#endif\n    \n#ifdef SHADOW_FILTER_PCSS\n    return SampleShadowmapPCSS(SpotLightShadow, shadow_coord, idx, light.filter_sample, light.filter_scale, light.light_scale);\n#endif\n    \n#else\n    return 1.f;\n#endif\n}\n#endif\n\n#ifdef HAS_DIRECTIONAL_LIGHT\nfloat CalculateDirectionalLightShadow(DirectionalLight light, uint idx, SurfaceInteraction interaction, float linear_z)\n{\n    float shadow = 1.f;\n    \n    linear_z = mul(ViewBuffer.view_projection_matrix, float4(interaction.isect.p, 1.f)).z;\n    \n    uint cascade_index = 0;\n\t// Select cascade\n    for (uint i = 0; i < 3; ++i)\n    {\n        if (light.split_depth[i] > -linear_z)\n        {\n            cascade_index = i + 1;\n        }\n    }\n\n    float4 shadow_clip = mul(light.view_projection[cascade_index], float4(interaction.isect.p, 1.0));\n    float4 shadow_coord = float4(shadow_clip.xyz / shadow_clip.w, shadow_clip.w);\n    shadow_coord.xy = shadow_coord.xy * 0.5 + 0.5;\n    shadow_coord.y = 1.0 - shadow_coord.y;\n\n    uint layer = idx * 4 + cascade_index;\n    \n#ifdef HAS_CASCADE_SHADOW_MAP\n#ifdef SHADOW_FILTER_NONE\n    return 1.f;\n#endif\n    \n#ifdef SHADOW_FILTER_HARD\n    return SampleShadowmap(DirectionalLightShadow, shadow_coord, idx * 4 + cascade_index, float2(0.0, 0.0));\n#endif\n    \n#ifdef SHADOW_FILTER_PCF\n    return SampleShadowmapPCF(DirectionalLightShadow, shadow_coord, idx * 4 + cascade_index, light.filter_sample, light.filter_scale);\n#endif\n    \n#ifdef SHADOW_FILTER_PCSS\n    return SampleShadowmapPCSS(DirectionalLightShadow, shadow_coord, idx * 4 + cascade_index, light.filter_sample, light.filter_scale, light.light_scale);\n#endif\n\n#else\n    return 1.f;\n#endif\n}\n#endif\n\n[numthreads(8, 1, 1)]\nvoid DispatchIndirect(CSParam param)\n{\n    uint id = param.DispatchThreadID.x;\n    uint offset = MaterialOffsetBuffer.Load(MATERIAL_ID);\n    uint count = MaterialCountBuffer.Load(MATERIAL_ID);\n    \n    if (id >= count)\n    {\n        return;\n    }\n    \n    uint2 extent;\n    VisibilityBuffer.GetDimensions(extent.x, extent.y);\n    \n    uint2 pixel;\n    UnpackXY(MaterialPixelBuffer.Load(id + offset), pixel.x, pixel.y);\n    \n    uint instance_id, primitive_id, mesh_type;\n    UnPackVisibilityBuffer(VisibilityBuffer.Load(uint3(pixel, 0)), mesh_type, instance_id, primitive_id);\n    \n    SurfaceInteraction interaction;\n    \n    float3 bary, bary_ddx, bary_ddy;\n    \n    float linear_z = 0.f;\n    \n#ifdef HAS_MESH\n    if (mesh_type == MESH_TYPE)\n    {\n        Instance instance = MeshInstanceBuffer.Load(instance_id);\n        uint mesh_id = instance.mesh_id;\n        \n        Vertex v0 = MeshVertexBuffer[mesh_id][MeshIndexBuffer[mesh_id][primitive_id * 3]];\n        Vertex v1 = MeshVertexBuffer[mesh_id][MeshIndexBuffer[mesh_id][primitive_id * 3 + 1]];\n        Vertex v2 = MeshVertexBuffer[mesh_id][MeshIndexBuffer[mesh_id][primitive_id * 3 + 2]];\n        \n        CalculateBarycentre(instance.transform, pixel, extent, v0.position, v1.position, v2.position, bary, bary_ddx, bary_ddy);\n        \n        interaction.isect.p = v0.position.xyz * bary.x + v1.position.xyz * bary.y + v2.position.xyz * bary.z;\n        linear_z = mul(ViewBuffer.view_matrix, mul(instance.transform, float4(interaction.isect.p, 1.0))).z;\n        interaction.isect.p = mul(instance.transform, float4(interaction.isect.p, 1.0)).xyz;\n        interaction.isect.uv = v0.texcoord0.xy * bary.x + v1.texcoord0.xy * bary.y + v2.texcoord0.xy * bary.z;\n        interaction.isect.n = v0.normal.xyz * bary.x + v1.normal.xyz * bary.y + v2.normal.xyz * bary.z;\n        interaction.isect.n = normalize(mul((float3x3) instance.transform, normalize(interaction.isect.n)));\n        interaction.isect.nt = v0.tangent.xyz * bary.x + v1.tangent.xyz * bary.y + v2.tangent.xyz * bary.z;\n        interaction.isect.nt = normalize(mul((float3x3) instance.transform, normalize(interaction.isect.nt)).xyz);\n        interaction.isect.wo = normalize(ViewBuffer.position - interaction.isect.p);\n        interaction.shading_n = dot(interaction.isect.n, interaction.isect.wo) <= 0 ? -interaction.isect.n : interaction.isect.n;\n        interaction.isect.t = length(ViewBuffer.position - interaction.isect.p);\n        interaction.material = instance.material_id;\n        interaction.duvdx = v0.texcoord0.xy * bary_ddx.x + v1.texcoord0.xy * bary_ddx.y + v2.texcoord0.xy * bary_ddx.z;\n        interaction.duvdy = v0.texcoord0.xy * bary_ddy.x + v1.texcoord0.xy * bary_ddy.y + v2.texcoord0.xy * bary_ddy.z;\n    }\n#endif\n    \n#ifdef HAS_SKINNED_MESH\n    if (mesh_type == SKINNED_MESH_TYPE)\n    {\n        Instance instance = SkinnedMeshInstanceBuffer.Load(instance_id);\n        uint mesh_id = instance.mesh_id;\n        \n        SkinnedVertex v[3];\n        \n        v[0] = SkinnedMeshVertexBuffer[mesh_id][SkinnedMeshIndexBuffer[mesh_id][primitive_id * 3]];\n        v[1] = SkinnedMeshVertexBuffer[mesh_id][SkinnedMeshIndexBuffer[mesh_id][primitive_id * 3 + 1]];\n        v[2] = SkinnedMeshVertexBuffer[mesh_id][SkinnedMeshIndexBuffer[mesh_id][primitive_id * 3 + 2]];\n        \n        float3 position[3];\n        float3 normal[3];\n        float3 tangent[3];\n        \n        if (instance.animation_id != ~0U)\n        {\n            uint bone_count = 0;\n            uint bone_stride = 0;\n            BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n            for (uint v_idx = 0; v_idx < 3; v_idx++)\n            {\n                position[v_idx] = 0.f;\n                normal[v_idx] = 0.f;\n                tangent[v_idx] = 0.f;\n                \n                for (uint bone_idx = 0; bone_idx < MAX_BONE_INFLUENCE; bone_idx++)\n                {\n                    int bone = v[v_idx].bones[bone_idx];\n                    float weight = v[v_idx].weights[bone_idx];\n            \n                    if (bone == -1)\n                    {\n                        continue;\n                    }\n                    \n                    if (bone >= bone_count)\n                    {\n                        position[v_idx] = v[v_idx].position;\n                        normal[v_idx] = v[v_idx].normal;\n                        tangent[v_idx] = v[v_idx].tangent;\n                        break;\n                    }\n\n                    position[v_idx] += mul(BoneMatrices[instance.animation_id][bone], float4(v[v_idx].position, 1.0f)).xyz * weight;\n                    normal[v_idx] += mul((float3x3) BoneMatrices[instance.animation_id][bone], v[v_idx].normal) * weight;\n                    tangent[v_idx] += mul((float3x3) BoneMatrices[instance.animation_id][bone], v[v_idx].tangent) * weight;\n                }\n            }\n        }\n        else\n        {\n            for (uint v_idx = 0; v_idx < 3; v_idx++)\n            {\n                position[v_idx] = v[v_idx].position;\n                normal[v_idx] = v[v_idx].normal;\n                tangent[v_idx] = v[v_idx].tangent;\n            }\n        }\n        \n        CalculateBarycentre(instance.transform, pixel, extent, position[0], position[1], position[2], bary, bary_ddx, bary_ddy);\n        \n        interaction.isect.p = position[0].xyz * bary.x + position[1].xyz * bary.y + position[2].xyz * bary.z;\n        linear_z = mul(ViewBuffer.view_matrix, mul(instance.transform, float4(interaction.isect.p, 1.0))).z;\n        interaction.isect.p = mul(instance.transform, float4(interaction.isect.p, 1.0)).xyz;\n        interaction.isect.uv = v[0].texcoord0.xy * bary.x + v[1].texcoord0.xy * bary.y + v[2].texcoord0.xy * bary.z;\n        interaction.isect.n = normal[0].xyz * bary.x + normal[1].xyz * bary.y + normal[2].xyz * bary.z;\n        interaction.isect.n = normalize(mul((float3x3) instance.transform, normalize(interaction.isect.n)));\n        interaction.isect.nt = tangent[0].xyz * bary.x + tangent[1].xyz * bary.y + tangent[2].xyz * bary.z;\n        interaction.isect.nt = normalize(mul((float3x3) instance.transform, normalize(interaction.isect.nt)).xyz);\n        interaction.isect.wo = normalize(ViewBuffer.position - interaction.isect.p);\n        interaction.shading_n = dot(interaction.isect.n, interaction.isect.wo) <= 0 ? -interaction.isect.n : interaction.isect.n;\n        interaction.isect.t = length(ViewBuffer.position - interaction.isect.p);\n        interaction.material = instance.material_id;\n        interaction.duvdx = v[0].texcoord0.xy * bary_ddx.x + v[1].texcoord0.xy * bary_ddx.y + v[2].texcoord0.xy * bary_ddx.z;\n        interaction.duvdy = v[0].texcoord0.xy * bary_ddy.x + v[1].texcoord0.xy * bary_ddy.y + v[2].texcoord0.xy * bary_ddy.z;\n    }\n#endif\n    \n    Material material;\n    material.Init(interaction);\n    \n    GBufferData g_buffer_data = material.bsdf.GetGBufferData();\n    \n    float3 radiance = g_buffer_data.emissive;\n    float3 ambient = 0.f;\n    \n    LightSampleContext li_ctx;\n    li_ctx.n = interaction.isect.n;\n    li_ctx.ns = interaction.shading_n;\n    li_ctx.p = interaction.isect.p;\n    \n    // Handle point light DI\n#ifdef HAS_POINT_LIGHT\n    uint point_light_id = 0;\n    for (uint i = 0; i < LightInfoBuffer.point_light_count; i++)\n    {\n        PointLight light = PointLightBuffer.Load(i);\n        LightLiSample light_sample = light.SampleLi(li_ctx, 0.f);\n        float3 f = material.bsdf.Eval(interaction.isect.wo, light_sample.wi, TransportMode_Radiance);\n        float3 color = f * light_sample.L;\n        if (light.cast_shadow)\n        {\n            color *= CalculatePointLightShadow(light, light.shadow_id, interaction);\n            point_light_id++;\n        }\n        radiance += color;\n\n    }\n#endif\n    \n    // Handle spot light DI\n#ifdef HAS_SPOT_LIGHT\n    uint spot_light_id = 0;\n    for (uint i = 0; i < LightInfoBuffer.spot_light_count; i++)\n    {\n        SpotLight light = SpotLightBuffer.Load(i);\n        LightLiSample light_sample = light.SampleLi(li_ctx, 0.f);\n        float3 f = material.bsdf.Eval(interaction.isect.wo, light_sample.wi, TransportMode_Radiance);\n        float3 color = f * light_sample.L;\n        if (light.cast_shadow)\n        {\n            color *= CalculateSpotLightShadow(light, light.shadow_id, interaction);\n            spot_light_id++;\n        }\n        radiance += color;\n    }\n#endif\n    \n    // Handle directional light DI\n#ifdef HAS_DIRECTIONAL_LIGHT\n    uint directional_light_id = 0;\n    for (uint i = 0; i < LightInfoBuffer.directional_light_count; i++)\n    {\n        DirectionalLight light = DirectionalLightBuffer.Load(i);\n        LightLiSample light_sample = light.SampleLi(li_ctx, 0.f);\n        float3 f = material.bsdf.Eval(interaction.isect.wo, light_sample.wi, TransportMode_Radiance);\n        float3 color = f * light_sample.L;\n        if (light.cast_shadow)\n        {\n            color *= CalculateDirectionalLightShadow(light, light.shadow_id, interaction, linear_z);\n            directional_light_id++;\n        }\n        radiance += color;\n    }\n#endif\n    \n#ifdef HAS_ENV_LIGHT\n    {\n#ifdef HAS_IRRADIANCE_SH\n        float3 F0 = float3(0.0, 0.0, 0.0);\n        F0 = lerp(F0, g_buffer_data.albedo.rgb, g_buffer_data.metallic);\n        float3 F = F0 + (max(float3(1.0 - g_buffer_data.roughness, 1.0 - g_buffer_data.roughness, 1.0 - g_buffer_data.roughness), F0) * pow(1.0 - max(dot(g_buffer_data.normal, interaction.isect.wo), 0.0), 5.0));\n        float3 Kd = (1.0 - F) * (1.0 - g_buffer_data.metallic);\n\n        float3 irradiance = float3(0.0, 0.0, 0.0);\n        SH9 basis = EvaluateSH(g_buffer_data.normal);\n        for (uint i = 0; i < 9; i++)\n        {\n            irradiance += IrradianceSH[uint2(i, 0)].rgb * basis.weights[i];\n        }\n        irradiance = max(float3(0.0, 0.0, 0.0), irradiance) * InvPI;\n        \n        float3 diffuse = irradiance * g_buffer_data.albedo.rgb;\n        ambient += Kd * diffuse;\n#endif\n\n#ifdef  HAS_PREFILTER_MAP\n        float3 prefiltered_color = PrefilterMap.SampleLevel(PrefilterMapSampler, reflect(-interaction.isect.wo, g_buffer_data.normal), g_buffer_data.roughness * PREFILTER_MIP_LEVELS).rgb;\n        float2 brdf = GGXPreintegration.SampleLevel(PrefilterMapSampler, float2(clamp(dot(g_buffer_data.normal, interaction.isect.wo), 0.0, 1.0), g_buffer_data.roughness), 0.0).rg;\n        float3 specular = prefiltered_color * (F * brdf.x + brdf.y);\n        ambient += specular;\n#endif\n    }\n#endif\n    \n    // Clamp toxic pixel\n    float lum = Luminance(radiance);\n    if (lum > 4.f)\n    {\n        radiance *= 4.f / lum;\n    }\n    \n    EnvDirectIllumination[pixel] = float4(ambient, 1.f);\n    LightDirectIllumination[pixel] = float4(radiance, 1.f);\n    PositionDepth[pixel] = float4(interaction.isect.p, linear_z);\n    NormalRoughness[pixel] = float4(g_buffer_data.normal * 0.5f + 0.5f, g_buffer_data.roughness);\n    AlbedoMetallic[pixel] = float4(g_buffer_data.albedo, g_buffer_data.metallic);\n}"
  },
  {
    "path": "Source/Shaders/Shading/Composite.hlsl",
    "content": "#include \"../Common.hlsli\"\n\nRWTexture2D<float4> Output;\n\n#ifndef RUNTIME\n#define HAS_LIGHT_DIRECT_ILLUMINATION\n#define HAS_ENV_DIRECT_ILLUMINATION\n#define HAS_AMBIENT_OCCLUSION\n#define HAS_ENVIRONMENT\n#endif\n\n#ifdef HAS_AMBIENT_OCCLUSION\nTexture2D<float> AmbientOcclusion;\n#endif\n\n#ifdef HAS_LIGHT_DIRECT_ILLUMINATION\nTexture2D<float4> LightDirectIllumination;\n#endif\n\n#ifdef HAS_ENV_DIRECT_ILLUMINATION\nTexture2D<float4> EnvDirectIllumination;\n#endif\n\n#ifdef HAS_ENVIRONMENT\nTexture2D<float4> Environment;\n#endif\n\n[numthreads(8, 8, 1)]\nvoid CSmain(CSParam param)\n{\n    uint2 extent;\n    Output.GetDimensions(extent.x, extent.y);\n    \n    if (param.DispatchThreadID.x >= extent.x ||\n        param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    float3 result = 0.f;\n    float3 environment = 0.f;\n#ifdef HAS_ENVIRONMENT\n    environment = Environment[param.DispatchThreadID.xy].xyz;\n#endif\n    \n    if (IsBlack(environment))\n    {\n#ifdef HAS_LIGHT_DIRECT_ILLUMINATION\n        result += LightDirectIllumination[param.DispatchThreadID.xy].xyz;\n#endif\n        \n#ifdef HAS_ENV_DIRECT_ILLUMINATION\n        float3 env_direct_illumination = EnvDirectIllumination[param.DispatchThreadID.xy].xyz;\n#ifdef HAS_AMBIENT_OCCLUSION\n        env_direct_illumination *= AmbientOcclusion[param.DispatchThreadID.xy].r;\n#endif\n        result += env_direct_illumination;\n#endif\n    }\n    else\n    {\n        result += environment;\n    }\n    \n    Output[param.DispatchThreadID.xy] = float4(result, 1.f);\n}"
  },
  {
    "path": "Source/Shaders/Shading/IBL.hlsl",
    "content": "#include \"../Common.hlsli\"\n#include \"../SphericalHarmonic.hlsli\"\n\n#define POSITIVE_X 0\n#define NEGATIVE_X 1\n#define POSITIVE_Y 2\n#define NEGATIVE_Y 3\n#define POSITIVE_Z 4\n#define NEGATIVE_Z 5\n\n#define LOCAL_SIZE 8\n\n#define SH_INTERMEDIATE_SIZE 128 / 8\n#define CUBEMAP_FACE_NUM 6\n#define PREFILTER_MAP_SIZE 256\n#define PREFILTER_MIP_LEVELS 5\n#define SAMPLE_COUNT 1024\n\nstruct Config\n{\n    uint2 extent;\n};\n\nConstantBuffer<Config> ConfigBuffer;\nRWTexture2DArray<float4> SHIntermediate;\nTextureCube Skybox;\nSamplerState SkyboxSampler;\n\ngroupshared SH9Color projection_shared_sh_coeffs[LOCAL_SIZE][LOCAL_SIZE];\ngroupshared float projection_shared_weights[LOCAL_SIZE][LOCAL_SIZE];\n\n[numthreads(LOCAL_SIZE, LOCAL_SIZE, 1)]\nvoid CubemapSHProjection(CSParam param)\n{\n    for (uint i = 0; i < 9; i++)\n    {\n        projection_shared_sh_coeffs[param.GroupThreadID.x][param.GroupThreadID.y].weights[i] = float3(0.0, 0.0, 0.0);\n    }\n\n    GroupMemoryBarrier();\n    \n    uint2 extent = { 128, 128 };\n\n    SH9 basis;\n\n    float3 dir = CalculateCubemapDirection(param.DispatchThreadID.z, param.DispatchThreadID.x, param.DispatchThreadID.y, extent.x, extent.y);\n    float solid_angle = CalculateSolidAngle(param.DispatchThreadID.x, param.DispatchThreadID.y, extent.x, extent.y);\n    float3 texel = Skybox.SampleLevel(SkyboxSampler, dir, 0.0).rgb;\n\n    basis = ProjectSH9(dir);\n\n    projection_shared_weights[param.GroupThreadID.x][param.GroupThreadID.y] = solid_angle;\n\n    for (uint i = 0; i < 9; i++)\n    {\n        projection_shared_sh_coeffs[param.GroupThreadID.x][param.GroupThreadID.y].weights[i] += texel * basis.weights[i] * solid_angle;\n    }\n\n    GroupMemoryBarrier();\n\n\t// Add up all coefficients and weights along the X axis\n    if (param.GroupThreadID.x == 0)\n    {\n        for (int i = 1; i < LOCAL_SIZE; i++)\n        {\n            projection_shared_weights[0][param.GroupThreadID.y] += projection_shared_weights[i][param.GroupThreadID.y];\n            for (int j = 0; j < 9; j++)\n            {\n                projection_shared_sh_coeffs[0][param.GroupThreadID.y].weights[j] += projection_shared_sh_coeffs[i][param.GroupThreadID.y].weights[j];\n            }\n        }\n    }\n\n    GroupMemoryBarrier();\n\n\t// Add up all coefficients and weights along the Y axis\n    if (param.GroupThreadID.x == 0 && param.GroupThreadID.y == 0)\n    {\n        for (int i = 1; i < LOCAL_SIZE; i++)\n        {\n            projection_shared_weights[0][0] += projection_shared_weights[0][i];\n            for (int j = 0; j < 9; j++)\n            {\n                projection_shared_sh_coeffs[0][0].weights[j] += projection_shared_sh_coeffs[0][i].weights[j];\n            }\n        }\n\n        for (int j = 0; j < 9; j++)\n        {\n            int3 p = int3(extent.x / LOCAL_SIZE * j + param.DispatchThreadID.x / LOCAL_SIZE, param.DispatchThreadID.y / LOCAL_SIZE, param.DispatchThreadID.z);\n            \n            SHIntermediate[p] = float4(projection_shared_sh_coeffs[0][0].weights[j], projection_shared_weights[0][0]);\n        }\n    }\n}\n\nRWTexture2D<float4> IrradianceSH;\n\ngroupshared float3 add_shared_sh_coeffs[SH_INTERMEDIATE_SIZE][CUBEMAP_FACE_NUM];\ngroupshared float add_shared_weights[SH_INTERMEDIATE_SIZE][CUBEMAP_FACE_NUM];\n\n[numthreads(1, SH_INTERMEDIATE_SIZE, CUBEMAP_FACE_NUM)]\nvoid CubemapSHAdd(CSParam param)\n{\n    add_shared_sh_coeffs[param.DispatchThreadID.y][param.DispatchThreadID.z] = float3(0.0, 0.0, 0.0);\n    add_shared_weights[param.DispatchThreadID.y][param.DispatchThreadID.z] = 0.0;\n\n    GroupMemoryBarrier();\n\n    for (uint i = 0; i < SH_INTERMEDIATE_SIZE; i++)\n    {\n        uint3 p = uint3(param.DispatchThreadID.x * SH_INTERMEDIATE_SIZE + i, param.DispatchThreadID.y, param.DispatchThreadID.z);\n        float4 val = SHIntermediate[p];\n        add_shared_sh_coeffs[param.DispatchThreadID.y][param.DispatchThreadID.z] += val.rgb;\n        add_shared_weights[param.DispatchThreadID.y][param.DispatchThreadID.z] += val.a;\n    }\n\n    GroupMemoryBarrier();\n\n    if (param.DispatchThreadID.z == 0)\n    {\n        for (uint i = 1; i < CUBEMAP_FACE_NUM; i++)\n        {\n            add_shared_sh_coeffs[param.DispatchThreadID.y][0] += add_shared_sh_coeffs[param.DispatchThreadID.y][i];\n            add_shared_weights[param.DispatchThreadID.y][0] += add_shared_weights[param.DispatchThreadID.y][i];\n        }\n    }\n\n    GroupMemoryBarrier();\n\n    if (param.DispatchThreadID.y == 0 && param.DispatchThreadID.z == 0)\n    {\n        for (uint i = 0; i < SH_INTERMEDIATE_SIZE; i++)\n        {\n            add_shared_sh_coeffs[0][0] += add_shared_sh_coeffs[i][0];\n            add_shared_weights[0][0] += add_shared_weights[i][0];\n        }\n\n        float scale = (4.0 * PI) / add_shared_weights[0][0];\n\n        IrradianceSH[int2(param.DispatchThreadID.x, 0)] = float4(add_shared_sh_coeffs[0][0] * scale, add_shared_weights[0][0]);\n    }\n}\n\nRWTexture2DArray<float4> PrefilterMap;\n\nfloat3 CalculateDirection(uint face_idx, uint face_x, uint face_y, uint2 extent)\n{\n    float u = 2.0 * (float(face_x) + 0.5) / float(extent.x) - 1.0;\n    float v = 2.0 * (float(face_y) + 0.5) / float(extent.y) - 1.0;\n    float x, y, z;\n\n    switch (face_idx)\n    {\n        case POSITIVE_X:\n            x = 1;\n            y = -v;\n            z = -u;\n            break;\n        case NEGATIVE_X:\n            x = -1;\n            y = -v;\n            z = u;\n            break;\n        case POSITIVE_Y:\n            x = u;\n            y = 1;\n            z = v;\n            break;\n        case NEGATIVE_Y:\n            x = u;\n            y = -1;\n            z = -v;\n            break;\n        case POSITIVE_Z:\n            x = u;\n            y = -v;\n            z = 1;\n            break;\n        case NEGATIVE_Z:\n            x = -u;\n            y = -v;\n            z = -1;\n            break;\n    }\n\t\n    return normalize(float3(x, y, z));\n}\n\nfloat GGX(float3 N, float3 H, float roughness)\n{\n    float a = roughness * roughness;\n    float a2 = a * a;\n    float NoH = max(dot(N, H), 0.f);\n    float NoH2 = NoH * NoH;\n    float nom = a2;\n    float denom = (NoH2 * (a2 - 1.f) + 1.f);\n    denom = PI * denom * denom;\n    return nom / denom;\n}\n\nfloat3 GGXImportanceSampling(float2 Xi, float3 N, float roughness)\n{\n    float a = roughness * roughness;\n\n    float phi = 2.0 * PI * Xi.x;\n    float cos_theta = sqrt((1.f - Xi.y) / (1.f + (a * a - 1.f) * Xi.y));\n    float sin_theta = sqrt(1.f - cos_theta * cos_theta);\n\n    float3 H = float3(\n        cos(phi) * sin_theta,\n        sin(phi) * sin_theta,\n        cos_theta);\n\n    float3 Up = N.z > 0.999 ? float3(0.0, 1.0, 0.0) : float3(0.0, 0.0, 1.0);\n    float3 T = normalize(cross(N, Up));\n    float3 B = normalize(cross(N, T));\n\n    return T * H.x + B * H.y + N * H.z;\n}\n\nfloat RadicalInverse_VdC(uint bits)\n{\n    bits = (bits << 16u) | (bits >> 16u);\n    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\n    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\n    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\n    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\n    return float(bits) * 2.3283064365386963e-10; // / 0x100000000\n}\n\nfloat2 Hammersley(uint i, uint N)\n{\n    return float2(float(i) / float(N), RadicalInverse_VdC(i));\n}\n\n[numthreads(LOCAL_SIZE, LOCAL_SIZE, 1)]\nvoid CubmapPrefilter(CSParam param)\n{\n    uint2 extent;\n    uint layers;\n    PrefilterMap.GetDimensions(extent.x, extent.y, layers);\n    \n    float3 colors[5] = {\n        float3(0, 0, 0),\n        float3(1, 0, 0),\n        float3(0, 1, 0),\n        float3(0, 0, 1),\n        float3(1, 1, 1),\n    };\n    \n    uint level = log2(PREFILTER_MAP_SIZE / extent.x);\n    float roughness = float(level) / float(PREFILTER_MIP_LEVELS - 1);\n    \n    if (param.DispatchThreadID.x >= extent.x ||\n        param.DispatchThreadID.y >= extent.y)\n    {\n        return;\n    }\n    \n    uint2 size;\n    Skybox.GetDimensions(size.x, size.y);\n    uint resolution = size.x;\n    \n    float3 N = CalculateDirection(param.DispatchThreadID.z, param.DispatchThreadID.x, param.DispatchThreadID.y, extent);\n    float3 R = N;\n    float3 V = R;\n\n    float3 prefilter_color = float3(0.0, 0.0, 0.0);\n    float total_weight = 0.0;\n\n    for (uint i = 0; i < SAMPLE_COUNT; i++)\n    {\n        float2 Xi = Hammersley(i, SAMPLE_COUNT);\n        float3 H = GGXImportanceSampling(Xi, N, roughness);\n        float3 L = normalize(2.0 * dot(V, H) * H - V);\n\n        float NoL = max(dot(N, L), 0.0);\n        if (NoL > 0.0)\n        {\n            float D = GGX(N, H, roughness);\n            float NoH = max(dot(N, H), 0.f);\n            float HoV = max(dot(H, V), 0.f);\n            float pdf = D * NoH / (4 * HoV) + 0.0001;\n            \n            float texel_ = 4.f * PI / (6.f * resolution * resolution);\n            float sample_ = 1.f / (float(SAMPLE_COUNT) * pdf + 0.0001f);\n            \n            float mip_level = (roughness == 0.0 ? 0.0 : 0.5f * log2(sample_ / texel_));\n            \n            prefilter_color += Skybox.SampleLevel(SkyboxSampler, L, mip_level).rgb * NoL;\n            total_weight += NoL;\n        }\n    }\n\n    prefilter_color /= total_weight;\n    PrefilterMap[int3(param.DispatchThreadID.xyz)] = float4(prefilter_color, 1.0);\n    //PrefilterMap[int3(param.DispatchThreadID.xyz)] = float4(colors[level], 1.0);\n}"
  },
  {
    "path": "Source/Shaders/Shading/Skybox.hlsl",
    "content": "#include \"Common.hlsli\"\n\nConstantBuffer<View> ViewBuffer;\nTextureCube Skybox;\nSamplerState SkyboxSampler;\n\nstruct VSInput\n{\n    uint VertexID : SV_VertexID;\n};\n\nstruct VSOutput\n{\n    float4 Pos : SV_Position;\n    float3 UVW : POSITION0;\n};\n\nstruct PSInput\n{\n    float3 UVW : POSITION0;\n};\n\nstruct PSOutput\n{\n    float4 Color : SV_Target0;\n};\n\n// A cube\nstatic const float3 vertices[] =\n{\n    { -1.0, -1.0, -1.0 }, // bottom-left\n    { 1.0, 1.0, -1.0 }, // top-right\n    { 1.0, -1.0, -1.0 }, // bottom-right\n    { 1.0, 1.0, -1.0 }, // top-right\n    { -1.0, -1.0, -1.0 }, // bottom-left\n    { -1.0, 1.0, -1.0 }, // top-left\n\t                                  // front face\n    { -1.0, -1.0, 1.0 }, // bottom-left\n    { 1.0, -1.0, 1.0 }, // bottom-right\n    { 1.0, 1.0, 1.0 }, // top-right\n    { 1.0, 1.0, 1.0 }, // top-right\n    { -1.0, 1.0, 1.0 }, // top-left\n    { -1.0, -1.0, 1.0 }, // bottom-left\n\t                                  // left face\n    { -1.0, 1.0, 1.0 }, // top-right\n    { -1.0, 1.0, -1.0 }, // top-left\n    { -1.0, -1.0, -1.0 }, // bottom-left\n    { -1.0, -1.0, -1.0 }, // bottom-left\n    { -1.0, -1.0, 1.0 }, // bottom-right\n    { -1.0, 1.0, 1.0 }, // top-right\n\t                                  // right face\n    { 1.0, 1.0, 1.0 }, // top-left\n    { 1.0, -1.0, -1.0 }, // bottom-right\n    { 1.0, 1.0, -1.0 }, // top-right\n    { 1.0, -1.0, -1.0 }, // bottom-right\n    { 1.0, 1.0, 1.0 }, // top-left\n    { 1.0, -1.0, 1.0 }, // bottom-left\n\t                                  // bottom face\n    { -1.0, -1.0, -1.0 }, // top-right\n    { 1.0, -1.0, -1.0 }, // top-left\n    { 1.0, -1.0, 1.0 }, // bottom-left\n    { 1.0, -1.0, 1.0 }, // bottom-left\n    { -1.0, -1.0, 1.0 }, // bottom-right\n    { -1.0, -1.0, -1.0 }, // top-right\n\t                                  // top face\n    { -1.0, 1.0, -1.0 }, // top-left\n    { 1.0, 1.0, 1.0 }, // bottom-right\n    { 1.0, 1.0, -1.0 }, // top-right\n    { 1.0, 1.0, 1.0 }, // bottom-right\n    { -1.0, 1.0, -1.0 }, // top-left\n    { -1.0, 1.0, 1.0 }, // bottom-left\n};\n\nVSOutput VSmain(VSInput input)\n{\n    VSOutput output;\n    output.UVW = vertices[input.VertexID];\n    output.Pos = mul(ViewBuffer.view_projection_matrix, float4(output.UVW + ViewBuffer.position, 1.0)).xyww;\n    return output;\n}\n\nPSOutput PSmain(PSInput input)\n{\n    PSOutput output;\n    output.Color = float4(Skybox.Sample(SkyboxSampler, input.UVW).rgb, 1.0);\n    return output;\n}"
  },
  {
    "path": "Source/Shaders/Shadow/CascadeShadowMap.hlsl",
    "content": "#include \"../Common.hlsli\"\n#include \"../Light.hlsli\"\n\nStructuredBuffer<Instance> InstanceBuffer;\nStructuredBuffer<Meshlet> MeshletBuffer[];\nStructuredBuffer<uint> MeshletDataBuffer[];\nStructuredBuffer<uint> IndexBuffer[];\nStructuredBuffer<DirectionalLight> DirectionalLightBuffer;\nConstantBuffer<LightInfo> LightInfoBuffer;\n\n#ifdef HAS_SKINNED\nStructuredBuffer<SkinnedVertex> VertexBuffer[];\nStructuredBuffer<float4x4> BoneMatrices[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    int4 Bones0 : BLENDINDICES0;\n    int4 Bones1 : BLENDINDICES1;\n    float4 Weights0 : BLENDWEIGHT0;\n    float4 Weights1 : BLENDWEIGHT1;\n    uint InstanceID : SV_InstanceID;\n};\n#else\nStructuredBuffer<Vertex> VertexBuffer[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    uint InstanceID : SV_InstanceID;\n};\n#endif\n\nstruct VertexOut\n{\n    float4 Position : SV_Position;\n    uint InstanceID : COLOR0;\n};\n\nstruct PrimitiveOut\n{\n    uint Layer : SV_RenderTargetArrayIndex;\n};\n\nstruct PayLoad\n{\n    uint MeshletIndices[32];\n    uint InstanceIndices[32];\n    uint LayerIndices[32];\n};\n\ngroupshared PayLoad s_payload;\n\n[numthreads(32, 1, 1)]\nvoid ASmain(CSParam param)\n{\n    bool visible = false;\n    \n    uint meshlet_id = param.DispatchThreadID.x;\n    uint instance_id = param.DispatchThreadID.y;\n    uint layer_id = param.DispatchThreadID.z;\n    \n    uint instance_count = 0;\n    uint instance_stride = 0;\n    InstanceBuffer.GetDimensions(instance_count, instance_stride);\n    \n    if (layer_id / 4 >= LightInfoBuffer.directional_light_count)\n    {\n        return;\n    }\n    \n    DirectionalLight light = DirectionalLightBuffer[layer_id / 4];\n    \n    if (!light.cast_shadow)\n    {\n        return;\n    }\n    \n    if (instance_id < instance_count)\n    {\n        Instance instance = InstanceBuffer[instance_id];\n        \n        uint meshlet_count = 0;\n        uint meshlet_stride = 0;\n        MeshletBuffer[instance.mesh_id].GetDimensions(meshlet_count, meshlet_stride);\n        \n        if (meshlet_id < meshlet_count)\n        {\n#ifdef HAS_SKINNED\n            visible = true;\n#else\n            Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n            float4 frustum[6];\n            CalculateFrustum(light.view_projection[layer_id % 4], frustum);\n            visible = IsInsideFrustum(meshlet, instance.transform, frustum, meshlet.center - light.direction);\n#endif\n        }\n    }\n\n    if (visible)\n    {\n        uint index = WavePrefixCountBits(visible);\n        s_payload.InstanceIndices[index] = instance_id;\n        s_payload.MeshletIndices[index] = meshlet_id;\n        s_payload.LayerIndices[index] = layer_id;\n    }\n    \n    uint visible_count = WaveActiveCountBits(visible);\n    \n    DispatchMesh(visible_count, 1, 1, s_payload);\n}\n\n[outputtopology(\"triangle\")]\n[numthreads(32, 1, 1)]\nvoid MSmain(CSParam param, in payload PayLoad pay_load, out vertices VertexOut verts[64], out indices uint3 tris[124], out primitives PrimitiveOut prims[124])\n{\n    uint instance_id = pay_load.InstanceIndices[param.GroupID.x];\n    uint meshlet_id = pay_load.MeshletIndices[param.GroupID.x];\n    uint layer_id = pay_load.LayerIndices[param.GroupID.x];\n    uint light_id = layer_id / 4;\n    \n    Instance instance = InstanceBuffer[instance_id];\n    Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n    DirectionalLight light = DirectionalLightBuffer[light_id];\n    \n    uint meshlet_vertices_count = meshlet.vertex_count;\n    uint meshlet_triangle_count = meshlet.triangle_count;\n    \n    SetMeshOutputCounts(meshlet_vertices_count, meshlet_triangle_count);\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_vertices_count; i += 32)\n    {\n        uint vertex_id = MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + i];\n        \n#ifdef HAS_SKINNED\n        SkinnedVertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        if (instance.animation_id != ~0U)\n        {\n            uint bone_count = 0;\n            uint bone_stride = 0;\n            BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n            float4 total_position = 0.f;\n            for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n            {\n                if (vertex.bones[i] == -1)\n                {\n                    continue;\n                }\n                if (vertex.bones[i] >= bone_count)\n                {\n                    total_position = float4(vertex.position, 1.0f);\n                    break;\n                }\n                float4 local_position = mul(BoneMatrices[instance.animation_id][vertex.bones[i]], float4(vertex.position, 1.0f));\n                total_position += local_position * vertex.weights[i];\n            }\n            verts[i].Position = mul(light.view_projection[layer_id % 4], mul(instance.transform, float4(total_position.xyz, 1.0)));\n        }\n        else\n        {\n            verts[i].Position = mul(light.view_projection[layer_id % 4], mul(instance.transform, float4(vertex.position.xyz, 1.0)));\n        }\n#else\n        Vertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        verts[i].Position = mul(light.view_projection[layer_id % 4], mul(instance.transform, float4(vertex.position.xyz, 1.0)));\n#endif\n    }\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_triangle_count; i += 32)\n    {\n        uint v0, v1, v2;\n        UnPackTriangle(MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + meshlet.vertex_count + meshlet.triangle_count + i], v0, v1, v2);\n        \n        tris[i] = uint3(v0, v1, v2);\n        prims[i].Layer = light.shadow_id * 4 + layer_id % 4;\n    }\n}\n\nvoid PSmain(VertexOut vert)\n{\n}\n\nvoid VSmain(in VertexIn vert_in, out VertexOut vert_out)\n{\n    Instance instance = InstanceBuffer[vert_in.InstanceID];\n    \n#ifdef HAS_SKINNED\n    if (instance.animation_id != ~0U)\n    {\n        uint bone_count = 0;\n        uint bone_stride = 0;\n        BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n        float4 total_position = 0.f;\n        for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n        {\n            int bone = -1;\n            float weight = 0.f;\n            \n            if (i < 4)\n            {\n                bone = vert_in.Bones0[i];\n                weight = vert_in.Weights0[i];\n            }\n            else\n            {\n                bone = vert_in.Bones1[i - 4];\n                weight = vert_in.Weights1[i - 4];\n            }\n            \n            if (bone == -1)\n            {\n                continue;\n            }\n            if (bone >= bone_count)\n            {\n                total_position = float4(vert_in.Position, 1.0f);\n                break;\n            }\n\n            float4 local_position = mul(BoneMatrices[instance.animation_id][bone], float4(vert_in.Position, 1.0f));\n            total_position += local_position * weight;\n        }\n        //vert_out.Position = mul(ViewBuffer.view_projection, mul(instance.transform, float4(total_position.xyz, 1.0)));\n    }\n    else\n    {\n       // vert_out.Position = mul(ViewBuffer.view_projection, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n    }\n#else\n    //vert_out.Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n#endif\n}\n\nvoid FSmain(VertexOut vert, uint PrimitiveID : SV_PrimitiveID)\n{\n}"
  },
  {
    "path": "Source/Shaders/Shadow/OmniShadowMap.hlsl",
    "content": "#include \"../Common.hlsli\"\n#include \"../Light.hlsli\"\n\nStructuredBuffer<Instance> InstanceBuffer;\nStructuredBuffer<Meshlet> MeshletBuffer[];\nStructuredBuffer<uint> MeshletDataBuffer[];\nStructuredBuffer<uint> IndexBuffer[];\nStructuredBuffer<PointLight> PointLightBuffer;\nConstantBuffer<LightInfo> LightInfoBuffer;\n\nstatic const float4x4 ViewProjection[6] =\n{\n    float4x4(\n        0, 0, 1.0001999, 1,\n        0, 1, 0, 0,\n        1, 0, 0, 0,\n        0, 0, -0.20002, 0\n    ),\n    float4x4(\n        0, 0, -1.0001999, -1,\n        0, 1, 0, 0,\n        -1, 0, 0, 0,\n        0, 0, -0.20002, 0\n    ),\n    float4x4(\n        1, 0, 0, 0,\n        0, 0, 1.0001999, 1,\n        0, 1, 0, 0,\n        0, 0, -0.20002, 0\n    ),\n    float4x4(\n        1, 0, 0, 0,\n        0, 0, -1.0001999, -1,\n        0, -1, 0, 0,\n        0, 0, -0.20002, 0\n    ),\n    float4x4(\n        1, 0, 0, 0,\n        0, 1, 0, 0,\n        0, 0, -1.0001999, -1,\n        0, 0, -0.20002, 0\n    ),\n    float4x4(\n        -1, 0, 0, 0,\n        0, 1, 0, 0,\n        0, 0, 1.0001999, 1,\n        0, 0, -0.20002, 0\n    ),\n};\n\n#ifdef HAS_SKINNED\nStructuredBuffer<SkinnedVertex> VertexBuffer[];\nStructuredBuffer<float4x4> BoneMatrices[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    int4 Bones0 : BLENDINDICES0;\n    int4 Bones1 : BLENDINDICES1;\n    float4 Weights0 : BLENDWEIGHT0;\n    float4 Weights1 : BLENDWEIGHT1;\n    uint InstanceID : SV_InstanceID;\n};\n#else\nStructuredBuffer<Vertex> VertexBuffer[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    uint InstanceID : SV_InstanceID;\n};\n#endif\n\nstruct VertexOut\n{\n    float4 Position : SV_Position;\n    float3 Pos : POSITION0;\n    float3 LightPos : POSITION1;\n    uint InstanceID : COLOR0;\n};\n\nstruct PrimitiveOut\n{\n    uint Layer : SV_RenderTargetArrayIndex;\n};\n\nstruct PayLoad\n{\n    uint MeshletIndices[32];\n    uint InstanceIndices[32];\n    uint LayerIndices[32];\n};\n\ngroupshared PayLoad s_payload;\n\n[numthreads(32, 1, 1)]\nvoid ASmain(CSParam param)\n{\n    bool visible = false;\n    \n    uint meshlet_id = param.DispatchThreadID.x;\n    uint instance_id = param.DispatchThreadID.y;\n    uint layer_id = param.DispatchThreadID.z;\n    \n    uint instance_count = 0;\n    uint instance_stride = 0;\n    InstanceBuffer.GetDimensions(instance_count, instance_stride);\n    \n    if (layer_id / 6 >= LightInfoBuffer.point_light_count)\n    {\n        return;\n    }\n    \n    PointLight light = PointLightBuffer[layer_id / 6];\n    \n    if (!light.cast_shadow)\n    {\n        return;\n    }\n    \n    if (instance_id < instance_count)\n    {\n        Instance instance = InstanceBuffer[instance_id];\n        \n        uint meshlet_count = 0;\n        uint meshlet_stride = 0;\n        MeshletBuffer[instance.mesh_id].GetDimensions(meshlet_count, meshlet_stride);\n        \n        if (meshlet_id < meshlet_count)\n        {\n#ifdef HAS_SKINNED\n            visible = true;\n#else\n            Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n            float4 frustum[6];\n            CalculateFrustum(transpose(ViewProjection[layer_id % 6]), frustum);\n            visible = IsInsideFrustum(meshlet, instance.transform, frustum, light.position, light.position);\n#endif\n        }\n    }\n\n    if (visible)\n    {\n        uint index = WavePrefixCountBits(visible);\n        s_payload.InstanceIndices[index] = instance_id;\n        s_payload.MeshletIndices[index] = meshlet_id;\n        s_payload.LayerIndices[index] = layer_id;\n    }\n    \n    uint visible_count = WaveActiveCountBits(visible);\n    \n    DispatchMesh(visible_count, 1, 1, s_payload);\n}\n\n[outputtopology(\"triangle\")]\n[numthreads(32, 1, 1)]\nvoid MSmain(CSParam param, in payload PayLoad pay_load, out vertices VertexOut verts[64], out indices uint3 tris[124], out primitives PrimitiveOut prims[124])\n{\n    uint instance_id = pay_load.InstanceIndices[param.GroupID.x];\n    uint meshlet_id = pay_load.MeshletIndices[param.GroupID.x];\n    uint layer_id = pay_load.LayerIndices[param.GroupID.x];\n    uint light_id = layer_id / 6;\n    \n    Instance instance = InstanceBuffer[instance_id];\n    Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n    PointLight light = PointLightBuffer[light_id];\n    \n    uint meshlet_vertices_count = meshlet.vertex_count;\n    uint meshlet_triangle_count = meshlet.triangle_count;\n    \n    SetMeshOutputCounts(meshlet_vertices_count, meshlet_triangle_count);\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_vertices_count; i += 32)\n    {\n        uint vertex_id = MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + i];\n        \n        verts[i].LightPos = light.position;\n        \n#ifdef HAS_SKINNED\n        SkinnedVertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        if (instance.animation_id != ~0U)\n        {\n            uint bone_count = 0;\n            uint bone_stride = 0;\n            BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n            float4 total_position = 0.f;\n            for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n            {\n                if (vertex.bones[i] == -1)\n                {\n                    continue;\n                }\n                if (vertex.bones[i] >= bone_count)\n                {\n                    total_position = float4(vertex.position, 1.0f);\n                    break;\n                }\n                float4 local_position = mul(BoneMatrices[instance.animation_id][vertex.bones[i]], float4(vertex.position, 1.0f));\n                total_position += local_position * vertex.weights[i];\n            }\n            verts[i].Pos = mul(instance.transform, float4(total_position.xyz, 1.0)).xyz;\n            verts[i].Position = mul(transpose(ViewProjection[layer_id % 6]), float4(mul(instance.transform, float4(total_position.xyz, 1.0)).xyz - light.position, 1.f));\n        }\n        else\n        {\n            verts[i].Pos = mul(instance.transform, float4(vertex.position.xyz, 1.0)).xyz;\n            verts[i].Position = mul(transpose(ViewProjection[layer_id % 6]), float4(mul(instance.transform, float4(vertex.position.xyz, 1.0)).xyz - light.position, 1.f));\n        }\n#else\n        Vertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        verts[i].Pos = mul(instance.transform, float4(vertex.position.xyz, 1.0)).xyz;\n        verts[i].Position = mul(transpose(ViewProjection[layer_id % 6]), float4(mul(instance.transform, float4(vertex.position.xyz, 1.0)).xyz - light.position, 1.f));\n#endif\n    }\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_triangle_count; i += 32)\n    {\n        uint v0, v1, v2;\n        UnPackTriangle(MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + meshlet.vertex_count + meshlet.triangle_count + i], v0, v1, v2);\n        \n        tris[i] = uint3(v0, v1, v2);\n        prims[i].Layer = light.shadow_id * 6 + layer_id % 6;\n    }\n}\n\nfloat PSmain(VertexOut vert) : SV_Depth\n{\n    return (length(vert.Pos.xyz - vert.LightPos.xyz) + 0.01) / 100.0;\n}\n\nvoid VSmain(in VertexIn vert_in, out VertexOut vert_out)\n{\n    Instance instance = InstanceBuffer[vert_in.InstanceID];\n    \n#ifdef HAS_SKINNED\n    if (instance.animation_id != ~0U)\n    {\n        uint bone_count = 0;\n        uint bone_stride = 0;\n        BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n        float4 total_position = 0.f;\n        for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n        {\n            int bone = -1;\n            float weight = 0.f;\n            \n            if (i < 4)\n            {\n                bone = vert_in.Bones0[i];\n                weight = vert_in.Weights0[i];\n            }\n            else\n            {\n                bone = vert_in.Bones1[i - 4];\n                weight = vert_in.Weights1[i - 4];\n            }\n            \n            if (bone == -1)\n            {\n                continue;\n            }\n            if (bone >= bone_count)\n            {\n                total_position = float4(vert_in.Position, 1.0f);\n                break;\n            }\n\n            float4 local_position = mul(BoneMatrices[instance.animation_id][bone], float4(vert_in.Position, 1.0f));\n            total_position += local_position * weight;\n        }\n        //vert_out.Position = mul(ViewBuffer.view_projection, mul(instance.transform, float4(total_position.xyz, 1.0)));\n    }\n    else\n    {\n       // vert_out.Position = mul(ViewBuffer.view_projection, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n    }\n#else\n    //vert_out.Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n#endif\n}\n\nvoid FSmain(VertexOut vert, uint PrimitiveID : SV_PrimitiveID)\n{\n}"
  },
  {
    "path": "Source/Shaders/Shadow/RayTracedShadow.hlsl",
    "content": ""
  },
  {
    "path": "Source/Shaders/Shadow/ShadowMap.hlsl",
    "content": "#include \"../Common.hlsli\"\n#include \"../Light.hlsli\"\n\nStructuredBuffer<Instance> InstanceBuffer;\nStructuredBuffer<Meshlet> MeshletBuffer[];\nStructuredBuffer<uint> MeshletDataBuffer[];\nStructuredBuffer<uint> IndexBuffer[];\nStructuredBuffer<SpotLight> SpotLightBuffer;\nConstantBuffer<LightInfo> LightInfoBuffer;\n\n#ifdef HAS_SKINNED\nStructuredBuffer<SkinnedVertex> VertexBuffer[];\nStructuredBuffer<float4x4> BoneMatrices[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    int4 Bones0 : BLENDINDICES0;\n    int4 Bones1 : BLENDINDICES1;\n    float4 Weights0 : BLENDWEIGHT0;\n    float4 Weights1 : BLENDWEIGHT1;\n    uint InstanceID : SV_InstanceID;\n};\n#else\nStructuredBuffer<Vertex> VertexBuffer[];\n\nstruct VertexIn\n{\n    float3 Position : POSITION0;\n    float3 Normal : NORMAL0;\n    float3 Tangent : TANGENT0;\n    float2 Texcoord0 : TEXCOORD0;\n    float2 Texcoord1 : TEXCOORD1;\n    uint InstanceID : SV_InstanceID;\n};\n#endif\n\nstruct VertexOut\n{\n    float4 Position : SV_Position;\n    uint InstanceID : COLOR0;\n};\n\nstruct PrimitiveOut\n{\n    uint Layer : SV_RenderTargetArrayIndex;\n};\n\nstruct PayLoad\n{\n    uint MeshletIndices[32];\n    uint InstanceIndices[32];\n    uint LightIndices[32];\n};\n\ngroupshared PayLoad s_payload;\n\n[numthreads(32, 1, 1)]\nvoid ASmain(CSParam param)\n{\n    bool visible = false;\n    \n    uint meshlet_id = param.DispatchThreadID.x;\n    uint instance_id = param.DispatchThreadID.y;\n    uint light_id = param.DispatchThreadID.z;\n    \n    if (light_id >= LightInfoBuffer.spot_light_count)\n    {\n        return;\n    }\n    \n    SpotLight light = SpotLightBuffer[light_id];\n    \n    if(!light.cast_shadow)\n    {\n        return;\n    }\n    \n    uint instance_count = 0;\n    uint instance_stride = 0;\n    InstanceBuffer.GetDimensions(instance_count, instance_stride);\n    \n    if (instance_id < instance_count)\n    {\n        Instance instance = InstanceBuffer[instance_id];\n        \n        uint meshlet_count = 0;\n        uint meshlet_stride = 0;\n        MeshletBuffer[instance.mesh_id].GetDimensions(meshlet_count, meshlet_stride);\n        \n        if (meshlet_id < meshlet_count)\n        {\n#ifdef HAS_SKINNED\n            visible = true;\n#else\n            Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n            float4 frustum[6];\n            CalculateFrustum(light.view_projection, frustum);\n            visible = IsInsideFrustum(meshlet, instance.transform, frustum, light.position);\n           // visible = true;\n#endif\n        }\n    }\n\n    if (visible)\n    {\n        uint index = WavePrefixCountBits(visible);\n        s_payload.InstanceIndices[index] = instance_id;\n        s_payload.MeshletIndices[index] = meshlet_id;\n        s_payload.LightIndices[index] = light_id;\n    }\n    \n    uint visible_count = WaveActiveCountBits(visible);\n    \n    DispatchMesh(visible_count, 1, 1, s_payload);\n}\n\n[outputtopology(\"triangle\")]\n[numthreads(32, 1, 1)]\nvoid MSmain(CSParam param, in payload PayLoad pay_load, out vertices VertexOut verts[64], out indices uint3 tris[124], out primitives PrimitiveOut prims[124])\n{\n    uint instance_id = pay_load.InstanceIndices[param.GroupID.x];\n    uint meshlet_id = pay_load.MeshletIndices[param.GroupID.x];\n    uint light_id = pay_load.LightIndices[param.GroupID.x];\n    \n    Instance instance = InstanceBuffer[instance_id];\n    Meshlet meshlet = MeshletBuffer[instance.mesh_id][meshlet_id];\n    SpotLight light = SpotLightBuffer[light_id];\n    \n    uint meshlet_vertices_count = meshlet.vertex_count;\n    uint meshlet_triangle_count = meshlet.triangle_count;\n    \n    SetMeshOutputCounts(meshlet_vertices_count, meshlet_triangle_count);\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_vertices_count; i += 32)\n    {\n        uint vertex_id = MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + i];\n        \n#ifdef HAS_SKINNED\n        SkinnedVertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        if (instance.animation_id != ~0U)\n        {\n            uint bone_count = 0;\n            uint bone_stride = 0;\n            BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n            float4 total_position = 0.f;\n            for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n            {\n                if (vertex.bones[i] == -1)\n                {\n                    continue;\n                }\n                if (vertex.bones[i] >= bone_count)\n                {\n                    total_position = float4(vertex.position, 1.0f);\n                    break;\n                }\n                float4 local_position = mul(BoneMatrices[instance.animation_id][vertex.bones[i]], float4(vertex.position, 1.0f));\n                total_position += local_position * vertex.weights[i];\n            }\n            verts[i].Position = mul(light.view_projection, mul(instance.transform, float4(total_position.xyz, 1.0)));\n        }\n        else\n        {\n            verts[i].Position = mul(light.view_projection, mul(instance.transform, float4(vertex.position.xyz, 1.0)));\n        }\n#else\n        Vertex vertex = VertexBuffer[instance.mesh_id][vertex_id];\n        \n        verts[i].Position = mul(light.view_projection, mul(instance.transform, float4(vertex.position.xyz, 1.0)));\n#endif\n    }\n    \n    for (uint i = param.GroupThreadID.x; i < meshlet_triangle_count; i += 32)\n    {\n        uint v0, v1, v2;\n        UnPackTriangle(MeshletDataBuffer[instance.mesh_id][meshlet.data_offset + meshlet.vertex_count + meshlet.triangle_count + i], v0, v1, v2);\n        \n        tris[i] = uint3(v0, v1, v2);\n        prims[i].Layer = light.shadow_id;\n    }\n}\n\nvoid PSmain(VertexOut vert)\n{\n}\n\nvoid VSmain(in VertexIn vert_in, out VertexOut vert_out)\n{\n    Instance instance = InstanceBuffer[vert_in.InstanceID];\n    \n#ifdef HAS_SKINNED\n    if (instance.animation_id != ~0U)\n    {\n        uint bone_count = 0;\n        uint bone_stride = 0;\n        BoneMatrices[instance.animation_id].GetDimensions(bone_count, bone_stride);\n            \n        float4 total_position = 0.f;\n        for (uint i = 0; i < MAX_BONE_INFLUENCE; i++)\n        {\n            int bone = -1;\n            float weight = 0.f;\n            \n            if (i < 4)\n            {\n                bone = vert_in.Bones0[i];\n                weight = vert_in.Weights0[i];\n            }\n            else\n            {\n                bone = vert_in.Bones1[i - 4];\n                weight = vert_in.Weights1[i - 4];\n            }\n            \n            if (bone == -1)\n            {\n                continue;\n            }\n            if (bone >= bone_count)\n            {\n                total_position = float4(vert_in.Position, 1.0f);\n                break;\n            }\n\n            float4 local_position = mul(BoneMatrices[instance.animation_id][bone], float4(vert_in.Position, 1.0f));\n            total_position += local_position * weight;\n        }\n        //vert_out.Position = mul(ViewBuffer.view_projection, mul(instance.transform, float4(total_position.xyz, 1.0)));\n    }\n    else\n    {\n       // vert_out.Position = mul(ViewBuffer.view_projection, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n    }\n#else\n    //vert_out.Position = mul(ViewBuffer.view_projection_matrix, mul(instance.transform, float4(vert_in.Position.xyz, 1.0)));\n#endif\n}\n\nvoid FSmain(VertexOut vert, uint PrimitiveID : SV_PrimitiveID)\n{\n}"
  },
  {
    "path": "Source/Shaders/SphericalHarmonic.hlsli",
    "content": "#ifndef __SPHERICALHARMONIC_HLSL__\n#define __SPHERICALHARMONIC_HLSL__\n\n#include \"Math.hlsli\"\n\nstatic const float CosineA0 = PI;\nstatic const float CosineA1 = (2.0 * PI) / 3.0;\nstatic const float CosineA2 = PI * 0.25;\n\nstruct SH9\n{\n    float weights[9];\n};\n\nstruct SH9Color\n{\n    float3 weights[9];\n};\n\nSH9 ProjectSH9(float3 dir)\n{\n    SH9 sh;\n\n    sh.weights[0] = 0.282095;\n\n    sh.weights[1] = -0.488603 * dir.y;\n    sh.weights[2] = 0.488603 * dir.z;\n    sh.weights[3] = -0.488603 * dir.x;\n\n    sh.weights[4] = 1.092548 * dir.x * dir.y;\n    sh.weights[5] = -1.092548 * dir.y * dir.z;\n    sh.weights[7] = 0.315392 * (3.0 * dir.z * dir.z - 1.0);\n    sh.weights[6] = -1.092548 * dir.x * dir.z;\n    sh.weights[8] = 0.546274 * (dir.x * dir.x - dir.y * dir.y);\n\n    return sh;\n}\n\nSH9 EvaluateSH(float3 dir)\n{\n    SH9 basis = ProjectSH9(dir);\n\n    basis.weights[0] *= CosineA0;\n\n    basis.weights[1] *= CosineA1;\n    basis.weights[2] *= CosineA1;\n    basis.weights[3] *= CosineA1;\n\n    basis.weights[4] *= CosineA2;\n    basis.weights[5] *= CosineA2;\n    basis.weights[6] *= CosineA2;\n    basis.weights[7] *= CosineA2;\n    basis.weights[8] *= CosineA2;\n\n    return basis;\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/Tonemapper.hlsli",
    "content": "#ifndef __TONEMAPPER_HLSL__\n#define __TONEMAPPER_HLSL__\n\nstatic const float GAMMA = 2.2;\nstatic const float INV_GAMMA = 1.0 / GAMMA;\n\n// linear to sRGB approximation\n// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html\nfloat3 LinearTosRGB(float3 color)\n{\n    return pow(color, float3(INV_GAMMA, INV_GAMMA, INV_GAMMA));\n}\n\n// sRGB to linear approximation\n// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html\nfloat3 sRGBToLinear(float3 srgbIn)\n{\n    return float3(pow(srgbIn.xyz, float3(GAMMA, GAMMA, GAMMA)));\n}\n\nfloat4 sRGBToLinear(float4 srgbIn)\n{\n    return float4(sRGBToLinear(srgbIn.xyz), srgbIn.w);\n}\n\n// Uncharted 2 tone map\n// see: http://filmicworlds.com/blog/filmic-tonemapping-operators/\nfloat3 ToneMapUncharted2Impl(float3 color)\n{\n    const float A = 0.15;\n    const float B = 0.50;\n    const float C = 0.10;\n    const float D = 0.20;\n    const float E = 0.02;\n    const float F = 0.30;\n    return ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;\n}\n\nfloat3 ToneMapUncharted(float3 color)\n{\n    const float W = 11.2;\n    color = ToneMapUncharted2Impl(color * 2.0);\n    float3 whiteScale = 1.0 / ToneMapUncharted2Impl(float3(W, W, W));\n    return LinearTosRGB(color * whiteScale);\n}\n\n// Hejl Richard tone map\n// see: http://filmicworlds.com/blog/filmic-tonemapping-operators/\nfloat3 ToneMapHejlRichard(float3 color)\n{\n    color = max(float3(0.0, 0.0, 0.0), color - float3(0.004, 0.004, 0.004));\n    return (color * (6.2 * color + .5)) / (color * (6.2 * color + 1.7) + 0.06);\n}\n\n// ACES tone map\n// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/\nfloat3 ToneMapACES(float3 color)\n{\n    const float A = 2.51;\n    const float B = 0.03;\n    const float C = 2.43;\n    const float D = 0.59;\n    const float E = 0.14;\n    return LinearTosRGB(clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0));\n}\n\n\nfloat3 ToneMap(float3 color, float exposure)\n{\n    color *= exposure;\n\n#ifdef TONEMAP_UNCHARTED\n  return ToneMapUncharted(color);\n#endif\n\n#ifdef TONEMAP_HEJLRICHARD\n  return ToneMapHejlRichard(color);\n#endif\n\n#ifdef TONEMAP_ACES\n  return ToneMapACES(color);\n#endif\n\n    return LinearTosRGB(color);\n}\n\n#endif"
  },
  {
    "path": "Source/Shaders/UpdateBoneMatrics.hlsl",
    "content": "struct UpdateInfoData\n{\n    uint count;\n    float time;\n};\n\nTexture2D<float4> SkinnedMatrics;\nRWStructuredBuffer<float4x4> BoneMatrics;\nConstantBuffer<UpdateInfoData> UpdateInfo;\n\nstruct CSParam\n{\n    uint3 DispatchThreadID : SV_DispatchThreadID;\n};\n\n[numthreads(8, 1, 1)]\nvoid CSmain(CSParam param)\n{\n    uint bone_id = param.DispatchThreadID.x;\n    \n    uint bone_count = 0;\n    uint frame_count = 0;\n    uint level_count = 0;\n    SkinnedMatrics.GetDimensions(0, bone_count, frame_count, level_count);\n    bone_count /= 3;\n        \n    if (bone_id >= bone_count)\n    {\n        return;\n    }\n    \n    uint frame0 = min(uint(UpdateInfo.time * 30.f), frame_count - 1);\n    uint frame1 = min(uint(UpdateInfo.time * 30.f) + 1, frame_count - 1);\n        \n    float4x4 mat0 = float4x4(\n        SkinnedMatrics.Load(int3(bone_id * 3 + 0, frame0, 0)),\n        SkinnedMatrics.Load(int3(bone_id * 3 + 1, frame0, 0)),\n        SkinnedMatrics.Load(int3(bone_id * 3 + 2, frame0, 0)),\n        float4(0, 0, 0, 1));\n\n    float4x4 mat1 = float4x4(\n        SkinnedMatrics.Load(int3(bone_id * 3 + 0, frame1, 0)),\n        SkinnedMatrics.Load(int3(bone_id * 3 + 1, frame1, 0)),\n        SkinnedMatrics.Load(int3(bone_id * 3 + 2, frame1, 0)),\n        float4(0, 0, 0, 1));\n    \n    BoneMatrics[bone_id] = lerp(mat0, mat1, frac(UpdateInfo.time * 30.f));\n}"
  },
  {
    "path": "Source/xmake.lua",
    "content": "includes(\"External\")\nincludes(\"Runtime\")\nincludes(\"Plugin\")\n\ntarget(\"Editor\")\n    if is_mode(\"debug\") then\n        add_defines(\"DEBUG\")\n        set_kind(\"shared\")\n        add_rules(\"utils.symbols.export_all\", {export_classes = true})\n    elseif is_mode(\"release\", \"releasedbg\") then\n        set_kind(\"static\")\n    end\n\n    set_pcxxheader(\"Editor/Precompile.hpp\")\n\n    add_files(\"Editor/**.cpp\")\n    add_headerfiles(\"Editor/**.hpp\")\n    add_includedirs(\"./\", {public  = true})\n    add_deps(\"Core\", \"RHI\", \"Scene\", \"ShaderCompiler\", \"ImGui-Tools\")\n    add_packages(\"imgui\", \"imnodes\", \"nativefiledialog\")\ntarget_end()\n\ntarget(\"Shader\")\n    add_rules(\"shader\", \"empty\")\n    add_headerfiles(\"Shaders/**.hlsl\")\n    add_headerfiles(\"Shaders/**.hlsli\")\ntarget_end()\n\ntarget(\"Engine\")\n    set_kind(\"binary\")\n    set_default(true,1)\n    set_rundir(\"$(projectdir)\")\n    set_pcxxheader(\"Engine/Precompile.hpp\")\n\n    add_files(\"Engine/**.cpp\")\n    add_headerfiles(\"Engine/**.hpp\")\n    add_includedirs(\"Engine\", {public  = true})\n    add_deps(\"Core\", \"RHI\", \"Scene\", \"Geometry\", \"Resource\", \"Renderer\", \"Editor\", \"Plugin\")\ntarget_end()"
  },
  {
    "path": "imgui.ini",
    "content": "[Window][DockSpace]\nPos=0,24\nSize=1440,786\nCollapsed=0\n\n[Window][Debug##Default]\nPos=60,60\nSize=400,400\nCollapsed=0\n\n[Window][Animation Editor]\nPos=196,24\nSize=785,515\nCollapsed=0\nDockId=0x00000003,4\n\n[Window][Hierarchy]\nPos=0,24\nSize=194,786\nCollapsed=0\nDockId=0x00000005,0\n\n[Window][Inspector]\nPos=983,24\nSize=457,786\nCollapsed=0\nDockId=0x00000002,0\n\n[Window][Material Editor]\nPos=196,24\nSize=785,515\nCollapsed=0\nDockId=0x00000003,2\n\n[Window][Mesh Editor]\nPos=196,24\nSize=785,515\nCollapsed=0\nDockId=0x00000003,3\n\n[Window][Render Graph Editor]\nPos=196,24\nSize=785,515\nCollapsed=0\nDockId=0x00000003,1\n\n[Window][Resource Browser]\nPos=196,541\nSize=785,269\nCollapsed=0\nDockId=0x00000004,0\n\n[Window][Scene View]\nPos=196,24\nSize=785,515\nCollapsed=0\nDockId=0x00000003,0\n\n[Window][sync_test]\nPos=453,751\nSize=79,36\nCollapsed=0\n\n[Window][visibility]\nPos=558,397\nSize=68,36\nCollapsed=0\n\n[Window][pathtracing]\nPos=475,597\nSize=90,36\nCollapsed=0\n\n[Window][test]\nPos=665,548\nSize=41,36\nCollapsed=0\n\n[Window][2]\nPos=498,591\nSize=25,36\nCollapsed=0\n\n[Window][3]\nPos=711,601\nSize=25,36\nCollapsed=0\n\n[Window][1]\nPos=475,613\nSize=25,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_SciFiHelmet_glTF_SciFiHelmet.gltf.mesh.0]\nPos=546,973\nSize=581,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_plane.gltf.mesh.0]\nPos=634,986\nSize=366,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_projects_bin_Debug-windows-x86_64_App_assets_skybox_newport_loft.hdr]\nPos=489,935\nSize=713,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_SciFiHelmet_glTF_SciFiHelmet_Normal.png]\nPos=616,768\nSize=542,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_plane.gltf]\nPos=698,658\nSize=313,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_shader_ball.glb.mesh.0]\nPos=729,969\nSize=406,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_shader_ball.glb]\nPos=812,656\nSize=352,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_SciFiHelmet_glTF_SciFiHelmet.gltf]\nPos=548,641\nSize=527,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_sphere.glb]\nSize=322,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_sphere.glb.mesh.0]\nPos=885,984\nSize=375,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_SciFiHelmet_glTF_SciFiHelmet_MetallicRoughness.png]\nSize=666,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_rusted_iron_roughness.png]\nPos=838,821\nSize=588,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_rusted_iron_albedo.png]\nPos=542,509\nSize=563,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_rusted_iron_normal.png]\nPos=758,815\nSize=564,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_SciFiHelmet_glTF_SciFiHelmet_BaseColor.png]\nPos=692,681\nSize=610,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_wall_normal.png]\nPos=472,677\nSize=516,36\nCollapsed=0\n\n[Window][4]\nPos=828,603\nSize=25,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_wall_albedo.png]\nPos=332,659\nSize=515,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_cg_normalmap__.jpg]\nPos=870,698\nSize=516,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_cg_normalmap.jpg]\nPos=616,715\nSize=501,36\nCollapsed=0\n\n[Window][5]\nPos=921,544\nSize=25,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb]\nPos=638,603\nSize=347,36\nCollapsed=0\n\n[Window][default]\nPos=818,637\nSize=61,36\nCollapsed=0\n\n[Window][red]\nPos=734,822\nSize=38,36\nCollapsed=0\n\n[Window][green]\nPos=1072,729\nSize=55,36\nCollapsed=0\n\n[Window][sphere]\nPos=1243,994\nSize=62,36\nCollapsed=0\n\n[Window][conell_box]\nPos=605,843\nSize=87,36\nCollapsed=0\n\n[Window][diffuse]\nPos=885,887\nSize=60,36\nCollapsed=0\n\n[Window][Dieletric]\nPos=949,632\nSize=70,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.6]\nPos=456,631\nSize=400,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.4]\nPos=608,654\nSize=400,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.1]\nPos=855,959\nSize=16,16\nCollapsed=0\n\n[Window][conductor]\nPos=634,868\nSize=82,36\nCollapsed=0\n\n[Window][thindielectric]\nPos=1037,603\nSize=99,36\nCollapsed=0\n\n[Window][Mix]\nPos=1044,737\nSize=40,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_wall_roughness.png]\nPos=571,678\nSize=540,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_pbr_rusted_iron_metallic.png]\nPos=1257,699\nSize=569,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.0]\nPos=700,959\nSize=400,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_BoomBox_glTF_BoomBox.gltf.mesh.0]\nPos=441,974\nSize=549,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_BoomBox_glTF_BoomBox_baseColor.png]\nPos=437,728\nSize=576,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_BoomBox_glTF_BoomBox_occlusionRoughnessMetallic.png]\nPos=537,725\nSize=697,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_BoomBox_glTF_BoomBox_normal.png]\nPos=577,774\nSize=554,36\nCollapsed=0\n\n[Window][cube]\nPos=1352,950\nSize=49,36\nCollapsed=0\n\n[Window][material]\nPos=669,640\nSize=70,36\nCollapsed=0\n\n[Window][dielectric]\nPos=765,879\nSize=75,36\nCollapsed=0\n\n[Window][mix]\nPos=1118,882\nSize=40,36\nCollapsed=0\n\n[Window][thin_dielectric]\nPos=727,978\nSize=107,36\nCollapsed=0\n\n[Window][E__Workspace_glTF-Sample-Models_2.0_Sponza_glTF_8006627369776289000.png]\nPos=1247,955\nSize=580,36\nCollapsed=0\n\n[Window][mask]\nPos=997,884\nSize=52,36\nCollapsed=0\n\n[Window][principled]\nPos=1242,877\nSize=80,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.3]\nPos=1100,992\nSize=400,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.5]\nPos=886,707\nSize=400,36\nCollapsed=0\n\n[Window][E__Workspace_Ilum_Asset_Model_conell_box.glb.mesh.2]\nPos=1109,710\nSize=400,36\nCollapsed=0\n\n[Window][checkboard]\nPos=521,874\nSize=94,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_checkboard.png]\nPos=1004,743\nSize=485,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_bricks2.jpg]\nPos=611,849\nSize=450,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_bricks2_normal.jpg]\nPos=771,814\nSize=503,36\nCollapsed=0\n\n[Window][E__Workspace_Chaf-Engine_src_App_assets_texture_green_checkerboard.png]\nPos=1114,724\nSize=544,36\nCollapsed=0\n\n[Window][rust_iron]\nPos=643,981\nSize=74,36\nCollapsed=0\n\n[Window][rough_conductor]\nPos=1272,845\nSize=128,36\nCollapsed=0\n\n[Window][rough_dielectric]\nPos=524,983\nSize=121,36\nCollapsed=0\n\n[Docking][Data]\nDockSpace       ID=0x3FC20BEE Window=0x9A404470 Pos=87,145 Size=1440,786 Split=X Selected=0x08AA43A5\n  DockNode      ID=0x00000001 Parent=0x3FC20BEE SizeRef=1461,1022 Split=X\n    DockNode    ID=0x00000005 Parent=0x00000001 SizeRef=194,786 Selected=0x29EABFBD\n    DockNode    ID=0x00000006 Parent=0x00000001 SizeRef=1244,786 Split=Y Selected=0x08AA43A5\n      DockNode  ID=0x00000003 Parent=0x00000006 SizeRef=1265,751 CentralNode=1 Selected=0x08AA43A5\n      DockNode  ID=0x00000004 Parent=0x00000006 SizeRef=1265,269 Selected=0xD4E0DDF3\n  DockNode      ID=0x00000002 Parent=0x3FC20BEE SizeRef=457,1022 Selected=0xE7039252\n\n"
  },
  {
    "path": "xmake/module.lua",
    "content": "function add_runtime_moulde(name, group, pcxxheader, deps, pkgs)\n    target(name)\n        if is_mode(\"debug\") then\n            add_defines(\"DEBUG\")\n            set_kind(\"shared\")\n            add_rules(\"utils.symbols.export_all\", {export_classes = true})\n        elseif is_mode(\"release\", \"releasedbg\") then\n            set_kind(\"static\")\n        end\n\n        if pcxxheader then\n            set_pcxxheader(string.format(\"%s/Public/%s/Precompile.hpp\", name, name))\n        end\n\n        add_files(string.format(\"%s/Private/**.cpp\", name))\n        add_headerfiles(string.format(\"%s/Public/**.hpp\", name))\n        add_includedirs(string.format(\"%s/Public/%s\", name, name))\n        add_includedirs(string.format(\"%s/Public\", name), {public  = true})\n        add_deps(deps)\n        add_packages(pkgs)\n\n        set_group(group)\n    target_end()\nend"
  },
  {
    "path": "xmake/plugin.lua",
    "content": "includes(\"rule.lua\")\n\ntarget(\"Plugin\")\n    add_rules(\"empty\")\n    set_group(\"Plugin\")\ntarget_end()\n\nrule(\"plugin\")\n    on_load(function (target)\n        if is_mode(\"debug\") then\n            target:add(\"defines\", \"DEBUG\")\n        end\n    end)\n    \n    after_build(function (target)\n        local source_path = path.join(target:targetdir(), string.format(\"%s.dll\", target:name()))\n        local target_path = path.join(\"$(projectdir)\", \"shared\", string.sub(target:name(), 0, string.find(target:name(), \"%.\") - 1), string.format(\"%s.dll\", target:name()))\n        os.cp(source_path, target_path)\n    end)\n"
  },
  {
    "path": "xmake/rule.lua",
    "content": "rule(\"empty\")\n    on_load(function (target)\n        if is_mode(\"debug\") then\n            target:add(\"defines\", \"DEBUG\")\n        end\n    end)\n\n    on_build(function (target, sourcefile)\n    end)"
  },
  {
    "path": "xmake/shader.lua",
    "content": "includes(\"rule.lua\")\n\nrule(\"shader\")\n    set_extensions(\".hlsli\", \".hlsl\")\n    on_load(function (target)\n        \n    end)"
  },
  {
    "path": "xmake.lua",
    "content": "set_project(\"Ilum\")\nset_version(\"0.0.1\")\n\nset_xmakever(\"2.7.5\")\n\nset_warnings(\"all\")\nset_languages(\"c++17\")\n\nadd_rules(\"mode.debug\", \"mode.release\", \"mode.releasedbg\")\n\nset_runtimes(\"MD\")\nadd_defines(\"NOMINMAX\")\nset_warnings(\"all\")\n\nincludes(\"xmake/module.lua\")\nincludes(\"xmake/plugin.lua\")\nincludes(\"xmake/shader.lua\")\nincludes(\"Source\")\n"
  }
]